Tôi nên sử dụng động từ HTTP nào để kích hoạt một hành động trong dịch vụ web REST?


80

Tôi đang triển khai một dịch vụ web RESTful và một trong những hành động khả dụng sẽ là reload. Nó sẽ được sử dụng để tải lại cấu hình, bộ đệm, v.v.

Chúng tôi đã bắt đầu với một GETURI đơn giản như thế này: ${path}/cache/reload(không có tham số nào được thông qua, chỉ có URI được gọi). Tôi biết rằng dữ liệu không nên được sửa đổi với yêu cầu GET.

Đó là động từ chính xác để sử dụng để gọi một hành động / lệnh trong dịch vụ web RESTful?

Tải lại là một lệnh của dịch vụ web REST tải lại bộ đệm / cấu hình / vv của chính nó. Nó không phải là một phương thức trả về thông tin cho khách hàng.

Có lẽ những gì tôi đang cố gắng không phải là REST, nhưng nó vẫn là thứ cần được thực hiện theo cách này. Các reloadphương pháp duy nhất là một ví dụ thực tế có ý nghĩa trong phạm vi của các ứng dụng và hầu hết các câu trả lời tập trung vào nó, nhưng trên thực tế, tôi chỉ cần biết đó động từ để kích hoạt một hành động mà không làm CRUD, nhưng vẫn thay đổi dữ liệu / tiểu bang.

Tôi đã tìm thấy thông báo chi tiết này về Stack Overflow abot chủ đề: https://stackoverflow.com/questions/16877968/


1
"Tải lại" là ý nghĩa của một ứng dụng làm mới dữ liệu mà nó sẽ hiển thị? Có sự khác biệt nào giữa việc tải lại và chỉ lấy lại dữ liệu không?
Sean Redmond

1
@SeanRedmond Không, dữ liệu không được gửi cho khách hàng. Trong thực tế, là máy khách nói với dịch vụ web REST để thực thi và lệnh nội bộ (tải lại). Một cái gì đó như: "rất nhiều cấu hình đã được thay đổi trong cơ sở dữ liệu, vì vậy dịch vụ web REST, tải lại chúng vào bộ nhớ của bạn ngay bây giờ".
Renato Dinhani

Trang web trùng lặp trùng lặp: stackoverflow.com/q/15340946/319403
cHao

Bạn đã xem xét sử dụng một tham số tiêu đề trên các yêu cầu thích hợp? Điều này nghe có vẻ giống như làm mới bộ nhớ cache ...
Guran

Câu trả lời:


25

Tôi không nghĩ có một động từ thích hợp cho hành động này vì giao dịch này không thực sự "RESTful". Chữ "s" và "t" là viết tắt của "chuyển trạng thái" và không có gì được chuyển ở đây. Hoặc, đặt một cách khác, theo định nghĩa nghiêm ngặt nhất, các động từ như PUT và POST luôn được sử dụng với một danh từ và "tải lại" chỉ có động từ.

Tải lại này có thể không phải là RESTful, nhưng nó vẫn có thể hữu ích và bạn sẽ chỉ cần chọn một cách để làm điều đó và sống với hoặc giải thích rằng điều đó là bất thường. GET có lẽ là đơn giản nhất. Tuy nhiên, có một sự hoài nghi khá lớn trong các bình luận, vì vậy bạn nên suy nghĩ xem liệu hành động tải lại này có được yêu cầu hay không bởi vì một cái gì đó khác không hoàn toàn làm những gì nó nên làm.


Tôi đồng ý rằng đây không phải là RESTful nhưng có thể hữu ích. Tôi nghĩ rằng bạn nên khuyên PUT, bởi vì điều này có thể là bình thường nhưng không vô hiệu.
Aaron Greenwald

@Aaron, việc so sánh idempotent và nullimpotent đều ổn và tốt, nhưng làm thế nào để bạn xác định khi nào nó không nổi bật?
Craig

