Search code examples
resthateoas

Handling write only resources in a HATEOAS based REST api


Let's assume I have a REST resource for my users. If the client requests one specific user with GET, the api returns the following json.

GET https://localhost:8080/api/user/xy

{
  "name": "John Smith",
  ...
  "_links": [{
      "rel": "self",
      "href": "https://localhost:8080/api/user/xy"
  },
  {
      "rel": "changepassword",
      "href": "https://localhost:8080/api/user/xy/password"
  }]
}

As you can see the api provides a reference (in the _links section) to a resource where the client can change the password. I expect now the client to update the password when sending a PUT request to this reference.

Now my questions:

  1. Is this a good/correct approach to implement a use-case like "change password" in a HATEOAS based REST api? Or is there another/better approach?
  2. What should the server return after changing the password successfully? I would probably expect the status 204 and an empty body.
  3. For sure I don't want to show the user his current password. Therefor my server will return a code 405, if the client is trying to GET the password resource. Is it generally valid to have a "write only" resource in a REST api?

Solution

  • ... in a HATEOAS based REST api

    First things first, one of the few constraint REST implies is that HATEOAS is already in place and therefore HTTP clients use links to progress its current state. A client not utilizing HATEOAS is not a REST client as well as an API not including links offering a clinet new state-possibilities is not a RESTful API!

    Concerning your actual questions, it always depends on how you model certain things. You can use PUT to update the field and then return a 204 No Content response to indicate that this field has no readable content. According to the Spec

    If the target resource does have a current representation and that representation is successfully modified in accordance with the state of the enclosed representation, then the origin server MUST send either a 200 (OK) or a 204 (No Content) response to indicate successful completion of the request.

    returning a 204 No Content status code is eligible.

    An other approach could send the old password to the service in order for the service to first check the current password against the provided old one and only then update the password. This might prevent attacks which try to alter the passwords of other users in case you do not use an encrypted connection anyways. In order to achive this validation check however the client is not able to use a simple PUT operation anymore unless you make the old password part of the new state. Here POST is probably better suited as it leaves the semantics to the implementor of the API. This can go as far as to maintain a history of the last n passwords which the new password may not be any of the former ones.

    HTTP offers the OPTIONS method a client can use to determine which operations are suitable for certain endpoints. Zac Stewart explained the usefulness of the OPTIONS method in regards to RESTful APIs in a blog post, and also points out the current shortcommings plenty of HTTP server have in regards to the usage of OPTIONS.

    Most HTTP frameworks will return a 405 Method Not Allowed response code in cases an endpoint is invoked with an operation that has no implementation by default. At least in Java either in Spring MVC/Rest data or in JAX-RS methods offered at certain endpoints have to be annotated with interfaces that correspond to HTTP methods. Invoking an endpoint with an operation that has now equivalent annotated method will produce a 405 error response automatically, though this might be language and framework dependant.