RESTful way to check availability of usernames, emails, etc - rest

I've recently gotten very into trying to think as RESTfully as possible, and I'm finding myself stymied by the non-obvious routes.
In this particular case, I'm curious about the RESTful way to check for username and email availability for a user, or anything else that has uniqueness.
My gut tells me that I would want to perform a GET on /users/email or /users/username/ each with a required param, or something along the lines of GET /users/search/ with optional params of email and username. If you get a 200, then the username or email is unavailable; if you get a 404, then it's available.
I prefer the first option since it's more explicit, but it's not like I've pored over Roy Fielding's thesis to know well enough what to do.
What's the most sound approach here?

The first approach does seem to be more "RESTful". You try to GET a specific resource (by username or email) and get it if it exists or get a status message "unavailable resource". This would be:
GET /users/username/johnwayne (to "get" johnwayne resource/username availability...)
This should generate:
200: if resource exists
404: if the resource does not exist
The second one seems more like "SOAP"-like web service, where you define a "function" (/users/search/) with some "parameters" (username, email)...

For unique fields, first option is a good fit (/users/email or /users/username/), for non-unique fields search would be more appropriate.

i would recommend, you use HEAD request instead of GET.
Using a GET may pose a security problem. A hacker can use a combination to identify valid username as GET would either result in 200 or 404.

You should try to get a list of users with your mail by
GET /users?query=asd#gmail.com
And here you can find 1 item or 0 items. In first case the address isn't unique. In another - it's unique

Related

How to design api to retrieve one resource by non-primary key in RESTful style?

Original, we have a api GET /users/:id to retrieve a user by its primary key.
Now we need a new api to retrieve a user by its email.
GET /users?email=xx#xx.com seems like to get a collection.
GET /users/byEmail/:email includes a non-noun word byEmail.
Is there any other choice?
Both approaches you have suggested are valid on their own, but I probably wouldn't do both as it's best to stick with one URI per resource. Another common way to do this is:
/users/id/:id
or
/users/email/:email
I should point out that the choice of query params vs url params or /name/:value vs /:value is not what make a service "RESTful". Put another way, having "pretty" or "readable" URLs does not automatically mean your service is RESTful.
One of the key points of REST is resource identification through a URI i.e. a particular URI will always point to a particular resource. In the case of email, this could probably change (user may want to change their email address) so this url no longer identifies this user at all times.
A more RESTful approach would be to make explicit that this is really a search and not an identifier, and have a URI like this:
/search/users/email/:email
This is more RESTful because this URI always identifies the same resource, namely the search results for this email address. Note that the resource in this case is the search results, not the user resource itself.
I like the convention that URIs with / at the end of the path are the collections. So GET /users?email=xx#xx.com returns an item and GET /users/?email=xx#xx.com returns a collection with a single item. But ofc. you don't have to use this convention.
Another options are using /users/:email if you can solve the routing on the server, or /users-by-email/:email or /users/email-:email, etc... It is not important which URI structure you choose as long as your REST API meets with the HATEOAS constraint.

Is it still REST if we identify resources with URLs which contain query string components?

1) I assume query string component of an URL is also considered as being a part of identity of a resource?
2) If it indeed is considered as being a part of identity, are there any reasons why in REST we can't/shouldn't identify resources with URLs which contain query string components?
Thank you
If the resource you are addressing with a URL represents a collection of resources like http://yourdomain.com/customers it's a valid restful way to filter the result with query-parameters:
http://yourdomain.com/customers?minSalary=2000&maxAge=50
So yes, query-parameters are meaningful for identifying resources.
I think you root question is about using a query that would return a unique item.
/orders?ID=8
which would be the same resource as
/order/8
So there we have two URIs for the same resource. You might be asking is that ok, and it is perfectly fine to have multiple URIs to get the same resource. Generally you should link to a more 'canonical' URI, the shortest 'path' (hierarchally speaking) for a resource.
You shouldn't rely on query parameters generally, as it tends to lead towards awkward API designs. For example, if you want to know all the orders made by bob, you might be tempted to think "well, I'm filtering the orders" and so do
/orders?users=bob
Where as better way of thinking is "I want all users, just bob, just his orders", so you would instead do
/users/bob/orders
This is a simple URI that you would be able to link to from the 'user resource' for bob. Sadly though, this second approach can get a bit awkward when you want to say, look at orders from multiple users
/users/jack,jill,alice,bob/orders
It's workable, but very odd looking.

What is the best way to design REST URI for nested resources