@Craig thật bình thường nếu chạy nó nhiều lần có tác dụng tương tự như chạy nó một lần. Sẽ không có giá trị nếu chạy nó một lần hoặc nhiều lần có tác dụng tương tự trên máy chủ như chạy 0 lần. vi.wikipedia.org/wiki/Idempotence
Aaron Greenwald

5
@AaronGreenwald “notimpotent” [không-im-poht-nt] [không-im-pawr-tnt] - tính từ - “quan trọng.” 1. Một cách chơi chữ, “không quan trọng”, phản nghĩa của tính từ 2. hài hước ... ;-)
Craig

@Craig Tôi hoàn toàn bỏ lỡ điều đó :)
Aaron Greenwald

75

Nếu bạn muốn trở thành RESTful, đừng nghĩ đến động từ để thực hiện một hành động, hãy nghĩ đến trạng thái bạn muốn tài nguyên ở sau khi khách hàng đã làm gì đó.

Vì vậy, sử dụng một trong những ví dụ của bạn ở trên, bạn có một hàng đợi email đang gửi email. Bạn muốn khách hàng đặt hàng đợi email đó vào trạng thái tạm dừng hoặc dừng hoặc một cái gì đó.

Vì vậy, máy khách PUT tạo một trạng thái mới cho máy chủ cho tài nguyên đó. Nó có thể đơn giản như JSON này

PUT http://myserver.com/services/email_service HTTP/1.1
Content-Type: text/json

{"status":"paused"}

Máy chủ tìm ra cách chuyển từ trạng thái hiện tại (nói "đang chạy") sang trạng thái / trạng thái "tạm dừng".

Nếu máy khách thực hiện GET trên tài nguyên, nó sẽ trả về trạng thái hiện tại (nói "đã tạm dừng").

Lý do để làm theo cách này và tại sao REST có thể mạnh mẽ như vậy, là bạn rời khỏi CÁCH để đến trạng thái đó trên máy chủ.

Máy khách chỉ nói "Đây là trạng thái bạn nên ở ngay bây giờ" và máy chủ tìm ra cách để đạt được điều đó. Nó có thể là một lật đơn giản trong cơ sở dữ liệu. Nó có thể đòi hỏi hàng ngàn hành động. Khách hàng không quan tâm và không cần phải biết.

Vì vậy, bạn hoàn toàn có thể viết lại / thiết kế lại cách máy chủ thực hiện điều đó và máy khách không quan tâm. Khách hàng chỉ cần nhận thức được các trạng thái khác nhau (và các đại diện của họ) của một tài nguyên, không phải bất kỳ nội bộ nào.


2
Theo tôi nghĩ đây là câu trả lời chính xác. Làm mới dữ liệu trên máy chủ không phải là một hoạt động bình thường và GETlà một động từ hoàn toàn không phù hợp để sử dụng. PUTlà động từ thích hợp nhất vì hoạt động có thể được coi là cập nhật "trạng thái tải lại" của bộ đệm thành "tải lại".
Jez

@Jez Trong số các câu trả lời ở đây, tôi cũng thích câu trả lời này. Gắn bó với hình ảnh ẩn dụ email, ngay nó không cảm thấy lẻ lúc đầu nghĩ đến việc gửi qua đường bưu điện bằng cách đặt nó vào "gửi" nhà nước thay vì chỉ gửi nó (một hành động). Nhưng nếu bạn nghĩ về nó, đó thực sự giống như việc đưa nó vào "hộp thư đi". Trong thực tế, hệ thống thư có thể đang xếp hàng theo cách đó trong nội bộ khi bạn bảo nó gửi. Vì vậy, API có thể cho phép bạn đặt thư ở trạng thái "gửi" và API không bắt buộc phải giải thích chính nó ngoài điều đó.
Craig

Vì vậy, bằng cách mở rộng, nếu bạn không muốn tin nhắn đi ngay, bạn hãy đặt nó ở trạng thái "đã lên lịch" với ngày / giờ khi nó sẽ được phát hành. Nếu nó không hoàn thành, bạn đặt nó (hoặc mặc định / theo mặc định) ở trạng thái "bản nháp", v.v.
Craig

