Cách xây dựng API REST lấy một mảng id cho các tài nguyên


103

Tôi đang xây dựng một API REST cho dự án của mình. API để nhận INFO của một người dùng nhất định là:

api.com/users/[USER-ID]

Tôi cũng muốn cho phép khách hàng chuyển vào danh sách ID người dùng. Làm cách nào tôi có thể xây dựng API để nó RESTful và đưa vào danh sách ID người dùng?


Câu trả lời chung chung nhất được đưa ra bởi @Shuja, vì các câu trả lời khác từ người đưa thư không hoạt động và phụ thuộc vào phần phụ trợ cơ sở dữ liệu. Tuy nhiên, bạn có thể có một điểm cuối API để yêu cầu nhiều id.
Eswar

Câu trả lời:


97

Nếu bạn đang chuyển tất cả các tham số của mình trên URL, thì có lẽ các giá trị được phân tách bằng dấu phẩy sẽ là lựa chọn tốt nhất. Sau đó, bạn sẽ có một mẫu URL như sau:

api.com/users?id=id1,id2,id3,id4,id5

7
@uclajatt, REST là một mô hình kiến ​​trúc chứ không phải một giao thức và nếu bạn nghiên cứu các API REST chính hiện nay, bạn sẽ thấy rằng có nhiều cách để triển khai nó. Cách tiếp cận mà tôi đang đề xuất có lẽ là một trong những cách gần nhất với khái niệm vì nó hoàn thành tất cả các ràng buộc được mô tả ở đây: en.wikipedia.org/wiki/… . Bạn sẽ chỉ sử dụng CSV để đại diện cho các mảng trong các yêu cầu, trong khi các phản hồi dịch vụ phải được tuần tự hóa bằng cách sử dụng XML hoặc JSON. Có bất kỳ lý do cụ thể nào khiến bạn không coi cách tiếp cận của tôi là REST không?
Florin Dumitrescu

10
Tại sao không phải cái này? api.com/users?id=id1&id=id2&id=id3&id=id4&id=id5
senfo

7
@senfo, tôi thích id = id1, id2, id3 vì nó làm cho URI ngắn hơn và dễ đọc hơn (ví dụ như con người, trong thao tác gỡ lỗi). Các thông số cá nhân cho mỗi giá trị sẽ làm cho URI đặc biệt là khó khăn hơn để làm theo nếu có các thông số khác giữa id: api.com/users?id=id1&id=id2&joined-after=2013-01-01&id=id3
Florin Dumitrescu

12
Tuy nhiên, hầu hết các máy chủ web đều hỗ trợ độ dài URL khoảng 2.000 byte. Làm cách nào để hỗ trợ API của tôi lên đến 5.000 id?
nicky_zs

6
@senfo Trong các URL như vậy …?id=1&id=2&id=3, không có gì đảm bảo rằng các tham số truy vấn trùng lặp sẽ được kết hợp thành một mảng. Với chuỗi truy vấn trên, PHP sẽ cho bạn biết rằng idbằng [1, 2, 3], nhưng Ruby on Rails cho bạn biết nó bằng 3và các khung công tác khác cũng có thể hoạt động khác, ví dụ: nói idbằng 1. Các URL như thế …?id=1,2,3này tránh tiềm ẩn sự nhầm lẫn.
Rory O'Kane

33
 api.com/users?id=id1,id2,id3,id4,id5
 api.com/users?ids[]=id1&ids[]=id2&ids[]=id3&ids[]=id4&ids[]=id5

IMO, các cuộc gọi trên có vẻ không RESTful, tuy nhiên đây là cách giải quyết nhanh chóng và hiệu quả (y). Nhưng độ dài của URL bị giới hạn bởi máy chủ web, ví dụ như tomcat .

RESTful nỗ lực:

POST http://example.com/api/batchtask

   [
    {
      method : "GET",
      headers : [..],
      url : "/users/id1"
    },
    {
      method : "GET",
      headers : [..],
      url : "/users/id2"
    }
   ]

Máy chủ sẽ trả lời URI của tài nguyên nhiệm vụ lô mới được tạo .

201 Created
Location: "http://example.com/api/batchtask/1254"

Giờ đây, khách hàng có thể tìm nạp phản hồi hàng loạt hoặc tiến trình tác vụ bằng cách bỏ phiếu

GET http://example.com/api/batchtask/1254


Đây là cách những người khác đã cố gắng giải quyết vấn đề này:


7
Yêu cầu POST để nhận nhiều kết quả không phải là RESTful. Của bạn hiển thị ví dụ tạo một tài nguyên, nơi mà nó là thích hợp để POST, nhưng đó là một trường hợp hoàn toàn khác nhau cho câu hỏi ban đầu
Anentropic

2
Tạo tài nguyên tạm thời là RESTful, phải không? Và tôi đang nhận tài nguyên bằng cách sử dụng GET, lại là RESTful.
Nilesh

vâng, nhưng không ai trong số đó là trong câu hỏi ban đầu, mà chỉ hỏi về việc nhận thông tin cho nhiều id người dùng
Anentropic

1
Cảm ơn @Anentropic đã chỉ ra. Tôi đọc lại câu hỏi nó hỏi Làm thế nào để xây dựng một REST API lấy một mảng id cho các tài nguyên? và tôi đồng ý, câu trả lời của tôi là khác. Xin lỗi vì không hiểu được ý của bạn.
Nilesh

Tôi thích câu trả lời này vì cách RESTful để có được nhiều người dùng là thông qua cơ chế này.
Shane Courtrille

20

Tôi tìm thấy một cách khác để làm điều tương tự bằng cách sử dụng @PathParam. Đây là mẫu mã.

