2013-07-08 30 views
7

Theo nguyên tắc HATEOAS mà mỗi tiểu bang nên được siêu liên kết, cách tốt nhất để tạo mô hình liên kết thay đổi trạng thái tài nguyên là gì?HATEOAS - Cách mô hình quan hệ liên kết thay đổi trạng thái

Hãy lấy ví dụ cổ điển với đơn đặt hàng:

{ 
    id : 12, 
    state: 'pending', 
    ..., 
    links: [ 
    ..., 
    { 
     rel: 'cancel', 
     href: '/orders/12/cancel' 
    }, 
    ... 
    ] 
} 

Tôi không totall hạnh phúc với điều đó "/ hủy" phần - Tôi sẽ cảm thấy tốt hơn rất nhiều nếu tôi có thể gửi "PUT" Yêu cầu với nội dung:

{ 
    status:'cancelled' 
} 

Nhưng làm cách nào để thể hiện điều đó với thuộc tính "href" trong phần liên kết? Tôi muốn đại diện cho các hành động có sẵn ở đó, ví dụ, hủy bỏ một đơn đặt hàng không phải lúc nào cũng có thể (trạng thái 'đã hoàn tất').

Một khả năng có thể là sử dụng URL như '/ orders/12? Action = cancel' những gì nó cảm thấy giống như phương pháp RPC và tôi đang thiếu thứ gì đó.

Một khả năng trông lẽ đẹp nhất, sẽ có liên hệ như thế:

{ 
    rel: 'cancel', 
    href: '/orders/12/', 
    type: 'PUT', 
    values: { 
    state: 'cancelled' 
    } 
} 

Giải pháp này có thể cảm thấy một chút dài dòng.

Bất kỳ ý tưởng nào về cách xử lý điều đó một cách duyên dáng? Có lẽ ai đó đã giải quyết "vấn đề" tương tự?

Trả lời

0

Tôi sẽ đề xuất một trong hai mô hình này. Đầu tiên là kiểu cổ điển, nhưng với số rel="edit-form" và sử dụng PATCH nếu có. Thứ hai là một lựa chọn thay thế thông qua một số suy nghĩ bên về cách mô hình tài nguyên HTTP ánh xạ vào mô hình miền ứng dụng của bạn (cụ thể là, hai không cần phải có ánh xạ 1: 1).


Giải pháp 1

Chỉnh sửa các tài nguyên tại chỗ.

HTML tương thích:

HTTP/1.1 200 OK 
Content-Type: text/html 
Location: /orders/1/ 

...<a rel="edit-form" href="./edit">Edit</a>... 

HTTP/1.1 200 OK 
Content-Type: text/html 
Location: /orders/1/edit 

... 
<form action="../" method="POST"> 
    <input type="hidden" name="_METHOD" value="PATCH"> 
    <button type="submit" name="status" value="cancelled">Cancel Order</button> 
</form> 
... 

POST /orders/1 HTTP/1.1 
Content-Type: application/x-www-form-urlencoded 

_METHOD=PATCH&status=cancelled 

giàu khách hàng (ví dụ HTML + Javascript) tương thích:

PATCH /orders/1 HTTP/1.1 
Content-Type: application/x-www-form-urlencoded 

status=cancelled 

và/hoặc

PATCH /orders/1 HTTP/1.1 
Content-Type: text/json 

{ 
    "status": "cancelled" 
} 

các _METHOD chính là một phương tiện nổi tiếng cung cấp khuôn khổ REST với phương pháp đúng do thiếu sự hỗ trợ cho HTTP HTML.


Giải pháp 2

Hoặc, Xóa tài nguyên (và, bất ngờ, tạo một hình mới)

DELETE /orders/1 HTTP/1.1 

HTTP/1.1 201 Created 
Location: /cancelled-orders/1 

Để biết thêm về cách này ánh xạ tài nguyên web cho đối tượng miền, vui lòng see my answer cho một câu hỏi tương tự.

Một câu trả lời khác mà bạn có thể muốn đọc là this one.

8

Tài nguyên mô hình là phần khó nhất của REST. Hoàn toàn tuân thủ các tiêu chuẩn nếu bạn thấy mình từng làm điều này: /resource/:id/{action}, bạn đang vi phạm tiêu chuẩn "sử dụng HTTP đúng", vì điểm cuối của bạn lý tưởng luôn là "danh từ", không bao giờ "động từ" (động từ là HTTP giao thức cung cấp)

vì vậy, trong khi "nó phụ thuộc" (tức là phần cứng của thiết kế nguồn lực), điển hình là:.. Object bang mô hình có thể được coi là nguồn lực tự

Điều đó có nghĩa, đặt hàng của bạn. trạng thái thực sự là tài nguyên mà bạn có thể truy vấn (hoặc là tài nguyên độc lập /orderstatuses hoặc dưới dạng tài nguyên phụ, ví dụ: /orders/:id/status)

Trạng thái đơn đăng ký của bạn hiện có thể liên kết với tài nguyên trạng thái dựa trên trạng thái hiện tại của đơn đặt hàng. Nếu 'tình trạng' của bạn schema trông giống như thế này (giả):

key: 'status' 
values: ['pending', 'cancelled'] 

Ứng dụng của bạn có thể sau đó PUT /order/:id/status {status:'cancelled'} (một tình trạng cũng được hình thành) trở về API, mà sau đó sẽ hành động để hủy bỏ đơn đặt hàng. Đó là một chút suy nghĩ kỳ lạ trong các điều khoản này (RPC là trực quan hơn rất nhiều), nhưng hy vọng điều này sẽ giúp.

1

Bạn phải mô tả các biểu mẫu bằng cách nào đó. Bạn "verbose" Giải pháp là hoàn toàn okay:

{ 
    rel: 'cancel', 
    href: '/orders/12/', 
    type: 'PUT', 
    values: { 
    state: 'cancelled' 
    } 
} 

lưu ý: bạn phải xác định một kiểu tùy chỉnh MIME hoặc sử dụng một loại MIME chung có khả năng hình thức mô tả (ví dụ như bộ sưu tập + json), hoặc có một RDF type (hỗ trợ REST vocabs như Hydra) - aka. giao diện thống nhất/tin nhắn tự mô tả

tôi muốn đại diện cho hành động sẵn có từ đó, ví dụ, việc hủy đơn hàng không phải lúc nào cũng có thể ('hoàn thành' nhà nước).

Nếu không có sẵn thao tác, thì đừng gửi liên kết trỏ đến thao tác đó.

0

Thêm vào câu trả lời của papercowboy, nơi chuyển đổi trạng thái không phải lúc nào cũng có sẵn, bạn có thể ghi lại những gì hiện có thể làm tài nguyên, ví dụ:

/order/:id/availableStates 

{ 
    "availableStates": [ 
     {"status": "cancelled"} 
    ] 
}