... mặc dù tôi nghĩ rằng tôi thích POST hơn PUT trong trường hợp này, vì PUT cũng được coi là không hoạt động, nhưng POST không bị ràng buộc như vậy.
Craig

1
Bạn có thể làm điều đó, nhưng cuối cùng nó đang cố gắng lắp một cái chốt vuông vào một cái lỗ tròn. Không có lý do tại sao khách hàng cần kích hoạt máy chủ để "tải lại" bất cứ thứ gì, đó chỉ là thiết kế kiến ​​trúc kém. Máy chủ có thể cập nhật trạng thái bên trong của nó trên mỗi cuộc gọi hoặc trong một khoảng thời gian cố định. Dựa vào máy khách để yêu cầu máy chủ tải lại một cái gì đó độc lập với bất kỳ yêu cầu thực tế nào đối với trạng thái tài nguyên không phải là kiến ​​trúc RESTful.
Cormac Mulhall

32

Một số câu trả lời khác, bao gồm câu trả lời được chấp nhận, khuyên bạn nên sử dụng GET (mặc dù không nhiệt tình lắm).

Tôi không đồng ý.

Trước hết, tất cả những người khác nói với bạn rằng điều này không lý tưởng và không thực sự RESTful là chính xác. Trong một kịch bản RESTful thích hợp, bạn đang thao tác các tài nguyên trên máy chủ và thêm, cập nhật, xóa, truy xuất, v.v. những tài nguyên đó. Một PUT sẽ gửi một tải trọng thể hiện tài nguyên sẽ là gì khi yêu cầu hoàn thành và POST sẽ gửi một tải trọng đại diện cho một tài nguyên được thêm vào máy chủ. Và một GET sẽ trả về một tài nguyên trên máy chủ.

Bạn có RPC (cuộc gọi thủ tục từ xa), không phải là RESTful - bạn muốn LÀM gì đó trên máy chủ. Vì vậy, nếu bạn đang cố gắng tạo một API RESTful hoàn toàn, bạn nên xem xét lại những gì bạn đang làm.

Điều đó nói rằng, đôi khi bạn cần phải uốn cong các quy tắc một chút. Đặc biệt nếu bạn đang phát triển một api nội bộ sẽ không được tiếp xúc với công chúng, bạn có thể quyết định rằng sự đánh đổi là xứng đáng.

Nếu bạn làm thế, tôi muốn giới thiệu một PUT hoặc POST, tùy thuộc vào việc hay không RPC là idempotent hay không.

Nói chung, chúng tôi nói rằng HTTP PUT ánh xạ tới SQL UPDATE và HTTP POST ánh xạ tới SQL INSERT, nhưng điều đó không hoàn toàn đúng. Một cách đơn giản hơn để nói rằng HTTP PUT phải là idempotent và HTTP POST không cần. Điều này có nghĩa là bạn có thể gọi cùng một yêu cầu PUT bao nhiêu lần tùy ý mà không có tác dụng phụ. Một khi bạn đã gọi nó một lần thì vô hại để gọi lại. Nhưng bạn không nên liên tục gọi các yêu cầu POST trừ khi bạn có ý định - mỗi POST lại thay đổi dữ liệu trên máy chủ.

Trong trường hợp của bạn, nếu bạn cần có chức năng tải lại này, tôi khuyên bạn nên PUT vì nó có vẻ như không hoạt động. Nhưng tôi vẫn mong bạn xem xét những gì người khác nói về việc không cần nó chút nào.


6

POSTPUTlà các động từ HTTP được sử dụng để gửi một thực thể đến máy chủ web. Với PUT, thực thể được gửi là đại diện (mới) cho tài nguyên tại URI đã cho, không phù hợp với những gì bạn muốn. POSTdành cho trình xử lý biểu mẫu truyền thống, trong đó thực thể là dữ liệu phụ trợ cho tài nguyên, vì vậy đó là người chiến thắng. Thực thể sẽ bao gồm lệnh hoặc hành động (ví dụ: "hành động = tải lại").

