REST, HTTP DELETE và các tham số


135

Có bất cứ điều gì không RESTful về việc cung cấp các tham số cho yêu cầu XÓA HTTP không?


Kịch bản của tôi là tôi đang lập mô hình "Bạn có chắc chắn muốn xóa nó không?" kịch bản. Trong một số trường hợp, trạng thái của tài nguyên cho thấy việc xóa được yêu cầu có thể không hợp lệ. Bạn có thể tự mình tưởng tượng một số tình huống trong đó yêu cầu xác nhận xóa

Giải pháp chúng tôi đã áp dụng là chuyển một tham số cho yêu cầu xóa để chỉ ra rằng bạn có thể tiến hành xóa ("? Force_delete = true")

ví dụ

DELETE http://server/resource/id?force_delete=true

Tôi tin rằng nó vẫn còn yên tĩnh kể từ:

(a) Các ngữ nghĩa của XÓA không bị thay đổi - người dùng vẫn có thể gửi yêu cầu XÓA bình thường nhưng điều này có thể thất bại với 409 và phần thân của phản hồi sẽ giải thích lý do. Tôi nói có thể thất bại bởi vì (vì lý do không đáng để giải thích) trong một số trường hợp không có lý do để nhắc nhở người dùng.

(b) Không có gì trong luận án của Roy để đề xuất rằng nó trái với tinh thần của REST - tại sao lại có vì HTTP chỉ là một triển khai của REST, vậy tại sao việc truyền các tham số HTTP lại quan trọng


Ai đó có thể chỉ cho tôi một tuyên bố dứt khoát rằng lý do tại sao điều này không phải là RESTful?

Đối với một câu hỏi liên quan, nếu người dùng không chỉ định Force_delete thì tôi sẽ trả lại 409 Conflict- đó có phải là mã phản hồi phù hợp nhất không?


Theo sát

Sau một số nghiên cứu sâu hơn, tôi nghĩ rằng việc thêm các tham số vào XÓA có thể vi phạm một số nguyên tắc.

Đầu tiên là việc triển khai có thể vi phạm "Giao diện thống nhất" (xem phần 5.1.5 của luận án của Roy

Bằng cách thêm 'force_delete', chúng tôi sẽ thêm một ràng buộc bổ sung vào phương thức XÓA đã được xác định rõ. Hạn chế này chỉ có ý nghĩa đối với chúng tôi.

Bạn cũng có thể lập luận rằng nó vi phạm "5.1.2 Máy khách-Máy chủ" do cuộc đối thoại xác nhận thực sự là mối quan tâm của UI và một lần nữa không phải tất cả khách hàng sẽ muốn xác nhận xóa.

Gợi ý cho ai?


1
Url của bạn cho luận văn của Roy chứa ")" gây ra 404. ics.uci.edu/~fielding/pub/dissertation/rest_arch_style.htmlm hoạt động.
NuclePeon

Câu trả lời:


78

Không, nó không phải là RESTful. Lý do duy nhất tại sao bạn nên đặt một động từ ( force_delete) vào URI là nếu bạn cần quá tải các phương thức GET / POST trong môi trường không có phương thức PUT / DELETE. Đánh giá từ việc bạn sử dụng phương pháp XÓA, đây không phải là trường hợp.

Mã lỗi HTTP 409/Conflictnên được sử dụng cho các tình huống có xung đột ngăn dịch vụ RESTful thực hiện thao tác, nhưng vẫn có khả năng người dùng có thể tự giải quyết xung đột. Một xác nhận xóa trước (trong đó không có xung đột thực sự sẽ ngăn chặn xóa) không phải là xung đột vì sẽ không có gì ngăn API thực hiện thao tác được yêu cầu.

Như Alex đã nói (tôi không biết ai đã hạ thấp anh ta, anh ta đúng), điều này nên được xử lý trong UI, bởi vì một dịch vụ RESTful như vậy chỉ xử lý các yêu cầu và do đó không nên dựa vào xác nhận bằng cách giữ bất kỳ thông tin phía máy chủ nào về yêu cầu).

Hai ví dụ về cách thực hiện điều này trong UI sẽ là:

  • tiền HTML5 : * hiển thị hộp thoại xác nhận JS cho người dùng và chỉ gửi yêu cầu nếu người dùng xác nhận nó
  • HTML5 : * sử dụng biểu mẫu với hành động XÓA trong đó biểu mẫu chỉ chứa các nút "Xác nhận" và "Hủy" ("Xác nhận" sẽ là nút gửi)

