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:

  1. Extend the org.restlet.resource.Resource class
  2. 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));
        
  3. Override the org.restlet.resource.Resource.represent(Variant variant) method to handle all GET HTTP requests and org.restlet.resource.Resource.acceptRepresentation(Representation entity) to handle all POST HTTP requests
  4. Optionally if you wish to handle PUT and DELETE HTTP requests, you can override the org.restlet.resource.Resource.storeRepresentation(Representation entity) and org.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:

  1. Extend the org.restlet.Filter class
  2. Override the beforeHandle(Request request, Response response) and/or afterHandle(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.