Có bất kỳ vấn đề với việc thực hiện các phương thức HTTP tùy chỉnh?


34

Chúng tôi có một URL theo định dạng sau

/ instance / {instanceType} / {instanceId}

Bạn có thể gọi nó bằng các phương thức HTTP tiêu chuẩn: POST, GET, DELETE, PUT. Tuy nhiên, có một vài hành động nữa mà chúng tôi thực hiện như "Lưu dưới dạng bản nháp" hoặc "Curate"

Chúng tôi nghĩ rằng chúng tôi chỉ có thể sử dụng các phương thức HTTP tùy chỉnh như: DRAFT, VALIDATE, HIỆN TẠI

Tôi nghĩ rằng điều này được chấp nhận vì các tiêu chuẩn nói

"Tập hợp các phương thức phổ biến cho HTTP / 1.1 được xác định bên dưới. Mặc dù bộ này có thể được mở rộng, các phương thức bổ sung có thể được giả sử để chia sẻ cùng một ngữ nghĩa cho các máy khách và máy chủ mở rộng riêng biệt."

Và các công cụ như WebDav tạo ra một số tiện ích mở rộng của riêng họ.

Có vấn đề ai đó đã gặp phải với các phương pháp tùy chỉnh? Tôi đang nghĩ về các máy chủ proxy và tường lửa nhưng bất kỳ lĩnh vực quan tâm nào khác đều được chào đón. Tôi có nên ở bên an toàn và chỉ cần có một tham số URL như hành động = xác thực | curate | dự thảo?


6
Như tôi đã trích dẫn từ RFC 1925 một lần nữa - "Trong thiết kế giao thức, sự hoàn hảo đã đạt được không phải khi không còn gì để thêm, mà là khi không còn gì để lấy đi." - nếu nó hoạt động, không có lý do để thêm vào http.

4
Không có gì sai, miễn là bạn nhận ra rằng bạn hiện đang sử dụng một giao thức tùy chỉnh chứ không phải HTTP.
dùng16764

10
@ user16764 "Tập hợp các phương thức phổ biến cho HTTP / 1.1 được xác định bên dưới. Mặc dù bộ này có thể được mở rộng, các phương thức bổ sung không thể được giả sử để chia sẻ cùng một ngữ nghĩa cho các máy khách và máy chủ được mở rộng riêng biệt." w3.org/Prot Protocol / rfc2616 / rfc2616-sec9.html Do đó, nó được cho phép và nó vẫn là HTTP
Juan Mendes

Tôi không có gì để thêm / xóa khỏi HTTP vì các định nghĩa phương thức nói rằng sử dụng các phương thức tùy chỉnh đã được chấp nhận trong phạm vi HTTP / 1.1 nhưng không thể chia sẻ cùng một ngữ nghĩa, vì vậy tôi đoán các điểm từ cả @MichaelT và Juan Mendes có thể được xoa dịu phần nào
Prof83

Câu trả lời:


42

Một trong những hạn chế cơ bản của HTTP và các tính năng thiết kế trung tâm của REST là một giao diện thống nhất được cung cấp bởi (trong số những thứ khác) một tập cố định nhỏ của phương pháp được áp dụng phổ biến cho tất cả các tài nguyên. Các ràng buộc giao diện thống nhất có một số mặt thăng trầm. Tôi đang trích dẫn từ Fielding tự do ở đây.

Giao diện thống nhất:

  • đơn giản hơn
  • decouples triển khai từ các dịch vụ mà họ cung cấp.
  • cho phép một kiến ​​trúc phân lớp, bao gồm những thứ như bộ cân bằng tải HTTP (nginx) và bộ đệm (véc ni).

Mặt khác, giao diện thống nhất:

  • làm giảm hiệu quả, bởi vì thông tin được truyền tải ở dạng chuẩn hơn là thông tin cụ thể theo nhu cầu của ứng dụng.

