0

It seems somewhat awkward whenever I need to deal with custom responses data type on Spring MVC.

In my case, I need to return a JavaScript content. However, I want it to be cache.

So to clarify, this is not a static file case (<mvc:resources...), Instead it's a dynamic file generated on the server, that I do want to cache (i.e. HttpResponse 200 and HttpResponse 302).

In terms of code, on the client side I simply have:

<script src="<spring:url value='/some-file.js'/>"></script>

Than a SpringMVC controller:

@RequestMapping(value = "/some-file.js")
public ResponseEntity<String> resourceBundles(HttpServletRequest request, HttpServletResponse response, Locale locale) throws IOException {

    responseHeaders.add("Cache-Control", "public, max-age");
    responseHeaders.add("Content-Type", "text/javascript; charset=UTF-8");
    responseHeaders.add("Expires", "max-age");

    // Turn this into JSON response:
    String someJson = "{ a:a, b;b};";
    return new ResponseEntity<String>("var data = " + someJson, responseHeaders,  HttpStatus.OK);
}

However, it seems that the browser is always trying to access this dynamic JS file.

Since this file is Session depended, I can not generate it and treat it as a static file.

Any suggestions?

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
JAR.JAR.beans
  • 9,668
  • 4
  • 45
  • 57
  • This may be of use: http://stackoverflow.com/questions/1362930/how-do-you-set-cache-headers-in-spring-mvc – beny23 Jul 25 '12 at 09:43

1 Answers1

1

This is the correct behavior. Most browsers will send you a GET request with a If-Modified-Since + time stamp to check whether a file has changed.

In the usual case, you'd use the time stamp to figure out whether the file has changed. But since it never changes in your case, you can reply with a 304 / HttpStatus.NOT_MODIFIED response without a response body (instead of 200 / OK).

That tells the browser that the file hasn't changed.

This should work:

@RequestMapping(value = "/some-file.js")
public ResponseEntity<String> resourceBundles(
    HttpServletRequest request, 
    HttpServletResponse response, Locale locale) throws IOException {

    Date lmod = session.getAttribute("lmod");
    if( null == lmod ) {
        lmod = new Date();
        session.setAttribute("lmod", lmod);
    }

    responseHeaders.add("Last-Modified", lmod);

    String ifModifiedSince = request.getHeader("If-Modified-Since");
    if( null != ifModifiedSince ) { // You may want to compare lmod and ifModifiedSince here, too
        return new ResponseEntity( responseHeaders, HttpStatus.NOT_MODIFIED );
    }

    ... create first time response ...
}

Telling the browser Last-Modified will enable it to send you If-Modified-Since

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • Thanks. The logic is clear to me, it is not clear to me however how do I create a mechanism to reply with Either 200 or 304 based on the request from the client. Testing this in chrome, I do not see If-Modified-Sinse being sent. – JAR.JAR.beans Jul 25 '12 at 12:09
  • Thanks for the effort. This is more or less what I tried but isModifiedSince is null at all cases. I tested it with all browers to see a similar behavior. With chrome I can clearly see that this one "Dynamic" JS does not send this header while other JSs, located in the mvc:resources path, do send If-Modified-Since. I'll check if I can add this path to the mvc:resources group. – JAR.JAR.beans Jul 25 '12 at 13:21
  • Make sure `max-age` is valid (i.e. with a max-age; just giving the string will only confuse the browser). If the JS file is included in the page with a `script` element, the browser will cache it. The rules are slightly different if you use AJAX to load it and then `eval()` what the server sends (AJAX requests can tweak the caching). – Aaron Digulla Jul 25 '12 at 13:27
  • I ended up comparing the requests and responses in various cases and the only time I could get this to work is when setting only "Last-Modified" and than checking "If-Modified-Since". Your answer is obviously led me to the right direction. thanks. – JAR.JAR.beans Jul 25 '12 at 14:40
  • how can I tell the browser use cache and not make request to the server , thank you – kevin Jun 27 '19 at 09:11