Zach's Blog

Just another WordPress.com weblog

Override the HTTP Request Method in Jersey

with 2 comments

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!

About these ads

Written by Zach Cox

June 17, 2009 at 1:10 pm

Posted in Java

Tagged with , ,

2 Responses

Subscribe to comments with RSS.

  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.

    Dan

    March 18, 2010 at 3:29 pm

  2. Thanks for this, it was a big help!

    Mike C

    November 23, 2010 at 3:50 am


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

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: