How to expose a validation API in a RESTful way?

HttpRest

Http Problem Overview


I'm generally a fan of RESTful API design, but I'm unsure of how to apply REST principles for a validation API.

Suppose we have an API for querying and updating a user's profile info (name, email, username, password). We've deemed that a useful piece of functionality to expose would be validation, e.g. query whether a given username is valid and available.

What are the resource(s) in this case? What HTTP status codes and/or headers should be used?

As a start, I have GET /profile/validate which takes query string params and returns 204 or 400 if valid or invalid. But validate is clearly a verb and not a noun.

Http Solutions


Solution 1 - Http

The type of thing you've described is certainly more RPC-style in its' semantics, but that doesn't mean you can't reach your goals in a RESTful manner.

There's no VALIDATE HTTP verb, so how much value can you get from structuring an entire API around that? Your story centers around providing users with the ability to determine whether a given user name is available - that sounds to me like a simple resource retrieval check - GET: /profile/username/... - if the result is a 404, the name is available.

What this highlights is that that client-side validation is just that - client side. It's a UI concern to ensure that data is validated on the client before being sent to the server. A RESTful service doesn't give a whit whether or not a client has performed validation; it will simply accept or reject a request based on its' own validation logic.

REST isn't an all-encompassing paradigm, it only describes a way of structuring client-server communications.

Solution 2 - Http

We have also encountered the same problem. Our reasoning for having the client defer to the server for validation was to prevent having mismatched rules. The server is required to validate everything prior to acting on the resources. It didn't make sense to code these rules twice and have this potential for them to get out of sync. Therefore, we have come up with a strategy that seems to keep with the idea of REST and at the same time allows us to ask the server to perform the validation.

Our first step was to implement a metadata object that can be requested from a metadata service (GET /metadata/user). This metadata object is then used to tell the client how to do basic client side validations (requiredness, type, length, etc). We generate most of these from our database.

The second part consist of adding a new resource called an analysis. So for instance, if we have a service:

GET /users/100

We will create a new resource called:

POST /users/100/analysis

The analysis resource contains not only any validation errors that occurred, but also statistical information that might be relevant if needed. One of the issues we have debated was which verb to use for the analysis resource. We have concluded that it should be a POST as the analysis is being created at the time of the request. However, there have been strong arguments for GET as well.

I hope this is helpful to others trying to solve this same issue. Any feedback on this design is appreciated.

Solution 3 - Http

You are confusing REST with resource orientation, there's nothing in REST that says you cannot use verbs in URLs. When it comes to URL design I usually choose whatever is most self-descriptive, wheather is noun or verb.

About your service, what I would do is use the same resource you use to update, but with a test querystring parameter, so when test=1 the operation is not done, but you can use it to return validation errors.

PATCH /profile?test=1
Content-Type: application/x-www-form-urlencoded

dob=foo

... and the response:

HTTP/1.1 400 Bad Request
Content-Type: text/html

<ul class="errors">
  <li data-name="dob">foo is not a valid date.</li>
</ul>

Solution 4 - Http

A very common scenario is having a user or profile signup form with a username and email that should be unique. An error message would be displayed usually on blur of the textbox to let the user know that the username already exists or the email they entered is already associated with another account. There's a lot of options mentioned in other answers, but I don't like the idea of needing to look for 404s meaning the username doesn't exist, therefore it's valid, waiting for submit to validate the entire object, and returning metadata for validation doesn't help with checking for uniqueness.

Imo, there should be a GET route that returns true or false per field that needs validated.

/users/validation/username/{username}

and

/users/validation/email/{email}

You can add any other routes with this pattern for any other fields that need server side validation. Of course, you would still want to validate the whole object in your POST.

This pattern also allows for validation when updating a user. If the user focused on the email textbox, then clicked out for the blur validation to fire, slightly different validation would be necessary as it's ok if the email already exists as long as it's associated with the current user. You can utilize these GET routes that also return true or false.

/users/{userId:guid}/validation/username/{username}

and

/users/{userId:guid}/validation/email/{email}

Again, the entire object would need validated in your PUT.

Solution 5 - Http

It is great to have the validation in the REST API. You need a validation anyway and wy not to use it on the client side. In my case I just have a convention in the API that a special error_id is representing validation errors and in error_details there is an array of error messages for each field that has errors in this PUT or POST call. For example:

{
  "error": true,
  "error_id": 20301,
  "error_message": "Validation failed!",
  "error_details": {
    "number": [
      "Number must not be empty"
    ],
    "ean": [
      "Ean must not be empty",
      "Ean is not a valid EAN"
    ]
  }
}

If you use the same REST API for web and mobile application you will like the ability to change validation in both only by updating the API. Especialy mobile updates would take more than 24h to get published on the stores.

And this is how it looks like in the Mobile application: enter image description here

The response of the PUT or POST is used to display the error messages for each field. This is the same call from a web application using React: enter image description here

This way all REST API response codes like 200 , 404 have their meaning like they should. A PUT call responses with 200 even if the validation fails. If the call passes validation the response would look like this:

{

"error": false, "item": { "id": 1, "created_at": "2016-08-03 13:58:11", "updated_at": "2016-11-30 08:55:58", "deleted_at": null, "name": "Artikel 1", "number": "1273673813", "ean": "12345678912222" } }

There are possible modifications you could make. Maby use it without an error_id. If there are error_details just loop them and if you find a key that has the same name as a field put his value as error text to the same field.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAseem KishoreView Question on Stackoverflow
Solution 1 - HttpJosh EView Answer on Stackoverflow
Solution 2 - HttpLeslie HanksView Answer on Stackoverflow
Solution 3 - HttpMax ToroView Answer on Stackoverflow
Solution 4 - HttpScubaSteveView Answer on Stackoverflow
Solution 5 - HttpTarik HuberView Answer on Stackoverflow