Reputation: 63
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
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:
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
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
Reputation: 40980
For these two models ie. countries
and states
, I think following Uri patterns will be most appropriate.
api/country
api/country/{England}
api/country/{England}/State
api/country/{England}/State/{Berkshire}
in above example value inside {}
represents the variables.
Upvotes: 1
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