Hoạt động không CRUD trong một dịch vụ RESTful


106

Cách "RESTful" để thêm các hoạt động không phải CRUD vào dịch vụ RESTful là gì? Giả sử tôi có một dịch vụ cho phép CRUD truy cập vào các bản ghi như sau:

GET /api/car/123           <- Returns information for the Car object with ID 123
POST /api/car              <- Creates a new car (with properties in the request)
PUT /api/car/123           <- Updates car 123 (with properties in the request)
DELETE /api/car/123        <- Deletes car 123    
POST /api/car/123/wheel/   <- Creates a wheel and associates it to car 123

Nếu tôi muốn thay đổi màu của chiếc xe, tôi chỉ cần POST /api/car/123thêm một biến POST cho màu mới.

Nhưng giả sử tôi muốn mua một chiếc ô tô và thao tác đó phức tạp hơn là chỉ cập nhật tài sản “ô tô đã sở hữu” của bản ghi "người dùng". Nó có RESTful chỉ đơn giản là làm một cái gì đó như POST /api/car/123/purchase, trong đó "mua" về cơ bản là một tên phương thức? Hay tôi nên sử dụng một động từ HTTP tùy chỉnh, như PURCHASEthay vì POST?

Hay các hoạt động không phải CRUD hoàn toàn nằm ngoài phạm vi của REST?


5
Nếu bạn đang thay đổi màu sắc của một chiếc ô tô, sẽ tốt hơn nếu bạn sử dụng PATCH /api/car/123và gửi thông số màu HOẶC sử dụng PUT /api/car/123và gửi toàn bộ đối tượng ô tô. POST sẽ suy ra rằng bạn đang tạo một chiếc xe mới và có lẽ không bao giờ nên bao gồm một id vào cuối URL
RonnyKnoxville

Câu trả lời:


65

Hãy nghĩ về việc mua hàng như một thực thể kinh doanh hoặc một tài nguyên trong từ điển RESTful. Nói như vậy, việc mua hàng thực sự là tạo ra một nguồn lực mới. Vì thế:

POST /api/purchase

sẽ đặt hàng mới. Các chi tiết (người dùng, ô tô, v.v.) phải được tham chiếu bằng id (hoặc URI) bên trong nội dung được gửi đến địa chỉ này.

Không có vấn đề gì khi đặt mua một chiếc xe không chỉ là một INSERT đơn giản trong cơ sở dữ liệu. Trên thực tế, REST không phải là để hiển thị các bảng cơ sở dữ liệu của bạn dưới dạng các hoạt động CRUD. Từ quan điểm logic, bạn đang tạo một đơn đặt hàng (mua hàng), nhưng phía máy chủ có thể tự do thực hiện nhiều bước xử lý tùy thích.

Bạn thậm chí có thể lạm dụng giao thức HTTP hơn nữa. Sử dụng Locationtiêu đề để trả về liên kết đến đơn đặt hàng mới được tạo, cẩn thận chọn mã phản hồi HTTP để thông báo cho người dùng về sự cố (phía máy chủ hoặc phía máy khách), v.v.


3
REST là tất cả về thao tác trạng thái tài nguyên và mọi hoạt động kinh doanh phải được ánh xạ đến hoạt động CRUD của trạng thái. Nếu bạn cần ngữ nghĩa hoạt động kinh doanh khó , bạn sẽ phải sử dụng SOAP (SOAP thực chất là truyền thông báo, nhưng thường được tổ chức trong các hoạt động phản hồi yêu cầu).
Tomasz Nurkiewicz

23
Thiết kế "mua dưới dạng tài nguyên" trông gọn gàng. Điều gì sẽ xảy ra nếu tài nguyên là "bia" .. và tôi muốn máy chủ uống nó .. (nó là dành cho tôi, tôi chắc chắn sẽ NHẬN được nó;)) .. chúng ta có nên coi "hành động uống" là tài nguyên không ?! .. hay là “uống bia ôm”, hoạt động kinh doanh vất vả ?! Nghiêm trọng hơn, là thiết kế RESTful về xem xét hành động như nguồn lực ..?!
Myobis

2
Làm thế nào bạn sẽ hiển thị "phê duyệt đơn đặt hàng" thông qua một dịch vụ REST? Tôi nghĩ @TomaszNurkiewicz đúng ở chỗ bất cứ thứ gì không thể được thực hiện gọn gàng theo cách CRUD sẽ cần ngữ nghĩa hoạt động do SOAP cung cấp. Trừ khi "chấp thuận đơn đặt hàng" là một mô hình / thực thể của riêng nó. Ví dụ: POST / po-accept (với chi tiết PO trong yêu cầu).
mydoghasworms

