API REST đó có thực sự là RPC không? Roy Fielding có vẻ nghĩ vậy


99

Một lượng lớn những gì tôi nghĩ rằng tôi biết về REST rõ ràng là sai - và tôi không đơn độc. Câu hỏi này có một sự dẫn dắt dài dòng, nhưng có vẻ là cần thiết vì thông tin hơi tản mạn. Câu hỏi thực sự đến ở phần cuối nếu bạn đã quen thuộc với chủ đề này.

Từ đoạn đầu tiên của các API REST của Roy Fielding phải theo hướng siêu văn bản , rõ ràng là anh ấy tin rằng công việc của mình đang bị hiểu sai rộng rãi:

Tôi đang cảm thấy thất vọng bởi số lượng người gọi bất kỳ giao diện dựa trên HTTP nào là API REST. Ví dụ hôm nay là API REST SocialSite . Đó là RPC. Nó hét lên RPC. Có rất nhiều khớp nối trên màn hình nên được xếp hạng X.

Fielding tiếp tục liệt kê một số thuộc tính của API REST. Một số người trong số họ dường như đi ngược lại với cả thông lệ và lời khuyên thông thường trên SO và các diễn đàn khác. Ví dụ:

  • Một API REST phải được nhập mà không có kiến ​​thức trước ngoài URI ban đầu (dấu trang) và tập hợp các loại phương tiện được tiêu chuẩn hóa phù hợp với đối tượng dự kiến ​​(tức là bất kỳ khách hàng nào có thể sử dụng API đều mong đợi hiểu được). ...

  • API REST không được xác định tên tài nguyên cố định hoặc cấu trúc phân cấp (một sự kết hợp rõ ràng giữa máy khách và máy chủ). ...

  • API REST nên dành gần như toàn bộ nỗ lực mô tả của mình trong việc xác định (các) loại phương tiện được sử dụng để đại diện cho tài nguyên và thúc đẩy trạng thái ứng dụng hoặc trong việc xác định tên quan hệ mở rộng và / hoặc đánh dấu hỗ trợ siêu văn bản cho các loại phương tiện tiêu chuẩn hiện có. ...

Ý tưởng về "siêu văn bản" đóng một vai trò trung tâm - hơn nhiều so với cấu trúc URI hoặc ý nghĩa của động từ HTTP. "Siêu văn bản" được định nghĩa trong một trong các nhận xét:

Khi tôi [Fielding] nói siêu văn bản, ý tôi là việc trình bày đồng thời thông tin và kiểm soát sao cho thông tin trở thành khả năng chi trả mà thông qua đó người dùng (hoặc automaton) có được các lựa chọn và lựa chọn hành động. Hypermedia chỉ là một bản mở rộng về ý nghĩa của văn bản để bao gồm các neo tạm thời trong một luồng phương tiện; hầu hết các nhà nghiên cứu đã bỏ sự khác biệt.

Siêu văn bản không cần phải là HTML trên trình duyệt. Máy có thể đi theo các liên kết khi chúng hiểu định dạng dữ liệu và các kiểu quan hệ.

Tôi đang đoán vào thời điểm này, nhưng hai điểm đầu tiên ở trên dường như gợi ý rằng tài liệu API cho tài nguyên Foo trông giống như phần sau dẫn đến sự kết hợp chặt chẽ giữa máy khách và máy chủ và không có vị trí trong hệ thống RESTful.

GET   /foos/{id}  # read a Foo
POST  /foos/{id}  # create a Foo
PUT   /foos/{id}  # update a Foo

Thay vào đó, một đại lý phải bị buộc phải phát hiện ra các URI cho tất cả các Foos, ví dụ: đưa ra yêu cầu GET đối với / foos. (Các URI đó có thể tuân theo mô hình ở trên, nhưng đó là điều bên cạnh vấn đề.) Phản hồi sử dụng một loại phương tiện có khả năng truyền đạt cách truy cập từng mục và những gì có thể được thực hiện với nó, dẫn đến điểm thứ ba ở trên . Vì lý do này, tài liệu API nên tập trung vào việc giải thích cách diễn giải siêu văn bản có trong phản hồi.

Hơn nữa, mỗi khi URI tới tài nguyên Foo được yêu cầu, phản hồi chứa tất cả thông tin cần thiết để tác nhân khám phá cách tiến hành, ví dụ: truy cập các tài nguyên mẹ và liên kết thông qua URI của chúng hoặc bằng cách thực hiện hành động sau khi tạo / xóa tài nguyên.

