Tôi cảm thấy hơi buồn khi thấy rằng sau hơn 10 năm, không có câu trả lời nào thực sự nêu rõ làm thế nào một thứ như yêu cầu trong OP có thể được thiết kế theo kiến trúc REST, do đó tôi cảm thấy cần phải làm điều này ngay bây giờ.
Đầu tiên, REST là gì?! Từ viết tắt REST hoặc ReST là viết tắt của "Chuyển giao trạng thái đại diện" và định nghĩa việc trao đổi trạng thái của tài nguyên theo một định dạng biểu diễn nhất định. Các định dạng đại diện là thủy triều cho loại phương tiện đàm phán. Trong trường hợp application/html
định dạng biểu diễn có thể là một luồng nội dung văn bản được định dạng HTML được hiển thị trong trình duyệt, có thể sau khi áp dụng một số định dạng biểu định kiểu để định vị các thành phần nhất định tại các vị trí nhất định.
Về nguyên tắc, REST là một sự khái quát hóa của Web có thể duyệt mà chúng ta đều biết, mặc dù nhắm mục tiêu tất cả các loại ứng dụng và không chỉ các trình duyệt. Do đó, theo thiết kế, các khái niệm tương tự áp dụng cho Web cũng áp dụng cho kiến trúc REST. Một câu hỏi như làm thế nào để đạt được điều gì đó theo cách "RESTful" giải quyết xung quanh việc trả lời câu hỏi làm thế nào để đạt được điều gì đó trên trang Web và sau đó áp dụng các khái niệm tương tự lên lớp ứng dụng.
Một máy tính dựa trên Web thường có thể bắt đầu với một số "trang" cho phép bạn nhập một số giá trị để tính toán trước khi gửi dữ liệu đã nhập đến máy chủ. Trong HTML, điều này thường đạt được thông qua <form>
các phần tử HTML dạy cho khách hàng về các tham số có sẵn để đặt, vị trí đích để gửi yêu cầu cũng như định dạng biểu diễn để áp dụng khi gửi dữ liệu đầu vào. Điều này có thể có nghĩa là như thế này:
<html>
<head>
...
</head>
<body>
<form action="/../someResource" method="post" enctype="application/x-www-form-urlencoded">
<label for="firstNumber">First number:</label>
<input type="number" id="firstNumber" name="firstNumber"/>
<label for="secondNumber">Second number:</label>
<input type="number" id="secondNumber" name="secondNumber"/>
<input type="submit" value="Add numbers"/>
</form>
</body>
</html>
Mẫu ở trên tức là có hai trường đầu vào có thể được điền bởi người dùng hoặc bởi một số automata khác và khi gọi phần tử đầu vào gửi, trình duyệt sẽ xử lý định dạng dữ liệu đầu vào thành application/x-www-form-urlencoded
định dạng đại diện được gửi đến vị trí đích được đề cập thông qua phương thức yêu cầu HTTP được chỉ định, POST
trong trường hợp này. Nếu chúng ta nhập 1
vào trường firstNumber
đầu vào và 2
vào trường secondNumber
đầu vào, trình duyệt sẽ tạo ra một đại diện firstNumber=1&secondNumber=2
và gửi nó dưới dạng trọng tải cơ thể của yêu cầu thực tế đến tài nguyên đích.
Do đó, yêu cầu HTTP thô được cấp cho máy chủ có thể trông như thế này:
POST /../someResource
Host: www.acme.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 28
Accept: application/html
firstNumber=1&secondNumber=2
Máy chủ có thể thực hiện tính toán và trả lời với một trang HTML khác có chứa kết quả của phép tính, vì yêu cầu chỉ ra rằng máy khách hiểu định dạng này.
Như Breton đã chỉ ra, không có URL hay URI "RESTful" nào. URI / URL là loại điều riêng của nó và không nên truyền đạt bất kỳ ý nghĩa nào cho khách hàng / người dùng. Trong mẫu máy tính ở trên, người dùng chỉ đơn giản là không quan tâm đến việc gửi dữ liệu tới đâu, chỉ quan tâm đến việc khi kích hoạt trường nhập dữ liệu, yêu cầu được gửi. Tất cả các thông tin cần thiết để thực hiện nhiệm vụ đã được cung cấp bởi máy chủ.
Một trình duyệt cũng có thể không nhận thức được rằng yêu cầu thực sự cung cấp cho máy tính một số tham số đầu vào, nó cũng có thể là một dạng đơn đặt hàng trả về đại diện biểu mẫu tiếp theo để tiếp tục quá trình đặt hàng hoặc một loại hoàn toàn khác nguồn. Nó chỉ đơn giản thực hiện những gì đặc tả HTML yêu cầu trong trường hợp như vậy và nó không quan tâm đến những gì máy chủ thực sự đang làm. Khái niệm này cho phép trình duyệt sử dụng cùng một định dạng đại diện để thực hiện tất cả các loại việc như đặt hàng một số thứ từ cửa hàng trực tuyến ưa thích của bạn, trò chuyện với những người bạn thân nhất của bạn, đăng nhập vào tài khoản trực tuyến, v.v.
Các affordance của một số yếu tố, chẳng hạn trong trường hợp nộp lĩnh vực đầu vào mà thường được trả lại như nút, định nghĩa những gì bạn nên đến với nó. Trong trường hợp của một nút hoặc một liên kết, về cơ bản nó sẽ cho bạn nhấp vào nó. Các yếu tố khác có thể truyền đạt chi phí khác nhau. Khả năng chi trả như vậy cũng có thể được thể hiện thông qua các mối quan hệ liên kết, tức là với preload
các liên kết được chú thích về cơ bản cho khách hàng biết rằng nó có thể tải nội dung của tài nguyên được liên kết trong nền vì người dùng rất có thể sẽ lấy nội dung này tiếp theo. Các mối quan hệ liên kết như vậy tất nhiên phải được chuẩn hóa hoặc tuân theo cơ chế mở rộng cho các loại quan hệ như được xác định bởi liên kết Web .
Đây là những khái niệm cơ bản được sử dụng trên Web và cũng nên được sử dụng trong kiến trúc REST. Theo "Chú Bob" Robert C. Martin, một kiến trúc là về ý định và ý định đằng sau kiến trúc REST là tách rời các máy khách khỏi các máy chủ để cho phép các máy chủ phát triển tự do trong tương lai mà không phải sợ chúng phá vỡ máy khách. Thật không may, điều này đòi hỏi rất nhiều kỷ luật vì nó rất dễ dàng để giới thiệu khớp nối hoặc thêm các giải pháp khắc phục nhanh để hoàn thành công việc và tiếp tục. Như Jim Webber đã chỉ ra trong kiến trúc REST, với tư cách là nhà cung cấp dịch vụ, bạn nên cố gắng thiết kế một giao thức ứng dụng miền tương tự như trò chơi máy tính dựa trên văn bản của thập niên 70 mà khách hàng sẽ thực hiện cho đến khi họ kết thúc quá trình.
Rất nhiều cái gọi là API "REST" không may làm trong thực tế là tất cả mọi thứ trừ cái đó. Bạn thấy việc trao đổi dữ liệu chủ yếu dựa trên JSON được chỉ định trong tài liệu bên ngoài cụ thể API thường khó tích hợp một cách linh hoạt khi đang di chuyển. Định dạng của một yêu cầu cần trông như thế nào cũng được mã hóa vào tài liệu bên ngoài dẫn đến nhiều URI diễn giải để trả về các ty được xác định trướcthay vì sử dụng một số định dạng đại diện phổ biến được đàm phán trả trước. Điều này ngăn máy chủ thay đổi vì hiện tại khách hàng sẽ nhận được một định dạng dữ liệu nhất định (lưu ý không phải định dạng đại diện!) Cho các URI được xác định trước. Ngoài ra, việc trao đổi định dạng dữ liệu tùy chỉnh này còn ngăn khách hàng tương tác với các API khác vì "định dạng dữ liệu" thường được chuyển sang một API cụ thể. Chúng ta biết khái niệm này từ quá khứ từ các công nghệ RPC như Corba, RMI hoặc SOAP mà chúng ta lên án là xấu xa, mặc dù Peppol đã chuyển sang sử dụng lại bằng cách thay thế AS2 bằng AS4 làm giao thức chuyển mặc định như gần đây.
Liên quan đến câu hỏi thực tế, việc gửi dữ liệu dưới dạng tệp csv không có gì khác so với sử dụng application/x-www-form-urlencoded
biểu diễn hoặc nội dung tương tự. Jim Webber đã nói rõ rằng sau tất cả HTTP chỉ là một giao thức truyền tải mà miền ứng dụng của nó là chuyển tài liệu qua Web . Máy khách và máy chủ ít nhất phải hỗ trợ cả hai text/csv
như được định nghĩa trong RFC 7111 . Tệp CSV này có thể được tạo do hậu quả của việc xử lý loại phương tiện xác định các thành phần biểu mẫu, thành phần đích hoặc thuộc tính để gửi yêu cầu cũng như phương thức HTTP để thực hiện tải lên cấu hình.
Có một số loại phương tiện hỗ trợ các biểu mẫu như HTML , HAL Forms , halform , ion hoặc Hydra . Tuy nhiên, hiện tại tôi không biết loại phương tiện tự động có thể mã hóa dữ liệu đầu vào thành text/csv
trực tiếp do đó có thể cần phải được xác định và đăng ký với sổ đăng ký loại phương tiện của IANA .
Tôi đoán việc tải lên và tải xuống bộ tham số hoàn chỉnh không phải là vấn đề. Như đã đề cập trước đó, URI mục tiêu không liên quan vì khách hàng sẽ chỉ sử dụng URI để truy xuất nội dung mới để xử lý. Lọc theo ngày làm việc cũng không nên khó khăn. Tuy nhiên, ở đây máy chủ nên ứng dụng khách với tất cả các khả năng khách hàng có thể chọn. Trong những năm gần đây, GraphQL và RestQL đã phát triển để giới thiệu một ngôn ngữ giống như SQL có thể được nhắm mục tiêu tại một điểm cuối nhất định để có được phản hồi được lọc. Tuy nhiên, theo nghĩa REST thực sự, điều này vi phạm ý tưởng đằng sau REST là a) GraphQL tức là chỉ sử dụng một điểm cuối duy nhất ngăn chặn việc sử dụng bộ nhớ đệm tối ưu và b) đòi hỏi kiến thức về các trường có sẵn, điều này có thể dẫn đến việc kết nối các máy khách đến mô hình dữ liệu cơ sở của tài nguyên.
Kích hoạt hoặc hủy kích hoạt một số tham số cấu hình nhất định chỉ đơn giản là vấn đề kích hoạt các điều khiển hypermedia cung cấp khả năng chi trả này. Trong các biểu mẫu HTML, đây có thể là hộp kiểm đơn giản hoặc lựa chọn nhiều dòng trong danh sách hoặc loại đó. Tùy thuộc vào hình thức và phương thức mà nó xác định, sau đó nó có thể gửi toàn bộ cấu hình thông qua PUT
hoặc thông minh về các thay đổi được thực hiện và chỉ thực hiện cập nhật một phần thông qua PATCH
. Cái thứ hai về cơ bản đòi hỏi một tính toán của biểu diễn thay đổi cho một bản cập nhật và cung cấp cho máy chủ các bước cần thiết để chuyển đổi biểu diễn hiện tại thành biểu diễn mong muốn. Theo đặc tả PATH, điều này phải được thực hiện trong một giao dịch để tất cả hoặc không có bước nào được áp dụng.
HTTP cho phép và khuyến khích một máy chủ xác nhận trả trước yêu cầu đã nhận trước khi áp dụng các thay đổi. Đối với PUT, các thông số kỹ thuật:
Máy chủ gốc NÊN xác minh rằng đại diện PUT phù hợp với bất kỳ ràng buộc nào mà máy chủ có đối với tài nguyên đích không thể hoặc sẽ không bị thay đổi bởi PUT. Điều này đặc biệt quan trọng khi máy chủ gốc sử dụng thông tin cấu hình bên trong liên quan đến URI để đặt các giá trị cho siêu dữ liệu đại diện trên các phản hồi GET. Khi biểu diễn PUT không phù hợp với tài nguyên đích, máy chủ gốc NÊN làm cho chúng nhất quán, bằng cách chuyển đổi biểu diễn hoặc thay đổi cấu hình tài nguyên hoặc phản hồi với thông báo lỗi thích hợp chứa đủ thông tin để giải thích tại sao biểu diễn không phù hợp. Mã trạng thái 409 (Xung đột) hoặc 415 (Loại phương tiện không được hỗ trợ) được đề xuất,
Ví dụ: nếu tài nguyên đích được định cấu hình để luôn có Loại nội dung "văn bản / html" và đại diện là PUT có Loại nội dung là "hình ảnh / jpeg", thì máy chủ gốc phải thực hiện một trong:
a. cấu hình lại tài nguyên đích để phản ánh loại phương tiện mới;
b. chuyển đổi biểu diễn PUT thành định dạng phù hợp với định dạng của tài nguyên trước khi lưu nó dưới dạng trạng thái tài nguyên mới; hoặc là,
c. từ chối yêu cầu với phản hồi 415 (Loại phương tiện không được hỗ trợ) cho biết rằng tài nguyên đích bị giới hạn ở "text / html", có lẽ bao gồm một liên kết đến một tài nguyên khác sẽ là mục tiêu phù hợp cho đại diện mới.
HTTP không xác định chính xác làm thế nào một phương thức PUT ảnh hưởng đến trạng thái của máy chủ gốc ngoài những gì có thể được thể hiện bằng ý định của yêu cầu tác nhân người dùng và ngữ nghĩa của phản hồi của máy chủ gốc. ...
Để tổng hợp bài đăng này, bạn nên sử dụng loại phương tiện hiện có cho phép bạn dạy khách hàng về các tham số đầu vào được yêu cầu hoặc được hỗ trợ, vị trí mục tiêu để gửi yêu cầu đến, thao tác sử dụng cũng như loại phương tiện yêu cầu phải được định dạng hoặc xác định yêu cầu của riêng bạn mà bạn đăng ký với IANA. Cái sau có thể là cần thiết nếu bạn muốn chuyển đổi đầu vào thànhtext/csv
và sau đó tải lên đại diện CSV lên máy chủ. Việc xác nhận phải xảy ra trước khi những thay đổi được áp dụng cho tài nguyên. URI thực tế không nên liên quan đến các khách hàng ngoài việc xác định nơi gửi yêu cầu đến và do đó, người triển khai dịch vụ có thể tự do lựa chọn. Bằng cách làm theo các bước này, bạn có thể tự do thay đổi phía máy chủ của mình bất cứ lúc nào và khách hàng sẽ không bị hỏng do hậu quả nếu họ hỗ trợ các loại phương tiện đã sử dụng.