2
Từ quan điểm của một khách hàng REST, "chấp thuận đơn đặt hàng" chỉ nên là một cập nhật khác của đơn đặt hàng. Ví dụ: thay đổi "Đã phê duyệt" thành "đúng" và gửi bản cập nhật đến máy chủ. Máy chủ có thể sẽ cần thực hiện một loạt các kiểm tra và có thể nó sẽ cần cập nhật / tạo một loạt các tài nguyên khác. Nhưng đó là vấn đề của máy chủ và không nên hiển thị cho máy khách.
AVee

2
@antinome: "Giả sử khách hàng biết một số điều này", nếu đó là trường hợp bạn không thực hiện REST (mặc dù nó vẫn có thể hợp lệ, phần mềm hợp lý!). REST được thiết kế để có thể tạo ra các máy khách không biết điều đó, để tạo các máy khách vẫn hoạt động nếu hành vi của máy chủ thay đổi. Những gì bạn đang cố gắng làm là RPC cổ điển, bạn cần phải xem lại cách tiếp cận của mình để nó phù hợp với REST hoặc chấp nhận rằng bạn đang làm RPC và sử dụng một giao thức dành cho RPC như SOAP. REST rất cố gắng để không phải là RPC, vì vậy nó sẽ không bao giờ phù hợp khi bạn muốn / cần RPC.
AVee

15

Cách RESTful như tôi hiểu là bạn không cần các động từ HTTP mới, có một danh từ ở đâu đó sẽ có nghĩa là những gì bạn cần làm.

Mua một chiếc xe hơi? Chà không phải vậy

POST /api/order

2
PUT không được sử dụng để cập nhật tài nguyên vì nó không có ích? Điều này có nghĩa là bạn có thể gọi nó bao nhiêu lần tùy thích, nhưng chỉ cuộc gọi đầu tiên / cuối cùng là quan trọng. Mặt khác, POST được sử dụng để tạo tài nguyên và gọi nó hai lần thực sự sẽ tạo ra hai.
Tomasz Nurkiewicz,

1
@Tomas, vâng, lỗi đánh máy. Tuy nhiên, nguyên tắc rất quan trọng, chúng ta đang giải quyết một thứ mới, một thứ tự, không cần động từ mới.
djna

5

Những gì bạn thực sự đang làm là tạo một đơn đặt hàng. Vì vậy, hãy thêm một tài nguyên khác để đặt hàng và đăng bài và đặt ở đó trong quá trình đặt hàng.

Hãy suy nghĩ về nguồn lực hơn là các cuộc gọi phương thức.

Để hoàn tất đơn đặt hàng, bạn có thể POST / api / order // hoàn thành hoặc thứ gì đó tương tự.


3

Tôi cảm thấy REST API giúp ích nhiều hơn theo nhiều cách hơn là chỉ cung cấp ngữ nghĩa. Vì vậy, không thể chọn kiểu RPC chỉ vì một số lời gọi dường như có ý nghĩa hơn trong kiểu hoạt động RPC. Ví dụ là api bản đồ google để tìm chỉ đường giữa hai địa điểm. Có vẻ như sau: http://maps.googleapis.com/maps/api/directions/json?origin=Jakkur&destination=Hebbal

Họ có thể gọi nó là "findDirections" (động từ) và coi nó như một phép toán. Thay vào đó, họ thực hiện "hướng" (danh từ) như một tài nguyên và coi việc tìm kiếm chỉ đường như một truy vấn về tài nguyên chỉ đường (Mặc dù trong nội bộ không thể có tài nguyên thực sự được gọi là hướng và nó có thể được thực hiện theo logic nghiệp vụ để tìm chỉ đường dựa trên các tham số).


Đó là một ví dụ tồi. Trong trường hợp này, các hướng (tất cả các hướng có thể có, vô số hướng) là tài nguyên và các tham số chỉ là bộ lọc. Nhưng bạn không thể làm một "mua" với điều này, như các bộ lọc chỉ có ý nghĩa đối với hoạt động get và đưa đơn đặt hàng hoặc hủy nó là hoạt động mà thay đổi dữ liệu
Tseng

2
giao dịch mua sẽ được ĐĂNG đến / đơn đặt hàng với một json trong nội dung để cho biết đơn đặt hàng đã được tạo. hủy sẽ là PUT đến / đặt hàng với một json thực hiện thay đổi trạng thái đơn hàng để cho biết đây là một bản cập nhật không cần thiết. Tôi vẫn phải chạy vào một hoạt động không thể được thể hiện trong một định dạng tài nguyên. Vì vậy, sẽ rất muốn xem một ví dụ như vậy
Maruthi
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.