0

I am designing a RESTful API which should return the validity of a username for registration. The invalid cases include:

  • duplicate username
  • too short or too long
  • invalid characters

My current design is:

GET /valid_username/{username}

  • returns 204 for valid username
  • returns 404 for invalid username with {err: 'DUPLICATE_USERNAME'}

Is this the preferred way in RESTful API?

lz96
  • 2,816
  • 2
  • 28
  • 46
  • 404 doesn't seem right, and why not just have invalidity of the username as an error when you POST to register? – jonrsharpe Jul 19 '17 at 06:47
  • @jonrsharpe Our registration includes 2 screens. User inputs username on the first one and phone number on the second one. We want to provide instant feedback for an invalid username even if phone number is unknown at that time. – lz96 Jul 19 '17 at 06:57
  • Then create the account with just a username; you're going to have to handle the error anyway, because otherwise people can create accounts with duplicate names if they check availability while the other user is entering their phone number. – jonrsharpe Jul 19 '17 at 07:00
  • 1
    here's a [guide](http://racksburg.com/choosing-an-http-status-code) for choosing the appropriate HTTP Status Code - I'd go with 409 Conflict and maybe 422 for different errors – Alexandru Marculescu Jul 19 '17 at 09:17

2 Answers2

0

Is this the preferred way in RESTful API?

I don't think so.

The guiding star for designing a REST API is a single question: How would you implement this as a web site?

As an integration protocol, when the client submits the username, you either want to advance them to the next form, or you send them back to the "previous" form with a bunch of error messages.

Technically, you could use 204 to do that in the happy path, with a Link in the meta data that the client could follow to go from the success page to the next. But it's a lot more likely that you would just send a representation of the next page at once; so 200 would be your most likely play.

For the unhappy path, instead of sending a representation of the next page, you'd probably send a representation of the current page with the data pre-filled in and the errors highlighted.

So key point: the human being is looking at the rendered representation, not at the meta-data in the headers. The browser is the audience for the metadata. The browser doesn't care anything about the semantics of the message, it just wants to know things like "can I cache this response?"

The most obvious choice of status codes for this case is: 200. Semantically, the representation of the integration resource change from one that would allow you to proceed (username Bob was available) to a representation that would force you to make another choice (username Bob is no longer available). The various headers in the meta data describe the appropriate caching policy to apply to this representation, and so on.

Technically, I think 404 "works", in so far that you can make it do what you want. The semantics are incorrect; from RFC 7231

The 404 (Not Found) status code indicates that the origin server did not find a current representation for the target resource or is not willing to disclose that one exists

My interpretation of that passage is that the server is claiming that the client submitted a bad request (all 4xx status codes share that meaning) , and more specifically that the spelling of the resource identifier is the root of the problem.

It's a bad fit because the server, in this case, isn't having any difficulty fulfilling the request -- it understands the request just fine; the "problem" is that the representation being returned isn't the one that the client is hoping for.

Community
  • 1
  • 1
VoiceOfUnreason
  • 52,766
  • 5
  • 49
  • 91
0

REST is about exposing, creating, and mutating resources. Each endpoint URI defines the location of that resource. In the case of a User resource, you would typically expose an endpoint to the collection of User resources with a URI like /users, and an endpoint for individual User resources of that collection with a URI like /users/{id}. Each endpoint is tied to a resource; not an operation. Endpoints that expose operations follow RPC architecture.

To do this RESTfully, your validations would be run when attempting to create a User resource using the user input. This could be done using an HTTP request line like POST /users. Upon invalid format of the username value, you would respond with a 400 status code, to indicate error on the user's part. Upon conflict with an existing username, you could return a 409 status to indicate a conflict between the request and internal API state. Your responses should also contain a body with further details of the issue. Upon a successful creation of a User resource, you should respond with a 201 status to indicate that the resource was created successfully.

Another way to go about this RESTfully, would be to key the individual User resource URI on the username, so that you would have something like /users/{username}. Then, to check if a username already exists, you would simply form a request like GET /users/{username}. If a User resource with that username does not exist, the API should respond with a 404 status, which would indicate to your client that the username is available. A response status of 200 would obviously indicate that the username is already in use.

Joshua Jones
  • 1,364
  • 1
  • 9
  • 15