9

Simple question I'm having trouble finding an answer to..

If I have a REST web service, and my design is not using url parameters, how can I specify two different keys to return the same resource by?

Example I want (and have already implemented)

/Person/{ID}

which returns a person as expected.

Now I also want

/Person/{Name}

which returns a person by name.

Is this the correct RESTful format? Or is it something like:

/Person/Name/{Name}
Erix
  • 7,059
  • 2
  • 35
  • 61

3 Answers3

7

You should only use one URI to refer to a single resource. Having multiple URIs will only cause confusion. In your example, confusion would arise due to two people having the same name. Which person resource are they referring to then?

That said, you can have multiple URIs refer to a single resource, but for anything other than the "true" URI you should simply redirect the client to the right place using a status code of 301 - Moved Permanently.

Personally, I would never implement a multi-ID scheme or redirection to support it. Pick a single identification scheme and stick with it. The users of your API will thank you.

What you really need to build is a query API, so focus on how you would implement something like a /personFinder resource which could take a name as a parameter and return potentially multiple matching /person/{ID} URIs in the response.

Brian Kelly
  • 19,067
  • 4
  • 53
  • 55
1

I guess technically you could have both URI's point to the same resource (perhaps with one of them as the canonical resource) but I think you wouldn't want to do this from an implementation perspective. What if there is an overlap between IDs and names?

It sure does seem like a good place to use query parameters, but if you insist on not doing so, perhaps you could do

person/{ID} 

and

personByName/{Name}
Boaz
  • 4,549
  • 2
  • 27
  • 40
pc1oad1etter
  • 8,549
  • 10
  • 49
  • 64
  • I figured there would be a standard way of doing this, seems like it would be common to me. Thanks for your input. – Erix Jun 19 '12 at 17:18
  • I think that the most standard way of doing it would be what you have ruled out - query parameters. As an aside, the content of your URL doesn't make it RESTful or not, but that doesn't seem to be the heart of the question. – pc1oad1etter Jun 19 '12 at 20:03
  • If you do just create a new URI pattern for searching by name (like /personByName/{Name} then you will end up creating a new pattern for each new parameter you think of (and each combination of those parameters!). If you're feel good about the odds that this is all that you will ever have, you can certainly do it this way. Again, though, a more standard approach would be having /person?name={Name} return a list of people matching by name. – pc1oad1etter Jun 19 '12 at 20:06
0

I generally agree with this answer that for clarity and consistency it'd be best to avoid multiple ids pointing to the same entity.

Sometimes however, such a situation arises naturally. An example I work with is Polish companies, which can be identified by their tax id ('NIP' number) or by their national business registry id ('KRS' number).

In such case, I think one should first add the secondary id as a criterion to the search endpoint. Thus users will be able to "translate" between secondary id and primary id.

However, if users still keep insisting on being able to retrieve an entity directly by the secondary id (as we experienced), one other possibility is to provide a "secret" URL, not described in the documentation, performing such an operation. This can be given to users who made the effort to ask for it, and the potential ambiguity and confusion is then on them, if they decide to use it, not on everyone reading the documentation.

In terms of ambiguity and confusion for the API maintainer, I think this can be kept reasonably minimal with a helper function to immediately detect and translate the secondary id to primary id at the beginning of each relevant API endpoint.

It obviously matters much less than normal what scheme is chosen for the secret URL.

Jan Żankowski
  • 8,690
  • 7
  • 38
  • 52