Chìa khóa của toàn bộ hệ thống là phản hồi bao gồm siêu văn bản chứa trong một loại phương tiện mà chính nó chuyển tải đến các tùy chọn tác nhân để tiếp tục. Nó không giống như cách một trình duyệt hoạt động cho con người.

Nhưng đây chỉ là dự đoán tốt nhất của tôi tại thời điểm cụ thể này.

Fielding đã đăng một bài tiếp theo, trong đó anh ta đáp lại những lời chỉ trích rằng cuộc thảo luận của anh ta quá trừu tượng, thiếu ví dụ và giàu biệt ngữ:

Những người khác sẽ cố gắng giải mã những gì tôi đã viết theo những cách trực tiếp hơn hoặc có thể áp dụng cho một số mối quan tâm thực tế ngày nay. Có lẽ tôi sẽ không làm, bởi vì tôi quá bận rộn với chủ đề tiếp theo, chuẩn bị cho một hội nghị, viết một tiêu chuẩn khác, đi du lịch đến một nơi xa xôi nào đó, hoặc chỉ làm những việc nhỏ để tôi cảm thấy mình đã kiếm được tiền lương.

Vì vậy, hai câu hỏi đơn giản dành cho các chuyên gia REST có tư duy thực tế: làm thế nào để bạn giải thích những gì Fielding đang nói và làm thế nào để bạn áp dụng nó vào thực tế khi lập tài liệu / triển khai các API REST?

Chỉnh sửa: câu hỏi này là một ví dụ về việc khó học một thứ gì đó nếu bạn không có tên cho thứ bạn đang nói. Tên trong trường hợp này là "Hypermedia as the Engine of Application State" (HATEOAS).


26
John, Rich chỉ đang giải thích sự thay đổi trong suy nghĩ của anh ấy. Không có gì chủ quan hoặc tranh luận về nó. Bỏ phiếu để tiếp tục mở - là một trong những câu hỏi hay hơn được gắn thẻ 'phần còn lại' mà tôi đã thấy trên SO.
Keith Gaughan

4
Keith, "giải thích sự thay đổi trong suy nghĩ" là điều anh ấy nên làm trong blog của mình, không phải trên SO.
John Saunders

13
Anh ấy không giải thích sự thay đổi trong suy nghĩ của mình, anh ấy đang hỏi liệu sự hiểu biết của mình có chính xác không.
aehlke

4
Tóm tắt xuất sắc. Tôi đã học được nhiều hơn từ câu hỏi này hơn là từ hầu hết các câu trả lời.
Martin Konecny

Câu trả lời:


21

Tôi nghĩ rằng lời giải thích của bạn chủ yếu bao gồm nó. URI là những số nhận dạng không rõ ràng, phần lớn, không được giao tiếp ngoài URI dấu trang được tác nhân người dùng sử dụng để truy cập ứng dụng.

Về phần tài liệu, câu hỏi này đã được thực hiện khá nhiều lần. Bạn ghi lại loại phương tiện của mình, cùng với các điều khiển siêu kết nối mà nó chứa (liên kết và biểu mẫu) và mô hình tương tác nếu bạn muốn (xem AtomPub).

Nếu bạn ghi lại các URI hoặc cách xây dựng chúng, bạn đang làm sai.


Điều này có còn đúng không? Có các thông số kỹ thuật phản hồi API như Ionspec đã tạo các URI này như một phần của phản hồi có chủ ý.
Sean Pianka

Vâng họ co. Tại thời điểm đó, câu hỏi đặt ra là phải tìm hiểu xem liệu các URI được ghi lại đó chỉ là các điểm vào ứng dụng, được đảm bảo ở một thông số kỹ thuật đi thẳng vào mã, ngăn máy chủ cho máy khách biết về cách nó có thể thực hiện mọi việc. Nếu khách hàng nghĩ rằng họ biết do hợp đồng đó, bạn không ở trong siêu phương tiện truyền thông, bạn đang thích mô hình xà phòng openapi hiện đại, với những vấn đề tương tự bạn đã gặp phải với 18 năm trước.
SerialSeb

Điều đúng là nhiều ngôn ngữ tài liệu API đã hình thành trong 11 năm qua, nhưng các nguyên tắc cơ bản không thay đổi. Tôi tin rằng giá trị trong việc khám phá các liên kết đó, hoặc ít nhất là khám phá mẫu URI, nằm ở việc xây dựng mã máy khách chung có thể tái sử dụng có thể sử dụng động các liên kết đó, cho phép nhiều triển khai ở phía máy chủ sử dụng lại cùng một mã máy khách. Việc nhúng URI tiếp tục tạo ra các tình huống khó hơn như vậy, nhưng nếu bạn sử dụng các định dạng đó, bạn có xu hướng kết hợp chặt chẽ một ứng dụng khách được tạo từ các thông số kỹ thuật đó, vì vậy bạn đã mất tính năng đó.
SerialSeb

8

Cách giải thích của bạn có vẻ đúng với tôi. Tôi tin rằng các ràng buộc của Fielding có thể được áp dụng trên thực tế.

Tôi thực sự muốn thấy ai đó xuất bản một số ví dụ hay về cách ghi lại giao diện REST. Có rất nhiều ví dụ kém, có một số ví dụ hợp lệ để hướng người dùng đến sẽ rất có giá trị.


2
Chà. Trang Mô hình Tài nguyên đó khiến tôi cay mắt. Hãy hy vọng điều này bắt đầu một xu hướng.
Darrel Miller

Thật tiếc đây là ví dụ duy nhất về một API như vậy trên web! Tệ hơn nữa, không có ví dụ tốt nào về mã khách hàng tuân theo nguyên tắc cả (mà tôi đã tìm thấy).
jkp

1
@DarrelMiller Nhưng các Loại Phương tiện đó không quá "cụ thể" sao? Đối với tôi, dường như API của họ thực sự chỉ sử dụng một MIME: application/jsonvà rằng Mô hình Tài nguyên thực sự là các mối quan hệ. Tôi có hiểu sai khía cạnh này của REST không? Tôi cũng đã đọc một trong SO câu trả lời của bạn mà dường như chỉ ra rằng những hợp đồng "một thuộc tính" nên tránh ...
edsioufi

2
@RichApodaca Liên kết của bạn đã chết vì bệnh kiết lỵ. web.archive.org/web/20170409132237/https://kenai.com/projects/...
forresthopkinsa

5

Tôi đã tìm kiếm một ví dụ điển hình về một API được viết theo HATEOAS và gặp sự cố khi tìm một API (tôi thấy cả API SunCloud và AtomPub đều khó áp dụng cho tình huống API "bình thường"). Vì vậy, tôi đã thử làm một ví dụ thực tế trên blog của mình theo lời khuyên của Roy Fieldings về ý nghĩa của việc triển khai REST thích hợp. Tôi cảm thấy rất khó để đưa ra ví dụ này, mặc dù thực tế là về nguyên tắc nó khá đơn giản (chỉ gây nhầm lẫn khi làm việc với một API chứ không phải một trang web). Tôi hiểu những gì Roy đang giải quyết và đồng ý, đó chỉ là một sự thay đổi trong tư duy để triển khai đúng cách cho một API.

Hãy xem: Ví dụ API sử dụng Rest


4

Một ngoại lệ khi đưa ra hướng dẫn về cách xây dựng URI là có thể gửi một mẫu URI trong phản hồi siêu văn bản, với các trường được thay thế tự động bởi ứng dụng khách, sử dụng các trường khác trong siêu văn bản. Điều này thường không giúp tiết kiệm nhiều băng thông mặc dù vì nén gzip sẽ xử lý các phần lặp lại của URI đủ tốt để không bận tâm đến điều này.

Một số thảo luận hay về REST và HATEOAS liên quan:

Ưu điểm của (Ngoài ra) Sử dụng HATEOAS trong API RESTFul

Cách uống một tách cà phê



4

Điều mà hầu hết mọi người sai là (ít nhất là tôi nghĩ) trong thế giới REST, bạn không ghi lại "Giao diện nghỉ ngơi" của mình, những gì bạn ghi lại là một loại phương tiện, độc lập với máy chủ hoặc dịch vụ của bạn.


2

Tôi nghĩ rằng trong số năm mà REST đã tồn tại, các nhà công nghệ đã hiểu về khái niệm Nguồn lực và thực sự RESTful là gì hay không.

