In a previous article, I was explaining how to extract HTTP headers. In this one, I will explain why the use of specific custom HTTP headers such as X-HTTP methods override can be very handy while developing and promoting a REST API.
When deploying REST API based web services, you may encounter access limitations on both the server and client sides.
1) X-HTTP methods override and server side
On the server side, the access to your REST based web application (I am using JBOSS) might be done via a proxy web server that does not support certain HTTP operations such as DELETE or PUT for security reasons.
For example if you are using Lotus Domino as redirector for your HTTP requests, be aware that by default Lotus Domino does not enable PUT and DELETE to go through.
Such requests will lead to HTTP 405 error:
Http Status Code: 405
Reason: Request method is not allowed by the server
Reason: Request method is not allowed by the server
By the way, if you really intend to allow PUT and DELETE on your Domino proxy web server, you need to add the following line to your notes.ini file:
HTTPEnableMethods=PUT,DELETE
However if you really need to have your proxy server filtering DELETE and PUT operations, then you will have to offer these operations via POST operations and ask your clients to add specific X-HTTP method override field in the header of their requests.
2) X-HTTP methods override and client side
The application consuming your web service might also have some constraints, for example restricting forms to only use GET or POST.
For these reasons, web infrastructure and solutions providers have proposed to use customized HTTP header fields:
- X-HTTP-Method (Microsoft)
- X-HTTP-Method-Override (Google/GData)
- X-METHOD-OVERRIDE (IBM)
I personally use JBoss RestEasy to develop a REST API for mobile health care applications, and it was quite straightforward to add the additional level of flexibility to my existing PUT and POST operations.
Note that if you want to use these methods to enforce either a PUT or a DELETE method, be aware that the RFC 2616 - HTTP 1.1 section 9.1.1 describes the GET operation as safe.
9.1.1 Safe Methods
Implementors should be aware that the software represents the user in
their interactions over the Internet, and should be careful to allow
the user to be aware of any actions they might take which may have an
unexpected significance to themselves or others.
In particular, the convention has been established that the GET and
HEAD methods SHOULD NOT have the significance of taking an action
other than retrieval. These methods ought to be considered "safe".
This allows user agents to represent other methods, such as POST, PUT
and DELETE, in a special way, so that the user is made aware of the
fact that a possibly unsafe action is being requested.
In other words, if you are tempted to use a GET to simulate a PUT or DELETE, don't do it.
Use a POST instead. Thank you to my colleague Ravi to point this to me!
X-HTTP methods override and PUT based operations
If your PUT operation does not have a corresponding DELETE counter-part,
you could just use the POST as a PUT and not even add a X-HHTP-Method override.
Both POST and PUT requests will end up being bound to the same method:
@PUT
@POST
@Path("/users/{userId}/order/{orderNum}")
@Produces("application/json")
@GZIP
public Response putPostUserOrder(@Context HttpServletRequest request,
@PathParam("userId") String userId,
@PathParam("orderNum") String orderNum)
If you still need to use a X-HTTP-Method override, what you need to do is to filter those specific POST requests.
boolean bProceed = true; if (request.getMethod().compareToIgnoreCase(POST) == 0) { String methodOverride = getHttpMethodOverride(request); if ((methodOverride == null) || (methodOverride.compareToIgnoreCase(PUT) != 0)) bProceed = false; }
private String getHttpMethodOverride(HttpServletRequest request){ String headerValue = request.getHeader("x-http-method-override"); if (headerValue != null) return headerValue; else return(request.getHeader("x-method-override")); }
In the example above, I have only implemented two customized X-HTTP headers, but you can add all of them if necessary.
X-HTTP methods override and DELETE based operations
For the DELETE operation, even if you don't have a PUT counter part, it is preferable to use a X-HTTP method override with DELETE to be semantically consistent (a PUT and POST are typically using to add or modify a resource, not removing it).
@POST
@Path("/users/{userId}/order/{orderNum}")
@Produces("application/json")
@GZIP
public Response postDeleteUserOrder(@Context HttpServletRequest request,
@PathParam("userId") String userId,
@PathParam("orderNum") String orderNum)
boolean bDelete = false; if (request.getMethod().compareToIgnoreCase(POST) == 0) { String methodOverride = getHttpMethodOverride(request); if ((methodOverride != null) && (methodOverride.compareToIgnoreCase(DELETE) == 0)) bDelete = true; }
Of course, if most likely want to still support the regular DELETE, so you also keep the original binding DELETE method:
@DELETE
@Path("/users/{userId}/order/{orderNum}")
@Produces("application/json")
@GZIP
public Response deleteUserOrder(@Context HttpServletRequest request,
@PathParam("userId") String userId,
@PathParam("orderNum") String orderNum)
Test harnessing X-HTTP Methods override operations
You can easily test your REST API with cURL as follow:
curl -H "X-HTTP-Method-Override: DELETE" -X POST http://restservice.acme.com/api/users/JJALGHPBIMA/orderNum/e7687673-479d-4d37-8bc0-a3e718aad33f
Should have the same effect as :
curl -X DELETE http://restservice.acme.com/api/users/JJALGHPBIMA/orderNum/e7687673-479d-4d37-8bc0-a3e718aad33f
No comments:
Post a Comment