REST API Design links between collections of resou

2020-08-16 08:29发布

问题:

I have been pondering the correct method of defining resource collections which have interdependence.

For instance, lets consider "documents" and "comments" which are independently accessible via the URI's:

/documents/{doc-uri}
/comments/{comment-id}

However, we typically want the collection of comments related to a specific document. Which creates a design question around how this should be archetected.

I can see a few main options:

1.) Supply an collection uri after the document uri for comments

GET /documents/{doc-uri}/comments/

2.) Provide a parameter to the comments collection to select by document

GET /comments/{comment-id}?related-doc={doc-uri}

3.) Use content negotiation to request the related comments be returned via the Accept header.

// Get all the comments for a document
GET /documents/{doc-uri} Accept: application/vnd.comments+xml
// Create a new comment
POST /documents/{doc-uri} Content-Type: application/vnd.comment+xml <comment>...</comment>

Method 1 has the advantage of automatically putting the comments in context of the document. Which is also nice when creating,updating and deleting comments using POST/PUT. However it does not provide global access to comments outside the context of a document. So if we wanted to do a search over all comments in the system we would need method #2.

Method 2 offers many of the same benefits as #1, however creating a comment without the context of a document makes no sense. Since comments must explicitly be related to a document.

Method 3 is interesting from a GET and POST/create perspective, but gets kinda hairy with update and delete.

I can see pro's and con's to all these methods so I am looking for some more guidance from someone who may have approached and solved this issue before.

I am considering doing both methods 1 & 2, thus I can provide all the functionality needed, but I am concerned I may be over-complicating/duplicating functionality.

回答1:

REST API must be hypermedia-driven. See Hypermedia as the Engine of Application State (HATEOAS) constraint. So, don't waste your time on URLPatterns, because they are not RESTful. URLPattern implicates tight-coupling between a client and a server; simply, the client must be aware of how URLs look like and has an ability to construct them.

Consider this REST design for your use-case:

The representation of a document contains a link where the client can POST comments or with using of GET get all comments on the document. e.g.

{
  ...
  "comments" : {
      "href": ".. url ..",
      "rel": ["create-new-comment", "list-comments"]
  }
}

A client just takes this URL and performs GET or POST method on the URL; without a knowledge how the URL is, looks like.

See also this post:

http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven



回答2:

The combination of methods 1 and 2 looks good, as you say in method 2, don't have too much sense create comments without a document context since a parent child relationship exists between both, if you delete a document is acceptable to delete all his comments also, you can make your/comments/ uri a read-only resource in order to avoid his creation without a document.

As filip26 says rest apis should be hypermedia driven but that not means that the url patterns aren't important, you could have a resource with one uri or many, if your resources have multiple uris is easier for clients to find them, the downside is that could be confusing because some clients use one uri instead of another, so you can use a canonical uri for a resource, when a client access a resource throught this canonical uri you can send back a 200 OK, when a client request one of the others uri you can send back a 303 "See also" along with the canonical uri.`



标签: api rest