REST một cách hiệu quả để tạo nhiều mục trong một yêu cầu


122

Tôi đang làm việc trên một chương trình máy chủ khách hàng nhỏ để thu thập đơn đặt hàng. Tôi muốn làm điều này theo cách "REST (ful)".

Điều tôi muốn làm là:

Thu thập tất cả các đơn đặt hàng (sản phẩm và số lượng) và gửi đơn đặt hàng hoàn chỉnh đến máy chủ

Hiện tại, tôi thấy có hai tùy chọn để thực hiện việc này:

  1. Gửi từng dòng đặt hàng đến máy chủ: POST qty và product_id

Tôi thực sự không muốn làm điều này vì tôi muốn giới hạn số lượng yêu cầu đến máy chủ nên tùy chọn 2:

  1. Thu thập tất cả các dòng đặt hàng và gửi chúng đến máy chủ cùng một lúc.

Tôi nên thực hiện tùy chọn 2 như thế nào? Tôi có một vài ý tưởng là: Gói tất cả các dòng trong một đối tượng JSON và gửi nó đến máy chủ hoặc sử dụng một mảng để đăng các dòng.

Thực hiện tùy chọn 2 có phải là một ý tưởng hay hay không, và nếu có thì tôi nên làm như thế nào.

Thực hành tốt là gì?

rest  post 

Câu trả lời:


74

Tôi tin rằng một cách đúng đắn khác để tiếp cận vấn đề này là tạo một tài nguyên khác đại diện cho bộ sưu tập tài nguyên của bạn. Ví dụ, hãy tưởng tượng rằng chúng ta có một điểm cuối giống như /api/sheep/{id}và chúng ta có thể ĐĂNG lên /api/sheepđể tạo tài nguyên cừu.

Bây giờ, nếu chúng tôi muốn hỗ trợ việc tạo số lượng lớn, chúng tôi nên xem xét một tài nguyên đàn mới tại /api/flock(hoặc /api/<your-resource>-collectionnếu bạn thiếu một cái tên có ý nghĩa hơn). Hãy nhớ rằng các tài nguyên không cần ánh xạ đến cơ sở dữ liệu hoặc mô hình ứng dụng của bạn . Đây là một quan niệm sai lầm phổ biến.

Tài nguyên là đại diện cấp cao hơn, không liên quan đến dữ liệu của bạn. Hoạt động trên một tài nguyên có thể có các tác dụng phụ đáng kể, như kích hoạt cảnh báo cho người dùng, cập nhật dữ liệu liên quan khác, bắt đầu một quy trình tồn tại lâu dài, v.v. Ví dụ: chúng tôi có thể ánh xạ hệ thống tệp hoặc thậm chí pslệnh unix dưới dạng API REST.

Tôi nghĩ rằng có thể an toàn khi cho rằng việc vận hành một tài nguyên cũng có thể có nghĩa là tạo ra một số thực thể khác như một tác dụng phụ.


Tôi đồng ý với điều này. Bạn nên tóm tắt khái niệm về tập hợp tài nguyên của mình và coi đó như một tài nguyên. Điều này sẽ cung cấp cho bạn sự linh hoạt hơn trong tương lai là tốt, khi bạn muốn bắt đầu thực hiện các hoạt động trên vv này
villy393

Đây là cách tiếp cận đúng. Điều này không phá vỡ yêu cầu Bộ sưu tập POST. Kể từ đó, nó được sử dụng để đăng một thực thể duy nhất. Gửi yêu cầu hàng loạt với một "thực thể hàng loạt riêng biệt" là cách tiếp cận đúng.
Sắp xếp

2
Tôi thích bạn đặt tên điểm cuối api rất nhiều với cừu và bầy! Với một mức độ trừu tượng, nó gần như có liên quan đến kinh thánh: "Ta có những con chiên khác, không thuộc giống này; Ta phải mang chúng đến, chúng sẽ nghe tiếng Ta; và chúng sẽ trở thành một bầy với một người chăn." Giăng 10:16.
Evgeny

1
Điều thú vị là mọi người khuyên bạn nên sử dụng dạng số nhiều (của bộ sưu tập) trong URL khi bạn muốn tạo một tài nguyên duy nhất, như sau: gửi ĐĂNG đến / api / books để tạo sách. Nhưng sau đó khi bạn muốn tạo 100 cuốn sách (trong một yêu cầu duy nhất là json), bạn sẽ đăng bộ sưu tập 100 cuốn sách lên URL nào? đó là nơi mà sự bồn chồn bắt đầu.
code4kix