Sự đánh đổi là "được thiết kế cho trường hợp chung của Web" và đã cho phép xây dựng một hệ sinh thái lớn, cung cấp giải pháp cho nhiều vấn đề phổ biến trong kiến ​​trúc web. Việc tuân thủ một giao diện thống nhất sẽ cho phép hệ thống của bạn được hưởng lợi từ hệ sinh thái này trong khi phá vỡ nó sẽ gây khó khăn. Bạn có thể muốn sử dụng một bộ cân bằng tải như nginx nhưng bây giờ bạn chỉ có thể sử dụng một bộ cân bằng tải hiểu DRAFT và HIỆN TẠI. Bạn có thể muốn sử dụng lớp bộ đệm HTTP như Varnish nhưng bây giờ bạn chỉ có thể sử dụng lớp bộ đệm HTTP hiểu DRAFT và HIỆN TẠI. Bạn có thể muốn nhờ ai đó giúp đỡ khắc phục sự cố máy chủ nhưng không ai biết ngữ nghĩa cho yêu cầu HIỆN TẠI. Có thể khó thay đổi thư viện máy khách hoặc máy chủ ưa thích của bạn để hiểu và thực hiện chính xác các phương thức mới. Và như vậy.

Cách * chính xác để biểu diễn điều này là một chuyển đổi trạng thái trên tài nguyên (hoặc tài nguyên liên quan). Bạn không DRAFT một bài đăng, bạn chuyển đổi drafttrạng thái của nó thành truehoặc bạn tạo một drafttài nguyên có chứa các thay đổi và liên kết đến các phiên bản dự thảo trước đó. Bạn không HIỆN một bài đăng, bạn chuyển đổi curatedtrạng thái của nó thành truehoặc tạo một curationtài nguyên liên kết bài đăng với người dùng đã quản lý nó.

* Chính xác ở chỗ nó tuân thủ chặt chẽ nhất các nguyên tắc kiến ​​trúc REST.


Cảm ơn các ý kiến ​​về cân bằng tải, tôi chắc chắn sẽ xem xét điều đó. Bạn có biết về một tài nguyên cho biết các phương thức tùy chỉnh có được chấp nhận hay không?
Juan Mendes

2
Tôi không thấy bất kỳ lợi thế nào cho các phương thức tùy chỉnh trừ khi chúng là một phần của tiện ích mở rộng được hỗ trợ rộng rãi như WEBDAV (và thậm chí sau đó, không quá nhiều) vì vậy tôi chưa bao giờ xem xét nó. Tôi chỉ khuyên bạn nên coi những thay đổi này là biến đổi trạng thái. Web hoạt động tốt với các phương pháp chúng tôi đã có. Thực sự không có lý do chính đáng để thêm nhiều hơn trừ khi chúng có ý nghĩa như là một phần của giao diện thống nhất (như PATCH).
Rein Henrichs

5
Tôi thấy lợi thế trong việc thiết kế theo cách bạn muốn dịch vụ HTTP của bạn hoạt động cho chính mình. tuy nhiên "các phương thức bổ sung không thể được giả định để chia sẻ cùng một ngữ nghĩa" - Đủ công bằng, NHƯNG nó vẫn là một phần của phạm vi HTTP / 1.1, do đó tường lửa, proxy, cân bằng tải và tương tự sẽ cho phép khả năng này, nếu chúng không ' Sau đó họ không thực hiện HTTP / 1.1 đúng cách?
Prof83

Bạn có thể đúng từ POV yên tĩnh, tuy nhiên, tôi không thể hiểu tại sao động từ tùy chỉnh nên có vấn đề. Tất cả các công cụ nên đối xử với chúng giống như POST, tức là "tài nguyên có thể thay đổi và đó là tất cả những gì chúng ta biết".
maaartinus

7

Tôi muốn thiết kế chúng dưới dạng các nguồn con, trên đó bạn thực hiện một yêu cầu POST.

Xem xét bạn có tài nguyên tại /instance/type/1, tôi sẽ có đại diện cho tài nguyên đó truyền tải một vài liên kết đến 'hành động' có thể được thực hiện trên tài nguyên, chẳng hạn như /instance/type/1/draft/instance/type/1/curate. Trong JSON, điều này có thể đơn giản như:

{
    "some property":"the usual value",
    "state": "we can still inform the client about the current state",
    "draft": "http://server/instance/type/1/draft",
    "curate": "http://server/instance/type/1/curate"
}

Điều này cho phép khách hàng rất rõ ràng về những gì cần phải xảy ra, trong khi yêu cầu POST đến liên kết được cung cấp bởi curatethành viên. Tài nguyên được đăng ở đó có thể bao gồm các đối số mô tả chi tiết sự kiện đó, có lẽ, gây ra sự chuyển đổi trạng thái.

