0

I have a simple Spring MVC 3.2 based application hosted on Google App Engine. Controllers return ModelAndView objects for GET requests, and the pages use JSP.

Instead of instrumenting each Controller with a handler for HEAD requests, I followed the instructions on this blog and created a filter: http://axelfontaine.com/blog/http-head.html

It works, except that the content length is never set and is returned as 0. Using breakpoints, I confirmed that the write methods in the NoBodyOutputStream class are not called, and when examining the source code of the ServletOutputStream and its base classes, I did not find other write methods that would be called instead (this could be an oversight on my part, though).

Has anyone had success in using a filter to handle HEAD requests in more recent versions of Spring MVC?

EDIT

GAE uses an embedded Jetty-6-1-x server.

Here is a sample controller:

@Controller
@RequestMapping("resources")
public class ResourcesController {

    @RequestMapping(method = RequestMethod.GET)
    public ModelAndView getResourcesPage() {
        return new ModelAndView("resources");
    }
}

Here is the relevant content from the web.xml file:

<filter>
    <filter-name>HttpHeadFilter</filter-name>
    <filter-class>com.foo.filter.HttpHeadFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>HttpHeadFilter</filter-name>
    <servlet-name>mvc-dispatcher</servlet-name>
</filter-mapping>

<servlet>
    <servlet-name>mvc-dispatcher</servlet-name>
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

I modified the HttpHeadFilter, and the problem seems to be with how the request is wrapped, because the Controller's GET method is invoked but no response is written:

if (isHttpHead(httpServletRequest)) {
    chain.doFilter(new ForceGetRequestWrapper(httpServletRequest), response);
} else {
    chain.doFilter(request, response);    
}
mustbealennox
  • 125
  • 1
  • 15
  • I don't get it. Responses to `HEAD` requests should not have a body. What's the problem? – Sotirios Delimanolis Mar 17 '14 at 16:27
  • It should not have a body, but it should have a content length set in the response header. – mustbealennox Mar 17 '14 at 16:30
  • As I mentioned, I don't want to instrument each Controller with a method to handle HEAD requests. – mustbealennox Mar 17 '14 at 16:31
  • @SotiriosDelimanolis A HEAD should be identical do a GET request except it has no body. – Bart Mar 17 '14 at 16:33
  • Are you using the `Content-Length` as a versioning tool for caching? It might be easier to use ETag and an internal versioning system. – Sotirios Delimanolis Mar 17 '14 at 16:48
  • Just ran a example with the `HttpHeadFilter` and it works like expected. Have you tested locally? Maybe it's something specific to GAE. – Bart Mar 17 '14 at 16:48
  • @Bart I've tested locally, and will try uploading the change and see if it behaves differently once it is hosted. What version of Spring MVC did you use, and what was your GET method handler returning (ResponseBody, String, ModelAndView)? – mustbealennox Mar 17 '14 at 16:54
  • If the `write` method of `NoBodyOutputStream` is never called, I'm guessing something else is up. Can you give us a small reproducible example? – Sotirios Delimanolis Mar 17 '14 at 17:03
  • Used the 3.2.8.RELEASE version with both GET and HEAD headers identical. Like @SotiriosDelimanolis said, likely something else is the culprit. – Bart Mar 17 '14 at 17:17

1 Answers1

0

This appears to be a known issue with Google App Engine: https://code.google.com/p/googleappengine/issues/detail?id=2719

mustbealennox
  • 125
  • 1
  • 15