Theo Mô hình trưởng thành của Richardson, có 4 cấp độ (0-3) xác định mức độ RESTful API của bạn, với 3 có nghĩa là một API RESTful thực sự, giống như Roy Fielding dự định.

Mức 0 là khi bạn có một URI điểm vào - như SOAP.

Mức 1 có nghĩa là API có thể phân biệt giữa các tài nguyên khác nhau và có nhiều hơn một điểm vào - vẫn có mùi SOAP.

Cấp độ 2 là khi bạn sử dụng các động từ HTTP - chủ yếu GET, POST, DELETE. Đây là mức mà REST thực sự đi vào hình ảnh.

Ở Cấp độ 3, bạn bắt đầu sử dụng các điều khiển siêu phương tiện để làm cho API của bạn thực sự RESTful.

Các liên kết được đề xuất để đọc thêm:


1

Chuẩn xác. Ngoài ra, tôi cũng lưu ý rằng các mẫu URI hoàn toàn tốt trong một ứng dụng RESTful miễn là các mẫu đó là từ các tài liệu nhận được từ máy chủ (OpenSearch là một ví dụ phù hợp). Đối với mẫu URI, bạn ghi lại nơi chúng đang được sử dụng và trình giữ chỗ dự kiến ​​trong mẫu là gì, nhưng không ghi lại chính các mẫu. Hơi trái ngược với những gì Wahnfrieden đã nói, đây không phải là một ngoại lệ.

Ví dụ: tại nơi làm việc của tôi, chúng tôi có hệ thống quản lý miền nội bộ và tài liệu dịch vụ chỉ định hai mẫu URI: một mẫu để tạo URI phỏng đoán tốt nhất cho tài nguyên miền và mẫu khác để xây dựng URI để truy vấn tính khả dụng của miền. Vẫn có thể duyệt qua bộ sưu tập tên miền để tìm ra URI của một tên miền nhất định là gì, nhưng với số lượng lớn các tên miền mà nó quản lý, điều này sẽ không khả thi đối với khách hàng, vì vậy hãy cho họ một cách để đoán xem URI của tài nguyên miền có thể là một chiến thắng lớn về mặt dễ triển khai từ quan điểm của khách hàng và băng thông từ máy chủ.

Đối với câu hỏi của bạn: Tài liệu quy chuẩn của chúng tôi là các tài nguyên tiếp xúc, ảnh hưởng của các phương pháp khác nhau đối với các tài nguyên đó và các loại phương tiện biểu diễn được sử dụng và các lược đồ của chúng cũng như loại tài nguyên mà URI trong các biểu diễn đó trỏ đến.

Chúng tôi cũng bao gồm tài liệu không quy chuẩn (cung cấp thông tin) đính kèm với tài liệu tuyên bố từ chối trách nhiệm không đọc quá nhiều vào các URI được đề cập trong tài liệu, cung cấp các ví dụ về tương tác máy khách-máy chủ điển hình. Điều này đặt các tài liệu quy chuẩn khá trừu tượng trong các thuật ngữ cụ thể.


1
Bạn có thể cung cấp các mẫu URI như là một phần của API của bạn, nằm ngoài dải tần. Chỉ VUI LÒNG KHÔNG gọi đây là REST, bởi vì nó không phải. Đó là một số lượng lớn các khớp nối và chính xác là những gì REST được thực hiện để tránh. Nhưng như bạn nói, REST không dành cho mọi ứng dụng. Vì vậy, đừng giả vờ mọi ứng dụng đều là REST.
aehlke

1
Thực ra, tôi đồng ý. Tôi tin rằng đó là những gì tôi đã nói. Tuy nhiên, tôi thực sự không thể thấy bất kỳ lý do chính đáng nào để cung cấp các mẫu URI nằm ngoài dải.
Keith Gaughan

0

Hãy giả sử GET /foos/createFormđược gọi để nhận các giá trị trường biểu mẫu mà chúng phải được cung cấp khi chúng ta tạo POST /foos. Bây giờ, URL cụ thể này, tức là số 1 được sử dụng để tạo foos sẽ được đề cập trong phản hồi với GET /foos/createFormtư cách là một liên kết hành động gửi theo đề xuất của Fielding, phải không?
Sau đó, lợi ích của việc ánh xạ các hành động với các động từ Http nổi tiếng thành các hành động là gì, điều "quy ước qua mã / cấu hình" bị vô hiệu hóa.

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.