(*) Xin lưu ý rằng các phiên bản HTML trước 5 không hỗ trợ các phương thức HTTP PUT và DELETE, tuy nhiên hầu hết các trình duyệt hiện đại có thể thực hiện hai phương thức này thông qua các cuộc gọi AJAX. Xem chủ đề này để biết chi tiết về hỗ trợ trình duyệt chéo.


Cập nhật (dựa trên điều tra và thảo luận bổ sung):

Kịch bản trong đó dịch vụ sẽ yêu cầu xuất hiện force_delete=truecờ vi phạm giao diện thống nhất như được định nghĩa trong luận án của Roy Fielding. Ngoài ra, theo HTTP RFC , phương thức DELETE có thể bị ghi đè trên máy chủ gốc (máy khách), ngụ ý rằng điều này không được thực hiện trên máy chủ đích (dịch vụ).

Vì vậy, một khi dịch vụ nhận được yêu cầu XÓA, nó sẽ xử lý nó mà không cần bất kỳ xác nhận bổ sung nào (bất kể dịch vụ có thực sự hoạt động hay không).


2
Bạn có thể giải thích ràng buộc REST nào đang bị vi phạm? Xem xét rằng các URI phải mờ đối với máy khách, tại sao bạn tin rằng các kỳ vọng của khách hàng không được đáp ứng với việc sử dụng HTTP DELETE xóa một tài nguyên nhưng không xóa được tài nguyên khác. Tôi không chắc 409 là mã trạng thái tốt nhất để trả về nhưng ngoài việc có một chút triển khai lạ, tôi không thể tìm thấy bất kỳ ràng buộc REST nào bị phá vỡ.
Darrel Miller

2
@Darrel: (imho) nó vi phạm giao diện thống nhất bởi phương thức XÓA không hoạt động theo tiêu chuẩn HTTP. Hãy xem xét một máy khách REST giả định dịch vụ REST tiêu chuẩn - dịch vụ sẽ cho khách hàng biết rằng nó cần thêm force_delete=truenhư thế nào? Theo HTTP RFC, phương thức DELETE có thể được ghi đè trên máy chủ gốc (máy khách), ngụ ý rằng điều này không được thực hiện trên máy chủ đích (dịch vụ). Vì vậy, sự hiểu biết của tôi là một khi dịch vụ nhận được yêu cầu XÓA, nó sẽ xử lý nó mà không cần bất kỳ xác nhận nào (bất kể dịch vụ có thực sự hoạt động hay không).
MicE

1
@Chris, đến điểm thứ hai của bạn: vâng, đó cũng là sự hiểu biết của tôi, tức là nhà nước gợi ý một cuộc xung đột thực sự và không cần phải xác nhận. Tôi chỉ nhận thấy bản cập nhật mà bạn đã làm trong câu hỏi của bạn và tôi đồng ý - trong khi tôi đang xem xét bản thân mình, tôi đã đi đến kết luận tương tự (rằng điều này vi phạm giao diện thống nhất và rằng xác nhận phải được thực hiện trên máy khách / UI bên). Tôi cũng đã chạy qua một chủ đề rất thú vị ở đây, nó có thể giúp: mail-archive.com/pylons-discuss@googlegroups.com/msg13578.html
MicE

2
@MicE Ở một mức độ lớn, tôi đồng ý với bạn rằng đó không phải là cách lý tưởng để xử lý tình huống này. Tôi chỉ hơi khó tính về nhãn "không phải là RESTful". Trong một thời gian ở đây cụm từ đó đã được ném vào tất cả mọi thứ. Tuy nhiên, có thể xác định quy tắc cho loại phương tiện cho biết nếu bạn cố gắng XÓA một tài nguyên và bạn gặp lỗi (tôi sẽ nói 403 bị cấm sẽ tốt hơn 409), sau đó khách hàng nên thử XÓA trên tài nguyên liên quan bằng cách xử lý "force_delete = true". Theo một cách nào đó, nó hơi giống như ủy quyền. Làm GET, nhận 401, thêm tiêu đề auth và GET lại.
Darrel Miller

2
@Darrel: đó là một điểm rất tốt, cảm ơn bạn. Và tôi đã thấy mọi người ném nhãn không RESTful cho mình. Có thể là trường hợp ngày nay rào cản giữa các dịch vụ và ứng dụng web đang trở nên rất mù mờ, vì vậy một bộ người có thể thấy điều này từ quan điểm dịch vụ thuần túy, trong khi những người khác nhìn nhận nó từ quan điểm ứng dụng / dịch vụ hỗn hợp. Đó là tôi tin rằng câu hỏi thực sự về cách thực hiện xác nhận được đưa ra. @Chris: đã cập nhật - cảm ơn ngài vì một chủ đề và thảo luận rất thú vị!
MicE

35

Tôi nghĩ rằng điều này là không nghỉ ngơi. Tôi không nghĩ rằng dịch vụ nghỉ ngơi nên xử lý yêu cầu buộc người dùng xác nhận xóa. Tôi sẽ xử lý việc này trong UI.

Việc chỉ định Force_delete = true có hợp lý không nếu đây là API của chương trình? Nếu ai đó đang viết một tập lệnh để xóa tài nguyên này, bạn có muốn buộc họ chỉ định Force_delete = true để thực sự xóa tài nguyên không?


Đoạn đầu tiên trong câu trả lời của bạn là ý kiến ​​của bạn và tôi tôn trọng điều đó nhưng bạn chưa chỉ ra điều gì trong tài liệu cấm sử dụng URI như thế này - nó vẫn xác định tài nguyên và động từ HTTP phù hợp nhất đang được sử dụng. Trả lời câu hỏi của bạn; vâng nó vẫn có ý nghĩa (theo ý kiến ​​của tôi). Tôi mong muốn một kịch bản (có lẽ dựa trên CURL) tôn trọng phản hồi 409 và đề xuất với người dùng về cách yêu cầu có thể được gửi lại - tất cả dựa trên cơ quan phản hồi của tôi
Chris McCauley 30/03

Điểm hay về việc so sánh API web với API của chương trình. Đó thường là một cách tốt để tìm hiểu xem API có RESTful hay không.
nguyệt quế

18

Đây là một câu hỏi cũ, nhưng đây là một số ý kiến ​​...

  1. Trong SQL, lệnh DELETE chấp nhận tham số "CASCADE", cho phép bạn chỉ định rằng các đối tượng phụ thuộc cũng sẽ bị xóa. Đây là một ví dụ về tham số XÓA có ý nghĩa, nhưng 'man rm' có thể cung cấp cho người khác. Làm thế nào những trường hợp này có thể được thực hiện trong REST / HTTP mà không có tham số?
  2. @Jan, dường như đây là một quy ước được thiết lập tốt rằng phần đường dẫn của URL xác định một tài nguyên, trong khi chuỗi truy vấn thì không (ít nhất là không nhất thiết). Ví dụ rất nhiều: nhận cùng một tài nguyên nhưng ở định dạng khác, nhận các trường cụ thể của tài nguyên, v.v. Nếu chúng ta coi chuỗi truy vấn là một phần của mã định danh tài nguyên, không thể có khái niệm "các chế độ xem khác nhau của cùng một tài nguyên" mà không chuyển sang các cơ chế không RESTful như đàm phán nội dung HTTP (có thể không mong muốn vì nhiều lý do).

Cảm ơn vì đã thêm điều này vào cuộc trò chuyện, ngay cả khi đó không phải là cuộc trò chuyện nhiều kể từ khi nó kéo dài nhiều năm.
silviot

6

Ngoài câu trả lời của Alex:

Lưu ý rằng http: // server / resource / id? Force_delete = true xác định một tài nguyên khác với http: // server / resource / id . Ví dụ, đó là một sự khác biệt rất lớn cho dù bạn xóa / khách hàng /? Status = cũ hay / khách hàng /.

tháng một


Tôi không đồng ý, tôi tự do cung cấp nhiều URI để xác định cùng một tài nguyên.
Chris McCauley

18
Đúng - mọi người có thể tự do gây rối :-)
Jan Algermissen

Dấu hiệu của các URI chính tắc có thể giúp với điều này: googlewebmastercentral.blogspot.com/2009/02/ Ấn
MicE

@Chris Chỉ nên có một URI trả về đại diện của tài nguyên. Các URI khác có thể đề cập đến cùng một khái niệm nhưng thực hiện GET sẽ trả về 303 Xem Khác. Và chỉ để chống lại sự phản đối rõ ràng về điều này, /foo.xml và /foo.json là hai tài nguyên khác nhau.
Darrel Miller

@Darrell - đồng ý nhưng định dạng không phải là vấn đề ở đây. Ngoài ra, .format là một quy ước trong Rails và các khung khác không phải là một phần của REST - bạn nên sử dụng đàm phán nội dung trong HTTP với MIME hoặc microformats để thực hiện đầy đủ điều này.
Chris McCauley
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.