@ code4kix bạn có thể sử dụng /api/book-group, /api/book-collectionhoặc một cái gì đó tương tự.
miguelcobain

46

Mặc dù các hoạt động hàng loạt (ví dụ: tạo hàng loạt) là điều cần thiết trong nhiều hệ thống, nhưng chúng không được giải quyết một cách chính thức theo kiểu kiến ​​trúc RESTful.

Tôi nhận thấy rằng ĐĂNG một bộ sưu tập như bạn đề xuất về cơ bản hoạt động, nhưng các vấn đề phát sinh khi bạn cần báo cáo lỗi theo yêu cầu như vậy. Những vấn đề như vậy sẽ tồi tệ hơn khi nhiều lỗi xảy ra vì các nguyên nhân khác nhau hoặc khi máy chủ không hỗ trợ giao dịch. Đề xuất của tôi cho bạn là nếu không có vấn đề gì về hiệu suất, chẳng hạn như khi nhà cung cấp dịch vụ ở trên mạng LAN (không phải WAN) hoặc dữ liệu tương đối nhỏ, thì việc gửi 100 yêu cầu POST đến máy chủ là điều đáng giá. Hãy đơn giản hóa, bắt đầu với các yêu cầu riêng biệt và nếu bạn gặp vấn đề về hiệu suất, hãy cố gắng tối ưu hóa.


3
Bạn đã tự mình tìm ra giải pháp cho những sai sót trong trường hợp đánh lô chưa? Trên kết nối di động, gửi 100 yêu cầu đăng bài để hiển thị đường nối trang giống như một ý tưởng tồi.
Thomas Ahle,

Tôi nối các lỗi vào một mảng, định tuyến người dùng đến trang lỗi Xung đột 419 (và trả lại lỗi đó cho máy khách) và hiển thị mảng lỗi. Xem câu trả lời của tôi bên dưới để biết thêm chi tiết.
Eric Fuller

5
Thật vô nghĩa. Câu hỏi là về việc gửi một đơn đặt hàng cho nhiều mặt hàng, như nhiều người đã nói, bạn chỉ có thể thực hiện trong thực thể của một yêu cầu POST. Cách máy chủ xử lý điều đó hoàn toàn là một điều khác. Trong trường hợp này, tôi thấy không có vấn đề gì với việc tạo đơn hàng, điền những gì bạn có thể cho đơn hàng đó và cũng điền các chi tiết không thể thực hiện được. Bằng cách đó, người dùng có thể xem đơn đặt hàng của họ và thấy rằng tất cả trừ N mặt hàng đã được thêm vào đơn hàng, nhưng một số đã hết hàng hoặc hệ thống không biết phải làm gì với. Một đơn giản nhưng ít người sử dụng lựa chọn thân thiện là để từ chối tất cả mọi thứ
thecoshman

2
@thecoshman rất nhiều thay đổi trong 3,25 năm. Bạn có thể nên đăng một câu trả lời hoàn chỉnh cho câu hỏi.
dlamblin

3
@dlamblin yeah, tôi có lẽ nên làm rất nhiều thứ ... Tôi sẽ nhận được nó tại một số sân khấu có lẽ ...
thecoshman

9

Facebook giải thích cách thực hiện điều này: https://developers.facebook.com/docs/graph-api/making-multiple-requests

Yêu cầu hàng loạt đơn giản

Lô API nhận vào một mảng các yêu cầu HTTP logic được biểu thị dưới dạng mảng JSON - mỗi yêu cầu có một phương thức (tương ứng với phương thức HTTP GET / PUT / POST / DELETE, v.v.), rel_url (phần của URL sau graph.facebook. com), mảng tiêu đề tùy chọn (tương ứng với tiêu đề HTTP) và một nội dung tùy chọn (cho các yêu cầu POST và PUT). Batch API trả về một mảng các phản hồi HTTP logic được biểu thị dưới dạng các mảng JSON - mỗi phản hồi có một mã trạng thái, một mảng tiêu đề tùy chọn và một nội dung tùy chọn (là một chuỗi được mã hóa JSON).


1
Đây là liên kết rất thú vị, giải pháp được đề xuất dường như có thể sử dụng được đối với tôi. Dù sao, tại StackOverflow, câu trả lời được ưu tiên là giải thích khái niệm về giải pháp trong phần nội dung của câu trả lời vì các liên kết có thể thay đổi hoặc biến mất.
Jan Vlcinsky