Điều đó nói rằng, lệnh trong câu hỏi có lẽ không nên được hiển thị thông qua giao diện REST. Nghe có vẻ cần thiết cho "tải lại" phát sinh vì dữ liệu có thể được thay đổi thông qua một số kênh khác (ví dụ: hệ thống tập tin, máy khách DB). Bộ nhớ cache phải minh bạch. Hơn nữa, các yêu cầu HTTP phải là nguyên tử, thậm chí xem xét các tin nhắn được gửi qua các kênh khác. Việc cung cấp lệnh "tải lại" cho các cài đặt cấu hình có vẻ phức tạp không cần thiết; đòi hỏi nó là một thiết kế dễ vỡ. Việc phơi bày "tải lại" để dọn dẹp sau khi cập nhật qua kênh khác là bẩn vì một kênh không chứa toàn bộ cuộc hội thoại. Thay vào đó, hãy xem xét một trong:

  • thực hiện cập nhật hoàn toàn thông qua REST
  • hiển thị (các) lệnh cho kênh khác
  • tự động hóa các hành động

Một số tùy chọn có thể không khả thi, tùy thuộc vào những hạn chế khác tồn tại.

Xem thêm " PUT vs POST trong REST ".


Cảm ơn bạn. Tôi đã xóa "nội bộ" của chỉnh sửa vì trên thực tế phương thức "tải lại" được dự định là công khai. Tôi chỉ cố gắng để chỉ nó đề cập đến chính dịch vụ web. Tôi nghĩ rằng đăng "hành động" sẽ là một cách tiếp cận tốt.
Renato Dinhani

@ RenatoDinhaniConceição: ngay cả khi không có "nội bộ", nó vẫn có mùi. Nó có thể khiến bạn phải đặt một câu hỏi mới về việc liệu thiết kế có tốt không.
outis

4

Tôi sẽ tranh luận lý do tại sao một yêu cầu khách hàng rõ ràng cần phải thực hiện một cuộc gọi để làm mới một cái gì đó như thế. Nghe có vẻ như đó phải là logic ẩn trong việc triển khai GET (Ie Pull dữ liệu điển hình hơn, nhưng dịch vụ sẽ làm mới dữ liệu trước khi được kéo) hoặc bởi một trình kích hoạt khác trong phần phụ trợ cách xa máy khách.

Rốt cuộc, dữ liệu / cấu hình sẽ chỉ cần hiện hành trong các cuộc gọi tiếp theo, vì vậy tôi sẽ nghiêng nhiều hơn về một cuộc gọi lười biếng và háo hức để làm mới dữ liệu. Rõ ràng tôi đang giả định rất nhiều ở đây, nhưng tôi sẽ lùi một bước để đánh giá lại sự cần thiết của một cuộc gọi rõ ràng và độc lập như vậy.


Nhìn vào chỉnh sửa của tôi. "tải lại" không phải là một lệnh trả về dữ liệu. Nó đề cập đến chính dịch vụ web REST. Nói chung, câu hỏi của tôi đề cập đến việc kích hoạt các hành động trong dịch vụ web REST. Ví dụ khác có thể là : email_queue/stop_sending_emails. Tôi chỉ đưa ra một lệnh cho một cái gì đó bằng giao diện RESTful.
Renato Dinhani

5
Tôi vẫn đồng ý. Gọi SIGHUP trên một quy trình cục bộ có ý nghĩa, vì máy tính nên tin tưởng một người nào đó đã đăng nhập cục bộ có quyền truy cập vào tín hiệu đó. Nhưng đối với một giao thức không trạng thái, có thể truy cập Internet? Có lẽ dịch vụ web sẽ tự động tải lại khi cần thiết thông qua bỏ phiếu hoặc giám sát tệp. Cuộc gọi này nên hoàn toàn không cần thiết.

1
Tôi đồng ý. Những thứ như cấu hình và bộ nhớ đệm có nghĩa là trong suốt đối với máy khách. Có lẽ bạn nên cung cấp cho chúng tôi một mô tả cụ thể hơn về một tình huống trong đó điểm cuối của bạn sẽ được gọi.
Benjamin Hodgson

