user2007820
user2007820

Reputation: 63

RESTful URI design

I'm looking for a right way to represent searches as a RESTful uri.

I have two models: countries and states, where countries have a collection the states.

What's the right way to represent a search for countries with id or name attributes?

api/countries/1/id

api/countries/Italy/name

or

api/countries?id=1

api/countries?name=Italy

Also, if I want view the list of states?

api/countries/1/id/states

api/countries/Italy/name/states

Thanks

Upvotes: 1

Views: 641

Answers (4)

Philzen
Philzen

Reputation: 4667

What's the right way to represent a search for countries with id or name attributes?

tl;dr: Variant one is a recipe for confusion. If having to choose, use the query string to search.


As far as the REST manifesto is concerned the URI logic is merely an implementation detail - the only concern is that the access mechanism at that location mustn't break over time. Content may be emptied or move - but URI must at all times end up at a service endpoint that gives clients a pre-response they understand and can act on (i.e. 3** redirect or hypermedia re-discovery by the client).

However, many successful and well-designed APIs try to expose an inherently consistent logic, aiming to become intuitively explorable. Therefore your first example api/countries/1/id is actually BAD regarding developer's experience and market success, as it be confusing to use:

  1. From looking at the URI, you don't have any clue that you're running a (potentially CPU/Memory-expensive) search and NOT retrieving a single ressource
  2. Many public APIs follow a logical mapping between resource hierarchy and the exposed URIs - so a common expectation would be that api/countries/1/id retrieves {1} (being a pointless query) or that api/countries/1/name gives {Italy}.

Therefore, Query string is an excellent option - especially to offer a Search functionality. One can see the implication from the words ;)

api/countries?name=Italy 
api/countries?q=name(Ital*)              // same result
api/countries?q=isoCode=(IT)             // same result

--> api/countries/1/states               // list all states of Italy
    api/states?q=country/name(Italy)     // - same -
    api/states?q=country/id(1)           // - same -

The response body of a request can be anticipated from looking at the URI only, which is nice. Better yet: it helps to tell apart resource and view. The "view" is defined in the query string, think of as lens, or filter, through which you look at extracts of what otherwise is one and the same resource (your countries collection).

This pattern is just as good in those regards and also commonly found:

api/countries/search/Italy
api/countries/search/name=Italy
api/countries/search/isoCode=IT,name=*aly

The reason to pick this may revolve around actual implementation details when building your API - as it seperates the direct access to a resource from a search operation - both the required CPU/Memory to fulfill the request, and the response count and format may be fundamentally different.

Upvotes: 0

arpadf
arpadf

Reputation: 443

Your approach, using name in the REST URL is wrong. The name is simply an attribute of the country not a sub-resource, meaning you should not see it in the URL. An option would be though, to use it as key and in this case, the name's value could be used in place of the ID.

api/countries/Italy

I think what you are trying to achieve though, is to filter fields, i.e. get only the names:

api/countries/Italy/states?fields=name

or, if you predefine some formats

api/countries/Italy/states?format=onlyName

Upvotes: 0

Sachin
Sachin

Reputation: 40980

For these two models ie. countries and states, I think following Uri patterns will be most appropriate.

  1. All Countries : api/country
  2. Specific Country : api/country/{England}
  3. All States : api/country/{England}/State
  4. Specific State : api/country/{England}/State/{Berkshire}

in above example value inside {} represents the variables.

Upvotes: 1

Valery Viktorovsky
Valery Viktorovsky

Reputation: 6736

It depends on your tastes. Both variant are ok.

For states it's possible to create new endpoint

api/states/name/Italy

Upvotes: 0

Related Questions