7
Đó thực sự là cách làm của Facebook, không nhất thiết phải RESTful như OP yêu cầu
0cd

Tôi nghĩ API Batch (từ Google, Facebook, v.v. - @PuneetArora) hữu ích hơn khi nhóm một số yêu cầu không liên quan lại với nhau. Tạo một yêu cầu tạo ra một mục, và sau đó nhóm tất cả các yêu cầu đó lại với nhau để gửi một bộ sưu tập các mục là "điên rồ" (Einstein). Chỉ cần tạo một yêu cầu vượt qua một bộ sưu tập các mục.
tfmontague

8

Ý tưởng của bạn có vẻ hợp lệ với tôi. Việc thực hiện là một vấn đề của sở thích của bạn. Bạn có thể sử dụng JSON hoặc chỉ các tham số cho mảng này (mảng "order_lines []") và làm

POST /orders

Vì bạn sẽ tạo ra nhiều tài nguyên hơn cùng một lúc trong một hành động (thứ tự và các dòng của nó), điều quan trọng là phải xác thực từng thứ và chỉ lưu chúng nếu tất cả chúng đều vượt qua xác thực, tức là. bạn nên làm điều đó trong một giao dịch.



5

Tôi thực sự đã vật lộn với điều này gần đây và đây là những gì tôi đang hướng tới.

Nếu POST thêm nhiều tài nguyên thành công, hãy trả về 200 OK (Tôi đang xem xét là 201, nhưng cuối cùng người dùng không truy cập vào tài nguyên đã được tạo) cùng với một trang hiển thị tất cả các tài nguyên đã được thêm vào, ở dạng đã đọc -chỉ hoặc thời trang có thể chỉnh sửa. Ví dụ: người dùng có thể chọn và ĐĂNG nhiều hình ảnh lên thư viện bằng cách sử dụng biểu mẫu chỉ bao gồm một đầu vào tệp duy nhất. Nếu yêu cầu POST thành công toàn bộ, người dùng sẽ được cung cấp một tập hợp các biểu mẫu cho mỗi biểu diễn tài nguyên hình ảnh được tạo cho phép họ chỉ định thêm chi tiết về từng biểu mẫu (tên, mô tả, v.v.).

Trong trường hợp một hoặc nhiều tài nguyên không được tạo, trình xử lý POST sẽ hủy bỏ tất cả quá trình xử lý và nối từng thông báo lỗi riêng lẻ vào một mảng. Sau đó, Xung đột 419 được trả lại và người dùng được chuyển đến trang lỗi Xung đột 419 trình bày nội dung của mảng lỗi, cũng như cách quay lại biểu mẫu đã được gửi.


-2

Bạn sẽ không muốn gửi tiêu đề HTTP cho 100 dòng đặt hàng. Bạn không muốn tạo thêm bất kỳ yêu cầu nào hơn mức cần thiết.

Gửi toàn bộ đơn đặt hàng trong một đối tượng JSON đến máy chủ, tới: máy chủ / đơn hàng hoặc máy chủ / đơn hàng / mới. Trả lại thứ gì đó trỏ đến: server / order / order_id

Cũng nên cân nhắc sử dụng CREATE PUT thay vì POST


Tôi cho rằng anh ấy đề cập đến phương thức HTTP POST. Không có cái gọi là phương thức CREATE HTTP.
Milan Novota

Có phải không? Chờ đã, không có. Đã có PUT thay thế.
Vui vẻ

22
Tại sao bạn lại sử dụng PUT để tạo nội dung? Đây chính xác là phương thức HTTP POST dùng để làm gì.
thecoshman

8
Bạn sử dụng PUT để tạo tài nguyên khi bạn muốn máy khách chỉ định URI của tài nguyên, như trong webdav. Tôi không đồng ý với việc sử dụng PUT của người đăng, nhưng nó có một vị trí trong việc tạo ra tài nguyên, mặc dù nơi đó có thể bị giới hạn về phạm vi.
user602525

2
Lưu ý: Việc ĐĂNG một thực thể sẽ dẫn đến việc thực thể trở thành cấp dưới của tài nguyên được giải quyết trong yêu cầu và không phải là đơn vị. PUT thay thế thực thể tại địa chỉ và là idmpotent. Tính lý tưởng (từ?) Là một kỳ vọng quan trọng đối với người tiêu dùng.
Luke Puplett,
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.