Restlet – Handling the X-HTTP-Method-Override request header
I have been using the Restlet framework for developing RESTful web applications in Java. I like how it makes designing Restful resources extremely simple. All you got to do is have your Resource class:
-
Extend the
org.restlet.resource.Resourceclass -
Override the 3 arg constructor –
org.restlet.resource.Resource.Resource(Context context, Request request, Response response)and declare which representation variants you want to expose. For example, if you plan on returning a JSON response, you would add something like this:getVariants().add(new Variant(MediaType.APPLICATION_JSON)); -
Override the
org.restlet.resource.Resource.represent(Variant variant)method to handle all GET HTTP requests andorg.restlet.resource.Resource.acceptRepresentation(Representation entity)to handle all POST HTTP requests -
Optionally if you wish to handle PUT and DELETE HTTP requests, you can override the
org.restlet.resource.Resource.storeRepresentation(Representation entity)andorg.restlet.resource.Resource.removeRepresentations()respectively
For clients (example, browser-based application) that cannot send PUT and DELETE HTTP methods, the Restlet framework supports HTTP method tunneling where you could specify the actual method PUT or DELETE as a query parameter. For example,
Using POST to PUT a resource:
curl -i -H "Accept: application/json" -X POST -d "phone=1-800-999-9999" http://192.168.0.165/persons/person/1?method=PUT
This works great!
But what about client applications that can fully control the HTTP requests? Google has taken a cleaner approach and proposed that these clients send in an extra request header with the actual method in a POST request.
For example:
Using POST to PUT a resource:
curl -i -H "Accept: application/json" -H "X-HTTP-Method-Override: PUT" -X POST -d "phone=1-800-999-9999" http://192.168.0.165/persons/person/1
As you can see, the second approach is much cleaner and more REST-like. Unfortunately you cannot get the Resource class to handle the above POST (to PUT) request.
Filters to the rescue
Fortunately, the Restlet framework comes with an abstract org.restlet.Filter class that you can extend. The Filter class according to the java docs is
Restlet filtering calls before passing them to an attached Restlet. The purpose is to do some pre-processing or post-processing on the calls going through it before or after they are actually handled by an attached Restlet.
Restlet Filters are similar to Servlet Filters conceptually. To develop a Restlet Filter all you got to do is:
-
Extend the
org.restlet.Filterclass -
Override the
beforeHandle(Request request, Response response)and/orafterHandle(Request request, Response response)methods
In our case we want to see if the client passed the X-HTTP-Method-Override request header in a POST request. Therefore all we need is to override the beforeHandle(Request, Response) method.
Our Filter will intercept the request and if it is a POST request with a X-HTTP-Method-Override request header with a value of PUT or DELETE, it will change the request method from POST to PUT or DELETE.
import org.restlet.Filter;
import org.restlet.data.Method;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.util.Series;
import com.noelios.restlet.http.HttpConstants;
public class ExtraHttpMethodOverrideFilter extends Filter {
protected int beforeHandle(Request request, Response response) {
System.out
.println("Intercepting filter ExtraHttpMethodOverrideFilter.beforeHandle");
handleHttpMethodOverride(request);
return CONTINUE;
}
@SuppressWarnings("unchecked")
private final void handleHttpMethodOverride(Request request) {
final Series extraHeaders = (Series) request.getAttributes().get(
HttpConstants.ATTRIBUTE_HEADERS);
final String overrideValue = extraHeaders.getFirstValue(
HttpConstants.HEADER_X_HTTP_METHOD_OVERRIDE, true);
if (overrideValue != null && overrideValue.trim().length() > 0) {
if (request.getMethod().equals(Method.POST)
&& overrideValue.trim().equalsIgnoreCase(
Method.PUT.getName())) {
request.setMethod(Method.PUT);
System.out
.println("ExtraHttpMethodOverrideFilter.handleHttpMethodOverride: Setting the HTTP method to PUT from POST");
} else if (request.getMethod().equals(Method.POST)
&& overrideValue.trim().equalsIgnoreCase(
Method.DELETE.getName())) {
request.setMethod(Method.DELETE);
System.out
.println("ExtraHttpMethodOverrideFilter.handleHttpMethodOverride: Setting the HTTP method to DELETE from POST");
}
}
}
}
The org.restlet.Filter.CONTINUE indicates that the request processing should continue normally.
And that’s how easy it is to support X-HTTP-Method-Override request header and hence the PUT and DELETE HTTP requests using the Restlet framework.

Leave a comment