Đi theo cách tiếp cận 'ngây thơ' của việc di chuyển giữa các trạng thái có thể có trên một tài nguyên có nhược điểm là không nắm bắt được những sự kiện dẫn đến những chuyển đổi này.

Chuyển đổi trạng thái thường xảy ra để đáp ứng với các sự kiện cụ thể và tôi muốn nắm bắt các sự kiện đó hơn là để khách hàng quyết định rằng một cái gì đó hiện đang ở một 'trạng thái' cụ thể. Nó cũng làm cho việc xác nhận khó khăn hơn rất nhiều. Ngoài ra, bạn sẽ không thể nắm bắt bất kỳ 'đối số' nào trừ khi bạn mô tả cả những người trong chính bang đó. Và sau đó, tất cả sẽ trở nên kỳ quặc khi một số mã thay đổi những mã không có chuyển đổi trạng thái thực và yêu cầu xác thực, và toàn bộ điều này nhanh chóng trở thành một mớ hỗn độn.


Câu trả lời tốt. Có thể cung cấp các đối số cho các chuyển đổi trạng thái và để máy chủ đóng gói và quản lý chúng, cho đến nay là cách tiếp cận tốt nhất.
Thomas W

Công ty tôi hiện đang ở (VMware) làm việc này. Một GET khi /vms/some-idtrả về các liên kết đến các hành động như POST /vms/some-id/restartvà chúng tôi sử dụng nó để xác định xem các hành động nên được bật hay tắt. Tôi có mối quan hệ yêu / ghét với HATEOAS :)
Juan Mendes

Sẽ có ý nghĩa hơn nhiều nếu hành động được thực hiện là động từ của yêu cầu so với một số tham số truy vấn ngẫu nhiên, phân đoạn đường dẫn tài nguyên hoặc thuộc tính cơ thể.
Matthew Whited

Bạn không thể liên kết đến một động từ.
Dave Van den Eynde

6

Tôi nghĩ phương pháp HTTP tùy chỉnh là cách tốt nhất để thực hiện các hành động thực thể. Thêm hành động vào cơ thể thực thể (POST) có vẻ không đúng, nó không phải là một phần của thực thể của bạn (mặc dù kết quả có thể được lưu trong đó). Ngoài ra, sử dụng các proxy phương thức HTTP tùy chỉnh có thể xác định hành động của họ mà không cần phân tích cú pháp phần thân.

Giống như CRUD, bạn luôn muốn thực hiện những điều đó, nhưng bạn cũng có bộ hành động cụ thể của riêng mình (theo sự đố kị). Tôi thực sự không thấy những gì sẽ là vấn đề mở rộng những người.

Ngoài ra @Rein Henrichs "Bạn không DRAFT một bài đăng, bạn chuyển đổi trạng thái dự thảo của nó thành đúng hoặc bạn tạo một tài nguyên dự thảo" có vẻ sai đối với tôi. Một draftstài sản sẽ được sử dụng để lưu trạng thái liên tục, không phải để thực hiện chuyển đổi. Các hành động thậm chí không nhất thiết dẫn đến một 'trạng thái' hoặc được lưu trong một tài sản. Tạo một thực thể riêng biệt cho mỗi trạng thái / biến đổi dường như còn mờ hơn .. cố gắng duy trì cùng một tham chiếu (URI) cho sự thù địch.


1
Đây là một điểm công bằng mặc dù không đồng ý rộng rãi, tôi có thể thấy lý do đằng sau nó và tôi không đồng ý với downvote (đặc biệt là không có bình luận nào từ cử tri). Hãy lấy việc xử lý ngoại lệ PHP làm ví dụ, "Thực tiễn tốt nhất" dường như nghiêng về việc sử dụng các loại Ngoại lệ cụ thể để đề xuất loại ngoại lệ, thậm chí bỏ qua thông báo thực tế như RuntimeException vs BadMethodCallException. Vậy tại sao nó lại được tranh luận rộng rãi về việc sử dụng DRAFT nếu sử dụng các phương thức tùy chỉnh đã được coi là một phần của phạm vi HTTP / 1.1? Và các bộ cân bằng tải và proxy cũng thực sự nên chấp nhận khả năng này
Prof83
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.