开发者

URL design for an API

开发者 https://www.devze.com 2023-01-30 03:23 出处:网络
I\'m working on a private apis for our backend. I have collections that have associations. Each collection can be requested, paginated, you can also ask for the associations and paginate this associat

I'm working on a private apis for our backend.

I have collections that have associations.

Each collection can be requested, paginated, you can also ask for the associations and paginate this associations.

We're not sure about which URL design to use ... we're thinking about :

  • /users.json?per_page=10&association=parts,auditions&parts_per_page=5&auditions_per_page=5

  • /users.json?per_page=10&association[]=parts&association[]=auditions&parts_per_page=5&auditions_per_page=10

  • 开发者_运维技巧/users.json?per_page=10&association[auditions]=true&association[parts][per_page]=5

What do you think ? which one would you chosse ? why ? is one of this not looking like valid url schemes ?

Thanks !


My answer: /users.json. HTTP is optimized for large-grain hypermedia transfer; caching is a big part of this, and none of the URI schemes given above are very cache-friendly.

Squid, for example, is a popular HTTP cache that by default will not cache any URL that has a querystring. In addition, many clients and even servers and intermediaries generate and consume query string parameters in an undefined order; that is, "?a=3&b=5" can be arbitrarily rewritten as "?b=5&a=3". However, for HTTP caching, the order matters, and the two pages will be cached separately even though they have the same content. As you add parameters, this problem increases exponentially.

You should design your resources (and their representations) to take advantage of caching by two opposing but complementary techniques:

  1. Combine fragmented and partial representations into larger, unified representations, and
  2. Separate large, unified representations into smaller representations along cache boundaries (which tend to be transactional boundaries), but related by hyperlinks.

In your case, step 1 implies combining associations and parts into the "users" representation, without any option for the client to configure which ones and how many. That will allow you to aggressively cache the single response representation without overloading your (and their) caches with a combinatorial explosion of responses due to all the querystring options.

Step 2 implies separating /users.json into separate "user" entities, each with an "associations" resource and a "parts" resource. So /users/{id} and /users/{id}/associations and /users/{id}/parts. The "/users" resource then returns an array of hyperlinks to the individual "/users/{id}" resources, and each "/users/{id}` representation contains hyperlinks to its associations and parts (that part is more malleable--it might fit your application better to embed the associations and parts into the user resource directly). That will allow you to aggressively cache the response for each "in demand" resource without having to cache your whole database.

Then your users will scream "but that's 10 times the network traffic!" To which you calmly respond, "no, that's 1/10th the network traffic, because 9 times out of 10 the requested resources are already sitting in your client-side (browser) cache (and when they're not, it's 1/10th the server's computational resources since they're sitting in a server-side cache, and when they're not there either, we avoid stampeding with a smart cache on the server)."

Of course, if the /users resource is something a million new visitors hit every day, then your optimization path might be different. But it doesn't seem so based on your example URI schemes.


There are a lot of useful posts under the restful-url tag.

Some useful posts:

Do REST API URLs have to look like this?

Best practices on using URIs as parameter value in REST calls.

How to create REST URL's without verbs?


I would go for the 1st one. I don't like to see the [] notation on the url, IMHO it makes harder for the client to both use and understand. A few changes as suggestions.

1) As association seems to be an array, change for associations (plural, if I am right and it is an array)

2) You can also try to put a default per_page and an optional one, even aggregating, something like per_page_parts_auditions instead of using both per_page_parts and per_page_auditions. I wouldn't do it if your API was designed to be public, since it makes easier to use but harder to understand, but as you posted it is a private one.. should be a good way to avoid replication.

0

精彩评论

暂无评论...
验证码 换一张
取 消