Shubham Kumar
Shubham Kumar

Reputation: 177

Accessing Request Headers

How to access request headers in implementation of WriterInterceptor interface in JAX-RS?

context.getHeaders(); //This line gives a set of response headers(not request headers) in the WriterInterceptor implementation.

Complete code below:

public class GzipFilterWriterInterceptor implements WriterInterceptor {

private static final Logger LOG = LoggerFactory.getLogger(GzipFilterWriterInterceptor.class);

@Override
public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
    MultivaluedMap<String,Object> headers = context.getHeaders();
    headers.add("Content-Encoding", "gzip");


    final OutputStream outputStream = context.getOutputStream();
    context.setOutputStream(new GZIPOutputStream(outputStream));
    context.proceed();
}

}

Upvotes: 11

Views: 14109

Answers (4)

gladiator
gladiator

Reputation: 1363

You can implement below code to ,see working example at http://jerseyexample-ravikant.rhcloud.com/rest/jws/say/Hello

import java.io.IOException;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.ext.Provider;

@Provider
public class SecurityInterceptor implements ContainerRequestFilter, ContainerResponseFilter {

    @Override
    public void filter(ContainerRequestContext reqCtx, ContainerResponseContext respCtx) throws IOException {

        long startTime=0;
        System.out.println("Adding ProcessingTime in response headers"); 
        if(reqCtx.getHeaderString("startTime")!=null)
        startTime = Long.parseLong(reqCtx.getHeaderString("startTime")); 
        respCtx.getHeaders().add("ProcessingTime",
                String.valueOf(System.currentTimeMillis() - startTime) + " millisecs"); 
    }

    @Override
    public void filter(ContainerRequestContext reqCtx) throws IOException {
        System.out.println("Adding start time in request headers");

        reqCtx.getHeaders().add("startTime", String.valueOf(System.currentTimeMillis()));

    }

}

Upvotes: 3

Jason Pyeron
Jason Pyeron

Reputation: 2528

@Provider
public class GzipFilterWriterInterceptor implements WriterInterceptor
{

    private static final Logger LOG = LoggerFactory.getLogger(GzipFilterWriterInterceptor.class);

    // use a context injection
    @Context 
    private HttpHeaders httpHeaders;

    @Override
    public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException
    {
        MultivaluedMap<String,Object> headers = context.getHeaders();
        headers.add("Content-Encoding", "gzip");

        // do stuff with headers
        if ("Basic Ym9iOnBhc3N3b3Jk".equals(httpHeaders.getRequestHeader("Authorization").get(0)))
        {
            //do stuff here, but be careful about the indexoutofbounds...
        }


        final OutputStream outputStream = context.getOutputStream();
        context.setOutputStream(new GZIPOutputStream(outputStream));
        context.proceed();
    }

}

The context injection will be injected per request, see the javadocs.

Upvotes: 3

Paul Samsotha
Paul Samsotha

Reputation: 208994

You can just inject HttpHeaders. It will be a thread-local proxy when it's injected, so it's thread safe.

@Context
private HttpHeaders headers;

It has methods


UPDATE (test)

import org.glassfish.jersey.filter.LoggingFilter;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.WriterInterceptor;
import javax.ws.rs.ext.WriterInterceptorContext;
import java.io.IOException;
import java.util.logging.Logger;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

/**
 * Run like any other JUnit test. Only one required dependency:
 * 
 *  <dependency>
 *    <groupId>org.glassfish.jersey.test-framework.providers</groupId>
 *    <artifactId>jersey-test-framework-provider-inmemory</artifactId>
 *    <scope>test</scope>
 *    <version>${jersey.version}</version>
 *  </dependency>
 */
public class HeadersTest extends JerseyTest {

    @Path("hello")
    public static class HelloResource {
        @GET
        public String get() {
            return "Hello";
        }
    }

    @Override
    public ResourceConfig configure() {
        return new ResourceConfig(HelloResource.class)
                .register(HeaderWriter.class)
                .register(new LoggingFilter(Logger.getAnonymousLogger(), true));
    }

    @Provider
    public static class HeaderWriter implements WriterInterceptor {
        @Context
        private HttpHeaders headers;

        @Override
        public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
            context.proceed();

            final String header = headers.getHeaderString("X-Request-Header");
            context.getHeaders().add("X-Response-Header", header);
        }
    }

    @Test
    public void doit() {
        final Response response = target("hello").request()
                .header("X-Request-Header", "BooYah")
                .get();
        assertThat(response.getHeaderString("X-Response-Header"), is("BooYah"));
    }
}

Upvotes: 11

Stan
Stan

Reputation: 1430

Probably not best solution, but you can have your interceptor implementing ReaderInterceptor. There you can get headers and save them in ThreadLocal variable so you can access then in WriterInterceptor

Also if you have annotation based configuration you can try to inject ContainerRequestContext with a @Context annotation

Upvotes: 1

Related Questions