开发者

The best practices for specific scenarios in RESTful Services

I have two quick questions which I just want to get the community's opinions on -

  1. If I have an entity which can be accessed with either an ID or a date (20110705), what's the best practice for the convention of the url used to access the entity?

    • GET : /myEntities/{date} and /myEntities/{id} ? (which the service will parse the {object} to check if it is a date or an id.

    • GET : /myEntities/date/{date} and /myEntities/id/{id}*?

  2. In WCF Rest, I can also do /myEntities/?date={date} and /myEntities/?id={id}, is this a good practice of REST? In other words, is it acceptable in terms of best practices to use ?date={date} instead of dat开发者_如何学Pythone/{date}/ like it is just a simply personal preference?

Thanks in advance.


I feel like a lot of this comes down to preference and style.

Having said that, I'd personally prefer:

/myEntities/date/{date} and /myEntities/{id}

No need to be explicit with the ID option; it's assumed.

In regards to #2; I personally don't like this syntax: /myEntities/?date={date} if it's implemented in WCF as a URI Template - because if you have more than one parameter the assumption is the order of the parameters can be jostled around - but they can't with the URI Template. But, as standard query string parameters, this is perfectly acceptable, and is done all over the place - Google, Yahoo, Amazon, and others all use this style. If anything, this is exactly what the 'query string' was meant for - parameters for a query... which is exactly what you're doing when retrieving entities by __.

(But I'm as curious as you are about what others will say).


/myEntities/date/{date} should redirect to /myEntities/{id} using 301 or 307 as appropriate for your app. This reduces the possibility for data to get out of sync due to multiple cached copies, and makes it clear to clients that /myEntities/date/* is just an alternate index, not a set of independent resources (as they might rightly expect if you did not redirect, due to the hierarchical nature of HTTP URI's).


A resource has one identifying URL (the self url if you will). That must NEVER change. That also means that if you risk changing that id at one point, then the id is not what you use in the url. If you risk recycling the id, then you definitely shouldn't use that id.

That also means, that you will never have two urls that will uniquely identify the same resource.

Now that doesn't mean, that you can't access the same resource from two different urls. There are many reasons why you would want to do that. There are just a few things that you need to make sure of.

You should make it very easily understandable for anyone that consumes your API what is happening. The options you have listed don't do that.

It basically comes down to modelling, and making sure your internal model doesn't bleed into the public api. The fact you might have an overloaded method that can take either an id or a date as input parameter, doesn't mean you should expose that overload.

So ask yourself what scenario each of the two situations solve, and then it might become apparent.

I don't like Steve's suggestion either. How would a consumer know that you can write 'date' instead of an id, and then all of a sudden access by date? It isn't intuitive.

So ask yourself if it is paramount to be able to use the date as part of the url, or if adding it as a querystring filter on the collection is better. That way you could actually expose a to and from date filter, that might be of even more value as well as being more intuitive.

Alternatively consider something along the lines of:

/years which might expose a list of year objects

{
  "year": 2015,
  "entities": "https://api.myapp.com/years/2015/entities",
  "months": [
      {
        "month": 1,
        "name": "January",
        "entities": "https://api.myapp.com/years/2015/months/1/entities",
        "self": "https://api.myapp.com/years/2015/months/1"
      },
       ... array of month objects
  ],
  "self": "https://api.myapp.com/years/2015"
}

/years/2015/months/1 is one example of a month object

{
  "month": 1,
  "name": "January",
  "entities": "https://api.myapp.com/years/2015/months/1/entities",
  "self": "https://api.myapp.com/years/2015/months/1"
}

The entities property has a link to a collection of entities filtered by date.

But again it all depends on your specific problem. Just remember to make the interface intuitive, and not let your internal modelling bleed into your public api. But that isn't an easy task at all.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