Để bao gồm ID tài nguyên trong tải trọng hoặc xuất phát từ URI


13

Thiết kế API, chúng tôi đã đưa ra câu hỏi liệu tải trọng PUT có nên chứa ID của tài nguyên đang được cập nhật hay không.

Đây là những gì chúng tôi hiện đang có:

PUT /users/123 Payload: {name: "Adrian"}

Mã lộ trình của chúng tôi trích xuất ID từ URI và tiếp tục với bản cập nhật.

Những người dùng API đầu tiên của chúng tôi đang đặt câu hỏi tại sao chúng tôi không cho phép ID trong tải trọng:

PUT /users/123 Payload: {id: 123, name: "Adrian"}

Lý do chúng tôi không cho phép là vì ID bị trùng lặp, trong tải trọng và URI.

Suy nghĩ thêm về điều này, chúng tôi đang ghép tài nguyên với URI.

Nếu URI không có ID, tải trọng sẽ cần được sửa đổi:

PUT /no/id/here Payload: {name: "Adrian"} < What user???

Có bất kỳ lý do để không?

Câu trả lời:


14

Bạn phải ghép cặp Mã định danh tài nguyên thống nhất với tài nguyên .

Khi REST được triển khai với HTTP, bạn sử dụng GET để lấy giá trị hiện tại của tài nguyên và PUT để đặt giá trị mới. GET không có tải trọng, do đó, tài nguyên phải được xác định bởi URI. Và PUT được thực hiện một cách hợp lý cho cùng một URI và tải trọng sẽ trông chính xác như những gì bạn muốn GET tiếp theo trả về.

Bạn có thể sử dụng POST cho các URI khác nhau, nhưng nó sẽ chỉ có ý nghĩa ít hơn vì nó sẽ không đối xứng một cách không cần thiết với GET. POST cho URI thông thường chỉ có thể có ý nghĩa trong việc tạo tài nguyên mới ( POST /users/new, tải trọng : {name: "Adrian"}, phản hồi {id: 345, name: "Adrian"}), nhưng đó không phải là idempotent và do đó nên tránh nếu bạn đang phấn đấu cho REST¹. Thay vào đó, bạn nên đặt trước ID với một cuộc gọi và sau đó sử dụng PUT để đặt ID mới; đó là khả năng chịu lỗi, bởi vì nếu yêu cầu đầu tiên không thành công, việc đặt trước ID cuối cùng có thể hết thời gian và PUTkhông có kết quả. Hoặc sử dụng UUID do khách hàng tạo.


Definition Định nghĩa của REST không nói bất cứ điều gì về tính không ổn định, vì vậy tôi thực sự không thể khẳng định đó không phải là REST nếu bạn có các hoạt động không bình thường. Điều đó không thay đổi thực tế rằng việc tuân thủ các yêu cầu tạm thời làm cho mọi thứ trở nên đáng tin cậy hơn mà không làm phức tạp chúng và do đó được khuyến nghị.


3
Theo như tôi biết thì một yêu cầu POST không nhất thiết phải là idempotent. Vì vậy, tôi thấy không có vấn đề gì với việc đăng lên /users(không cần thêm 'mới').
lex82

Cảm ơn vì đã trả lời. Tôi thấy rằng đó là một tính năng tuyệt vời để có tính tạm thời cho tất cả các yêu cầu nhưng ai nói điều này là bắt buộc đối với API REST? Chắc chắn nhiều API tự gọi là RESTful cho phép các yêu cầu POST không bình thường (đặc biệt là khi máy chủ tạo id cho tài nguyên mới). Nhưng ngay cả khi bạn áp dụng một định nghĩa rất nghiêm ngặt về REST, tôi không thấy ràng buộc kiến ​​trúc nào bị vi phạm với các POST không bình thường như ví dụ trên.
lex82

Tôi chắc chắn có thể hình ảnh các yêu cầu POST vi phạm một ràng buộc. Tôi chỉ không hiểu tại sao việc đăng tài nguyên vào bộ sưu tập và để máy chủ quyết định id của nó là vi phạm các ràng buộc REST.
lex82


3
Toàn bộ ý tưởng của POST không phải là bình thường ....
EralpB

2

Suy nghĩ thêm về điều này, chúng tôi đang ghép tài nguyên với URI.

Nếu URI không có ID, tải trọng sẽ cần được sửa đổi:

PUT / no / id / here Tải trọng: {name: "Adrian"} <Người dùng nào ???

Có bất kỳ lý do để không?

Câu trả lời cho câu hỏi này phụ thuộc vào việc bạn có muốn cho phép khách hàng thay đổi ID không?

Nếu khách hàng có thể thay đổi ID, thông qua PUT, thì URI cho tài nguyên sẽ thay đổi và bạn nên cung cấp 301 Đã di chuyển vĩnh viễn bất cứ khi nào tài nguyên truy cập vào URI cũ.

Vì vậy, ví dụ bạn bắt đầu với một tài nguyên tại

/users/123

và khách hàng PUT sau đây vào tài nguyên

{id: 222, name: "Adrian"}

tài nguyên đã được cập nhật và URI của nó hiện

/users/222

Các Locationtrường trong phản ứng PUT nên chứa URI mới, và nếu bạn đi đến /users/123bạn sẽ nhận được một 301phản ứng với lĩnh vực Location trỏ đến mới /users/222tài nguyên.

Trong hầu hết các trường hợp mặc dù bạn không thực sự muốn khách hàng có thể thay đổi ID, vì điều này có thể trở nên khá lộn xộn khá nhanh. Trong trường hợp đó, ID là thứ mà chỉ máy chủ mới có thể thay đổi và bạn nên để nó ra khỏi thân PUT, vì máy khách không thể cập nhật trạng thái này.

Nếu bạn đặt yêu cầu cho một URI khác trên cùng một tài nguyên, hãy nói

/users/adian_lync

sau đó nếu tài nguyên đó không tồn tại, máy chủ sẽ tạo nó và tạo và ID khi nó đang thực hiện


1
Lý do khiến chúng tôi đặt câu hỏi về vị trí của ID trong tải trọng là do Backbone.js chuyển ID trong yêu cầu PUT theo mặc định. Chúng ta có thể ngăn chặn điều đó xảy ra, nhưng bây giờ tôi muốn biết tại sao đó là hành vi mặc định.
Adrian Lynch

1
Sợ tôi không quen với Backbone.js. Có vẻ không cần thiết nếu ID cũng được bao gồm trong URL. Có lẽ một sự giám sát về phía các nhà phát triển
Cormac Mulhall
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.