Say there are users having multiple authorizations having multiple permissions.
Retrieving all authorizations for the specified user (without permissions) could be:
GET users/{id}/authorizations
The "normal" case is to not embed permissions with authorizations for performance reason.
There are cases when authorizations must be returned with their respective permissions for that user.
Suggested solutions are:
GET users/{id}/authorizations/permissions // does not seem clear
GET users/{id}/authorizations?permissions=true // with query string
GET users/{id}/authorizationswithpermissions // new resource
Now what is the best way to design the REST URI in that case?
Your ideas
There are cases when authorizations must be returned with their respective permissions for that user.
GET users/{id}/authorizations/permissions
It is not a good idea to nest collection resource like this. Does it mean "give me all permissions of all authorizations of user id"? This is unclear. Don't do this.
GET users/{id}/authorizations?permissions=true
A query is normally used to query, search, or filter on a collection resource. This URL woud return all authorizations for user id for which permissions is true. But what does that man? This is unclear. Don't do this.
GET users/{id}/authorizationswithpermissions
Authorizations are authorizations. Their representation should not depend on the URI. Don't do this.
Content Negotiation
The solution to your problem is to use content negotiation. You only use one URL:
GET users/{id}/authorizations
This means: Give me a list of all authorizations of user id.
Now if you want to get this list without permissions, you could use the HTTP header
Accepts: application/vnd.mycompany.authorizations+xml
Let's digest this.
application: the first part of the normal MIME type application/xml
vnd: a prefix to define your own type
mycompany.authorizations: your type
xml: the second part of application/xml
Now if you want to get this list with permissions, you could use the HTTP header
Accepts: application/vnd.mycompany.authorizations.permissions+xml
Note that me now use vnd.mycompany.authorizations.permissions. The server should return the authorizatons including the permissions. Only the representations are different, not the resources.
Personnally I can't find any problem with both two last suggestions:
GET users/{id}/authorizations?permissions=true // with query string
GET users/{id}/authorizationswithpermissions // new resource
Except I would change them as follow to be more relevant:
GET users/{id}/authorizations?withPermissions=true // with query string
GET users/{id}/authorizationsANDpermissions // new resource
The first one seems to be quite confusing but your RESTful entities should be documented whatever notation you will opt for.

RESTful url to GET resource by different fields

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}
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.
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}
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.

What's the best to do when you need a verb using REST api?

I'm exposing a REST API, and It's amazingly easy and smooth to work with as long as you do CRUD (Create, Update, Delete). But I have this Tickets which return a list of tickets (get), a Ticket/{id} which get a particular item (get) and an activate method (put) that change the ticket status from not activated to activated.
Now I'm in need to give the REST 'consumer' the ability to do something like (in ws will be called: GetAndActivateRandomTicket() and it keeps me wondering, what that should be described as on REST ? Is it a post? A put? A get? The Goal is to get a random amount of tickets and set their status to active. Something like a get & put at the same time but without knowing before hand the {id} for the put.
Should it be /Tickets?activate=true&amount=5 ? What verb? Should I expose a verb instead of a noun? What is the 'best practices' on this issue?
If repeating the operation does something different (e.g., activates a different ticket) then it is not idempotent. Non-idempotent operations always map to POST (or a custom verb) in a RESTful architecture.
Some resources are easily identifiable and exist in the domain. Some however are a bit tricky as you pointed out. But ROA (resource oriented architecture) takes some getting used to. Anything can be made a resource including transactions, sessions and other such non-domain entities :)
In your case you seem to have an 'algorithmic' resource - selecting a random amount of tickets and activating them. I'm sure this 'randomness' has some way of selecting tickets which is not purely random else there'll be wasted computation with getting already activated set of tickets.
So I'm not sure how your activation is happening - does someone select activate against a bunch of tickets (checkboxes) or just part of 'data packet' without human intervention?
You description seems to hint the latter - so a good practice is to do what you just said:
Multiple options on the URL:
/Tickets?amountToActivate=5;activate (Note the semicolon and just the 'word' activate)
/Tickets?amountToActivate=5&activate=true (Note: I personally feel the above is better since =true is actually redundant, it's an artifact of non-restful URIs where most folks would explicitly state = true - it's as good as just writing 'activate' in the URL (implies true) absence would imply false :)
Your resource IS algorithmic and the human 'consumer of the URL' when reading it would instantly understand the former URL, =true may not be well understood, but that's just me perhaps. There is a tendency to also use the latter since most frameworks are able to parse query parameters and split by '&' and semicolons may just require some work
In case if there is manual intervention you can break it into two parts:
GET: /Tickets?fetchRandomAmountOfTickets=100 (since it's algorithmic)
PUT: /Tickets (the activation 'update' part of PUT for list of tickets that you 'GOT' above)
Hope this helps :)
First of all GET should be idempotent and never make any changes to the resource. Activating a resource should be done using a PUT.
What I would do is create a resource URL like /Tickets/Random that as a result to a GET returns an HTTP 303 to redirect the user to a randomly determined actual resource URL like /Tickets/12345. The user can then activate this ticket using a PUT. All the user app needs to know is the /Tickets/Random URL and he can keep on activating tickets as long as there are any there.
I extracted this :
Anything can be made a resource including transactions, sessions and other such non-domain entities :)
and went with :
TicketActivation resource.
[POST] with a query parameter of amount will return a set of random tickets activated.
and return the resource url as such that you can get like /ticket/id=1,2,3,4,5
[GET] will return tickets as normaly with an optional filter of id to return multiple tickets
[PUT] will use the filter of id also and set activation true or false depending on parameter.
so I can do :
[post]
/ticket/activation/?amount=5
resource returned will be something like /ticket?id=1,2,3,4,5
so I can issue a get on it.
[get]
/ticket?id=1,2,3,4,5
[put]
/ticket/activation?id=1,2,3,4,5&deActivate [OR]
/ticket/activation?id=1,2,3,4,5&activate
I guess this is the most elegant and also RESTfull and clear solution to this problem, I wanted to share for future reference. Also if you think there is a problem with this approach feel free to comment on it.