Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
329 views
in Technique[技术] by (71.8m points)

uri - REST resource path design

I'm developing a REST service, and I'm trying to adhere to Doctor Roy Fielding's conventions and guidelines.

I picture my service as an endpoint that exposes a set of resources. A resource is identified by an URI, and api clients can manipulate resources by using using HTTP semantics (i.e., different HTTP verbs map to the corresponding operations over URIs).

Guidelines state that these URIs should be defined in an hierarchical way, reflecting object hierarchy. This renders useful in resource creating, because on the backend we need the data to perform the create operation. However, on further manipulations, a lot of the information included in the URI is not even going to be used by the service, because generally the resource Id alone is enough to uniquely identify the operation target.

An example: Consider an Api that exposes the creation and management of products. Consider also that a product is associated with a brand. On creation it makes sense that the following action is performed: HTTP POST /Brand/{brand_id}/Product [Body containing the input necessary to the creation of the product]

The creation returns an HTTP 201 created with a location header that exposes the newly created product's location.

On further manipulations, clients could access the product by doing: HTTP PUT /Brand/{brand_id}/Product/{product_id} HTTP DELETE /Brand/{brand_id}/Product/{product_id} etc

However, since the product Id is universal in the product scope, the following manipulations could be performed like this: /Product/{product_id} I am only keeping the /Brand/{brand_id} prefix for coherence reasons. In fact, the brand id is being ignored by the service. Do you thing that this is a good practice, and is reasonable for the sake of maintaining a clear, unambiguous ServiceInterface definition? What are the benefits of doing this, and is this the way to go at all?

Also any pointers on URI definition best practices would be appreciated.

Thanks in advance

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You are saying:

Guidelines state that these URIs should be defined in an hierarchical way, reflecting object hierarchy.

While it is often done this way it is not really relevant for a RESTful API design. Roy Fielding has a nice article addressing common misconceptions about REST. There he even says:

A REST API must not define fixed resource names or hierarchies (an obvious coupling of client and server).

and

A REST API should be entered with no prior knowledge beyond the initial URI …

So don't encode information in your URL that should be passed inside the resource. A RESTful API should work even if you replace all your URLs with artificial and non-sensical URIs. (I like understandable URIs as anybody but as an mental exercise to check your "RESTfullness" it's quite good.)

The problem to model an URI for an object "hierarchy" is that the hierarchy isn't very often as obvious as it seems. (What is the object hierarchy between teacher, course, and student?). Often objects are in a web of relations and belong not clearly beneath another object. A product might belong to a brand but you might have multiple supplier (covering a subset of products for multiple brands). And REST is wonderful to express complex nets of relations. The whole internet/web works this way.

Instead of encoding the relationship in the hierarchy just define a hyperlink in your resource pointing to the related objects.

For your specific example I would use POST /product/ to create a new product and have a link to your /brand/xzy in the resource representation when creating the product.

If you want to know which products are defined for a specific brand, just include a list of links in the returned representation for GET /brand/xzy. If you want to have an explicit resource representing for this relationship you still could define GET /brand/{id}/products as an URL (or /brandproducts/xzy or /34143453453) and return it as a link in your brand resource.

Don't think so much about the design of your URIs, think more about the information you provide in your resources. Make sure it provides links to all the resource representations your client might want to view or manipulate after receiving it from your API.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...