JBoss7 setting Cache-Control, Pragma to no-cache for all responses from RESTEasy
Asked Answered
T

2

12

I'm trying to add Cache-Control headers to the responses generated in JBoss 7 using the RESTEasy framework. However, all the responses end up getting multiple Cache-Control headers due to JBoss adding a no-cache header by default.

I can't find any setting to remove it and adding interceptors is also not working since a no-cache header is being added later.

Can someone tell me how to disable the default pragma and cache-control headers in JBoss 7?

Note: I'm using resteasy with Stateless EJBs.

@Path("/api")
@Local
public interface UCSRestServiceInterface
{
    @GET
    @Path("/token")
    @Produces("application/json")
    @Cache(maxAge = 3600, noTransform = true)
    public Response getToken();
}

Getting the response headers as,

{
  "pragma": "No-cache",
  "date": "Thu, 11 Feb 2016 20:16:30 GMT",
  "content-encoding": "gzip",
  "server": "Apache-Coyote/1.1",
  "x-frame-options": "SAMEORIGIN",
  "vary": "Accept-Encoding,User-Agent",
  "content-type": "application/json",
  "cache-control": "no-cache, no-transform, max-age=3600",
  "transfer-encoding": "chunked",
  "connection": "Keep-Alive",
  "keep-alive": "timeout=15, max=100",
  "expires": "Wed, 31 Dec 1969 19:00:00 EST"
}
Trencher answered 30/1, 2016 at 2:47 Comment(2)
Write a filter. Take the response; and manipulate the headers you want.Urbanus
I have the same issue with wildfly 10 (and it also seems to be like that in wildfly 8) where there is always also the following present in the reponse header: "Cache-Control: no-cache, no-store, must-revalidate". Adding the @Cache annotation just adds a second header field. This can't be correct behavior! Did you find a solution to this problem?Ieper
U
1

A Filter resource in a web-app basically lets you intercept requests and response and mainly designed for some use cases which work by altering request/response headers. More details here

Since you are using RESTEasy you can make use of ContainerResponseFilter; a filter interface provided by JAX-RS. You can write your custom filter by implementing this interface. The filter class(add one to your web app source code) will look like below:-

@Provider
public class YourCustomFilter implements ContainerResponseFilter{

// you can check the actual string value by using method "getStringHeaders" on 'resp' below
private static final String CACHE_CONTROL = "cache-control";

@Override
public void filter(ContainerRequestContext req,
        ContainerResponseContext resp) throws IOException {

    if(resp.getHeaders().containsKey(CACHE_CONTROL)){
       resp.getHeaders().remove(CACHE_CONTROL);
       resp.getHeaders().add(CACHE_CONTROL, "no-transform, max-age=3600");
    }
    resp.getHeaders().add(CACHE_CONTROL, "no-transform, max-age=3600");

  }

}

Here you basically check for the prescense of Cache-Control header and if present remove the existing one and add one of your own. Please dont forget the @Provider annotation which is needed by the jax rs runtime to discover your custom filter.

Note that with this filter all requests to your webapp will be intercepted. If you want a certain resource or a resource method to be intercepted you can explore the use of @NameBinding

Let me know if that works.

Urbanus answered 15/2, 2016 at 11:20 Comment(6)
Sorry. But adding a filter is also not solving the problem. The only header found by the filter is content-type which indicates JBOSS is adding the Pragma + Cache-Control header after the response filter is processed.Trencher
Looks like there is a solution at access.redhat.com/solutions/28847 but I don't have paid subscription to view it.Trencher
Sorry. Was away from SO for couple of days. You can try two things:- 1) Try Adding @BindingPriority(0) annotation to your Filter. 2) Navigate to your server.xml found in <JBOSSDIR/ deploy/jboss-web/server.xml and check for any cache setting set on a valve tag and change that .Urbanus
Don't see any BindingPriority annotation in resteasy. There is no valve setting in standalone.xml in jboss 7 (server.xml is in older versions).Trencher
Tried @Priority but still didn't help. The issue appears to be non jax-rs or resteasy related.Trencher
@Gary, thank you, I had the same error with JBoss. I found this on that link: "The Pragma and Cache-Control headers are automatically inserted in the response when the web application is secured with a <security-constraint>."Sarcoid
D
0

I found this workaround consisting in setting empty value for Pragma header when "Cache-Control" header is present and "no-cache" is absent

import javax.annotation.Priority;
import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.Provider;
import java.io.IOException;

@Priority(Priorities.HEADER_DECORATOR - 1)
@Provider
public class PragmaRemover implements ContainerResponseFilter {

    private static final String PRAGMA = "Pragma";

    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
        MultivaluedMap<String, Object> headers = responseContext.getHeaders();
        if(headers.containsKey(HttpHeaders.CACHE_CONTROL)){
            for (Object header : headers.get(HttpHeaders.CACHE_CONTROL)) {
                CacheControl cacheControl = (CacheControl) header;
                if(!cacheControl.isNoCache()){
                    headers.add(PRAGMA, "");
                }
            }
        }
    }
}

Priorities.HEADER_DECORATOR - 1 is to be sure that the cache header has been set by resteasy.

And don't forget to add this filter to your Jax-Rs application.

Dunlap answered 22/8, 2019 at 14:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.