3

Tại sao không coi hành động như một tài nguyên. Vì vậy, vì bạn muốn cập nhật bộ đệm, bạn sẽ POST một hành động mới trong hệ thống của bạn.

Đối với những người theo chủ nghĩa thuần túy, bạn có thể có một url dành riêng cho điều đó. Lưu ý rằng bạn có thể mở rộng điều này và ghi lại các hành động thực tế trong cơ sở dữ liệu (hoặc bất kỳ lưu trữ nào) với ngày, trạng thái, người dùng, v.v ... Chỉ là suy nghĩ của tôi ở đây.

Hoạt động / hành động trên toàn hệ thống chung

Hoạt động cụ thể cho loại tài nguyên / hành động / {resource} / {action}

Hoạt động cụ thể đối với tài nguyên / hành động / {resource} / {id} / {action}

Trong trường hợp của bạn, bộ đệm có thể là toàn hệ thống / hành động / reload_cache


0

Tôi nên sử dụng động từ HTTP nào để kích hoạt một hành động trong dịch vụ web REST?

Khi xem xét các chi tiết của dịch vụ REST, thường rất hữu ích khi xem xét phương pháp phỏng đoán này: bạn sẽ triển khai việc này với một trang web như thế nào?

HTML chỉ có thể mô tả tự nhiên các yêu cầu GET và POST. Vì vậy, chúng ta có thể bắt đầu tìm kiếm ở đó.

GETphù hợp không? Để trả lời câu hỏi này, chúng ta cần suy nghĩ về các giả định mà khách hàng và các thành phần trung gian được phép đưa ra GET. Các ngữ nghĩa GETan toàn

khách hàng không yêu cầu và không mong đợi bất kỳ thay đổi trạng thái nào trên máy chủ gốc do áp dụng phương pháp an toàn cho tài nguyên đích. Tương tự như vậy, việc sử dụng hợp lý một phương pháp an toàn không được dự kiến ​​sẽ gây ra bất kỳ tổn hại, mất mát tài sản hoặc gánh nặng bất thường nào trên máy chủ gốc.

Do đó, hàm ý là các máy khách và các thành phần trung gian có toàn quyền đưa ra yêu cầu GET thường xuyên khi cần thiết để đáp ứng mối quan tâm của riêng chúng. Nhện có thể NHẬN tài nguyên bừa bãi để cập nhật chỉ mục của chúng. Bộ nhớ cache có thể tìm nạp trước. Trên một mạng không đáng tin cậy, các tin nhắn bị mất có thể được kiểm tra lại thường xuyên khi cần thiết để đảm bảo ít nhất một phản hồi.

Nó sẽ được sử dụng để tải lại cấu hình, bộ đệm, v.v.

Nếu đây là những việc đắt đỏ phải làm, thì có lẽ bạn không muốn khách hàng đưa ra những yêu cầu này theo ý mình.

POSTmặt khác, thực sự không bị ràng buộc - điều này làm giảm đáng kể các giả định mà khách hàng chung được phép thực hiện. Bạn không nhận được các thành phần thực hiện các yêu cầu POST đầu cơ vì chúng sẽ bị lỗi khi thực hiện - không có gì trong tiêu chuẩn nói rằng điều đó ổn cả.

PUT, PATCH, DELETE... đây là những phương pháp không an toàn với ngữ nghĩa cụ thể hơn POST; việc chúng có phù hợp hay không sẽ phụ thuộc vào mô hình tài nguyên của bạn.

Một ý tưởng quan trọng cần ghi nhớ là các phương thức HTTP thuộc về miền tài liệu (Xem bài nói chuyện năm 2011 của Jim Webber ), các hiệu ứng bạn đang mô tả có thể không phải là một phần của miền tài liệu, nhưng thay vào đó là các tác dụng phụ được gọi khi thay đổi tài liệu . Điều đó mang lại cho bạn rất nhiều sự tự do về cách bạn sắp xếp các tài liệu của mình để hoàn thành công việc.

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.