7

We have some entities that have both a unique business id (e.g. "my-unique-name") and also have an internal UUID (e.g. aa54-342-dffdf-55445-effab). Whats is a good way to provide a REST URI that can return the resource using either method.

Approach 1 - have two resource URLs (ugly!!!):

/foo-by-id/my-unique-name

/foo-by-uuid/aa54-342-dffdf-55445-effab

Approach 2 - always use a query parameter (even though it returns a single item...seems un-rest-lke)

/foo?id=my-unique-name

/foo?uuid=aa54-342-dffdf-55445-effab

Approach 3 - have the web service figure out whether the {id} is a UUID or not (this could get error prone, but in all likihood would work just fine...

Approach 4 - use the UUID, allow business id as a query parameter (don't know if this would work)

/foo?id=my-unique-name

/foo/aa54-342-dffdf-55445-effab

Any thoughts are appreciated.

Dave
  • 21,524
  • 28
  • 141
  • 221

6 Answers6

6

I would use something similar to option 4. Use the UUID in the path segment as the single resource URL. Use the alternate URL as a kind of search URL

e.g.

GET /foo?name=my-unique-name

303 See Other
Location: http://example.org/foo/aa54-342-dffdf-55445-effab

You don't want to have two URLs that both return a 200 with the same resource. That causes cache pollution.
And now you are free to use the GET "search style" URL for other types of searches.

GET /foo?account=other-unique-value

303 See Other
Location: http://example.org/foo/aa54-342-dffdf-55445-effab

or you could even search on non-unique stuff.

GET /foo?country=a-non-unique-value

200 OK
Content-Type: application/vnd.hal+xml

<resource href="http://example.org/foo?country=a-non-unique-value">
   <resource rel="urn:acme:foo" href="http://example.org/foo/aa54-342-dffdf-55445-effab"/>
   <resource rel="urn:acme:foo" href="http://example.org/foo/ba54-299-weras-55445-effab"/>
   <resource rel="urn:acme:foo" href="http://example.org/foo/ca54-743-werre-23434-effab"/>
<resource>
Darrel Miller
  • 139,164
  • 32
  • 194
  • 243
  • I like this. It has good looking URLs, is easy to remember and also solves the cache problem that greyfairer brought up. I will however, have to figure out how to implement it. It seems like you guys are saying that it is a rule that the result set of a REST query should return only the URI location of the real resource. I was hoping to do it all in one round-trip to minimize chatter. Maybe I should open another question! – Dave Jan 07 '12 at 19:16
  • Read my comment at http://stackoverflow.com/a/4411929/23692 instead of opening another question :) – fumanchu Jan 07 '12 at 20:01
  • OK, I get it. My main problem is I am still thinking RPC/SOAP. REST is truly a very different beast from other web services! BTW -- I meant to say fumanchu in my first comment. – Dave Jan 08 '12 at 02:08
5

Pick one as canonical, and 307 redirect the other to it. If you don't, then you run the risk of the two URI's returning different data because they have been cached at different times or lifetimes. By redirecting from one to the other, you allow a PUT, POST, or DELETE request to invalidate the cache of a single, canonical URI. Use 307 instead of 302 so that "historic" clients don't change POST to GET. I'd recommend Approach 1, having the UUID redirect to the business ID just because it's prettier.

fumanchu
  • 14,419
  • 6
  • 31
  • 36
3

REST is not all about nice URL's. However the first approach is, in my own opinion, not really REST because of the two "resources" as you pointed out.

The second approach is REST, but if you don't want to have a QS style URL, you can do something like this:

/foo/id-my-unique-name
/foo/uuid-aa54-342-dffdf-55445-effab

Then you can split it by using a regex.

As far as I'm concerned, I like the last one because of the nice URL.

basgys
  • 4,320
  • 28
  • 39
1

I would go with the second approach. Moslty because semantically speaking, you want to GET entity named foo by "filtering" through something. This something is obviously reflected by defining constraints on its attributes, namely id or uuid.

That said, REST is not about URLs. The approach you are talking about is commonly known as "nice urls". REST is about semantically driven operations on representation of resources carried out by common actions (HTTP methods) and names (URLs).

You may read something more on Fielding dissertation about REST.

Moreover, if you want to be RESTful, you should have unique URLs for each entity. But as Fielding himself points out, nobody is RESTful.

1

I'm currently developing android app with rest calls and i used second approach, the reason is rest unique path id is more comfortable with human readable format such as http://example.com/rest/news/2007/6 is obviously represents news in year 2007 and month 6.

GiantRobot
  • 432
  • 3
  • 6
0

According to REST principles, each representation should have a unique URI.

The one with the business key probably refer to related entities by business key as well, so that representation is different from the one with the UUID, which will use probably UUID's for its related entities.

/foo/my-unique-name -> link: /foo/parent-uniquename
/internal/foo/aa54-342-dffdf-55445-effab -> link: /internal/foo/parent-xxxyyyy
GeertPt
  • 16,398
  • 2
  • 37
  • 61
  • I think in all 4 approaches each representation has a unique URI that only returns that entity. However, in all the approaches there are multiple URI's that can return the same entity. Sounds like you are advocating approach 1 though. – Dave Jan 07 '12 at 02:27
  • Every **Resource** should have a single URL, using server driven content negotiation, you can have multiple **representations** with the same URL. – Darrel Miller Jan 07 '12 at 14:32