@GET
@Path("data/xml/{Ids}")
@Produces("application/xml")
public Object getData(@PathParam("zrssIds") String Ids)
{
  System.out.println("zrssIds = " + Ids);
  //Here you need to use String tokenizer to make the array from the string.
}

Gọi cho dịch vụ bằng cách sử dụng url sau.

http://localhost:8080/MyServices/resources/cm/data/xml/12,13,56,76

Ở đâu

http://localhost:8080/[War File Name]/[Servlet Mapping]/[Class Path]/data/xml/12,13,56,76

5
Tôi thích cái này vì GET nhất quán. Bạn có thể sử dụng một hoặc nhiều số trong ví dụ này. Và nó không thực sự là một tìm kiếm (tham số), vì bạn đang cung cấp cho mặt sau các id chính xác mà bạn muốn.
markthegrea 12/09/12

1
Tôi thấy câu trả lời được ủng hộ nhiều nhất không hoạt động và câu trả lời của bạn có lẽ là câu trả lời chung chung nhất. Nên được chấp nhận là câu trả lời.
Eswar

18

Tôi thích cách tiếp cận này nhiều nhất: -

    api.com/users?id=id1,id2,id3,id4,id5

Cách chính xác là

    api.com/users?ids[]=id1&ids[]=id2&ids[]=id3&ids[]=id4&ids[]=id5

hoặc là

    api.com/users?ids=id1&ids=id2&ids=id3&ids=id4&ids=id5

Đây là cách giá đỡ thực hiện nó. Đây là cách php thực hiện nó. Đây là cách nút cũng thực hiện nó ...


19
Tôi không chắc rằng việc tham khảo các tiêu chuẩn PHP như một nguyên tắc để tuân theo là lời khuyên tốt nhất. eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design
trebor

Đây không phải là cách Flask làm.
jscul

0

Bạn có thể xây dựng một API Rest hoặc một dự án còn lại bằng cách sử dụng ASP.NET MVC và trả về dữ liệu dưới dạng JSON. Một chức năng điều khiển ví dụ sẽ là:

        public JsonpResult GetUsers(string userIds)
        {
           var values = JsonConvert.DeserializeObject<List<int>>(userIds);

            var users = _userRepository.GetAllUsersByIds(userIds);

            var collection = users.Select(user => new { id = user.Id, fullname = user.FirstName +" "+ user.LastName });
            var result = new { users = collection };

            return this.Jsonp(result);
        }
        public IQueryable<User> GetAllUsersByIds(List<int> ids)
        {
            return _db.Users.Where(c=> ids.Contains(c.Id));
        }

Sau đó, bạn chỉ cần gọi hàm GetUsers thông qua một hàm AJAX thông thường cung cấp mảng Id (trong trường hợp này tôi đang sử dụng jQuery stringify để gửi mảng dưới dạng chuỗi và phi vật chất hóa nó trở lại trong bộ điều khiển nhưng bạn chỉ có thể gửi mảng int và nhận nó như một mảng int trong bộ điều khiển). Tôi đã xây dựng toàn bộ API Restful bằng cách sử dụng ASP.NET MVC trả về dữ liệu dưới dạng json tên miền chéo và có thể được sử dụng từ bất kỳ ứng dụng nào. Tất nhiên nếu bạn có thể sử dụng ASP.NET MVC.

function GetUsers()
    {
           var link = '<%= ResolveUrl("~")%>users?callback=?';
           var userIds = [];
            $('#multiselect :selected').each(function (i, selected) {
                userIds[i] = $(selected).val();
            });

            $.ajax({
                url: link,
                traditional: true,
                data: { 'userIds': JSON.stringify(userIds) },
                dataType: "jsonp",
                jsonpCallback: "refreshUsers"
            });
    }

3
Xin lỗi, tôi không hỏi cách triển khai API. Tôi chỉ hỏi về cách xây dựng API URI để khách hàng có thể truy cập thông tin về một loạt người dùng. Tôi có thể chuyển id thông qua các tham số truy vấn, nhưng tôi tin rằng điều đó sẽ không quá mệt mỏi.
uclajatt

@uclajatt Tại sao bạn cho rằng đó không phải là RESTful?
Darrel Miller

1
Tôi tin rằng việc chuyển id hoặc bất kỳ giá trị nào khác thông qua các tham số truy vấn thực sự là một cách tiếp cận tương tác với hệ thống hiệu quả. Bạn xây dựng bạn như thế nào thì tùy thuộc vào bạn. Là người dùng / tất cả, người dùng / mảng, mảng / người dùng hoặc bất kỳ quy ước đặt tên nào khác mà bạn cảm thấy hợp lý. Cân nhắc cách thức hoạt động của khuôn khổ MVC, rất dễ sử dụng nó để xây dựng một API hoàn chỉnh vì bạn có thể tổ chức và xây dựng cho mình Uris ngay khi bạn cần. Khi bạn có Uris, bạn có thể chuyển cho mình các tham số bằng AJAX dưới dạng một chuỗi, hoặc dưới dạng nhiều giá trị nếu bạn đang sử dụng biểu mẫu và thực hiện đăng hành động MVC.
Vasile Laur

1
@uclajatt Thats hai lần bạn đã được hỏi trên bài đăng này tại sao bạn nghĩ rằng việc chuyển một danh sách được phân tách bằng dấu phẩy trong một tham số truy vấn không phải là RESTful và bạn thậm chí không buồn trả lời nó, hãy để một mình chấp nhận bất kỳ giải pháp rất hợp lý nào !? ! Không mát mẻ.
samis
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.