Override the HTTP Request Method in Jersey

RESTful web services take advantage of all of the HTTP methods including GET, POST, PUT, DELETE, HEAD and OPTIONS.  However, a lot of HTTP libraries (BlackBerry JDE, iPhone SDK, etc) and all browsers only support GET and POST.  There are several ways to get around these deficiencies – in this post I’ll describe two of them and show a Jersey filter for implementing them.

Jersey provides a PostReplaceFilter that looks for the X-HTTP-Method-Override header and changes the request’s method to that header’s value. To use this approach to perform a PUT from your client, just do a POST request and include a “X-HTTP-Method-Override: PUT” header.  The filter will then translate it into a PUT request before handling it.

Ruby on Rails looks for a _method form parameter and changes the request’s method to that parameter’s value.  To use this approach to perform a PUT from your client, just do a POST request and include a “_method=PUT” form parameter.  The Rails version is particularly useful if you’re making the request from an HTML form (updating or deleting a resource, for example).

I combined the two HTTP method overwriting approaches into a new Jersey filter:

import com.sun.jersey.spi.container.*;

/** Clients may override the HTTP method by setting either the X-HTTP-Method-Override header or
 * the _method form or query parameter in a POST request.  If both the X-HTTP-Method-Override
 * header and _method parameter are present in the request then the X-HTTP-Method-Override header
 * will be used.
 *
 * Inspired by https://jersey.dev.java.net/nonav/apidocs/1.1.0-ea/jersey/com/sun/jersey/api/container/filter/PostReplaceFilter.html
 */
public class OverrideHttpMethodFilter implements ContainerRequestFilter
{
    private static final String HEADER = "X-HTTP-Method-Override";
    /** The name of the form or query parameter that overrides the HTTP method. */
    public static final String METHOD = "_method";

    @Override
    public ContainerRequest filter(ContainerRequest request)
    {
        if (request.getMethod().equalsIgnoreCase("POST"))
            if (!override(request.getRequestHeaders().getFirst(HEADER), request))
                if (!override(request.getFormParameters().getFirst(METHOD), request))
                    override(request.getQueryParameters().getFirst(METHOD), request);

        return request;
    }

    private boolean override(String method, ContainerRequest request)
    {
        if (!Strings.isEmpty(method))
        {
            request.setMethod(method);
            return true;
        }

        return false;
    }
}

If you’re creating a web service that uses more than just GET and POST, combining these two approaches will make the unfortunate developers who have to use these flawed HTTP libraries very happy!

3 thoughts on “Override the HTTP Request Method in Jersey

  1. Hi,
    I found this really useful, but I had to put in a couple of alterations to get it working…

    line 29 I changed to if(null!=method && !method.isEmpty())

    and line 31 had to be changed to request.setMethod(method.toUppercase());

    without those changes, I was getting apparently random failures, but with them it appears to be working well.

    Thanks for sharing the original.

  2. Pingback: PATCH request using Jersey Client | Ngoding

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s