title: Why Tomcat returns different headers for HEAD and GET requests to my RESTful API?
body: <p>My initial purpose was to verify the <em>HTTP chunked transfer</em>. But accidentally found this inconsistency.</p>
  
  <p>The API is designed to return a file to client. I use <code>HEAD</code> and <code>GET</code> methods against it.  <strong>Different headers are returned.</strong></p>
  
  <p>For <code>GET</code>, I get these headers: (This is what I expected.)</p>
  
  <p><a href="https://i.stack.imgur.com/naVSK.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/naVSK.png" alt="Transfer-Encoding: chunked, no Content-Length."></a></p>
  
  <p>For <code>HEAD</code>, I get these headers:</p>
  
  <p><a href="https://i.stack.imgur.com/ytiRS.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/ytiRS.png" alt="Content-Length: 1017118720, no Transfer-Encoding."></a></p>
  
  <p>According to <a href="https://stackoverflow.com/questions/15477742/http-head-and-get-different-result">this thread</a>, <code>HEAD</code> and <code>GET</code> <strong>SHOULD</strong> return identical headers but <strong>not necessarily</strong>.</p>
  
  <p><strong>My question is:</strong></p>
  
  <p>If <code>Transfer-Encoding: chunked</code> is used <em>because</em> the file is dynamically fed to the client and Tomcat server cannot know its size <em>beforehand</em>, how could  Tomcat know the <code>Content-Length</code> when <code>HEAD</code> method is used? Does Tomcat just <strong>dry-run</strong> the handler and count all the file bytes? Why doesn't it simply return the same <code>Transfer-Encoding: chunked</code> header?</p>
  
  <p>Below is my RESTful API implemented with <strong>Spring Web MVC</strong>:</p>
  
  <pre><code>@RestController
  public class ChunkedTransferAPI {
  
      @Autowired
      ServletContext servletContext;
  
      @RequestMapping(value = "bootfile.efi", method = { RequestMethod.GET, RequestMethod.HEAD })
      public void doHttpBoot(HttpServletResponse response) {
  
          String filename = "/bootfile.efi";
          try {
              ServletOutputStream output = response.getOutputStream();
              InputStream input = servletContext.getResourceAsStream(filename);
              BufferedInputStream bufferedInput = new BufferedInputStream(input);
              int datum = bufferedInput.read();
              while (datum != -1) {
                  output.write(datum);
                  datum = bufferedInput.read();
              }
              output.flush();
              output.close();
  
          } catch (IOException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          }
  
      }
  
  }
  </code></pre>
  
  <p><strong>ADD 1</strong></p>
  
  <p>In my code, I didn't explicitly add any headers, then it must be Tomcat that add the <code>Content-Length</code> and <code>Transfer-Encoding</code> headers as it sees fit. </p>
  
  <p><strong>So, what are the rules for Tomcat to decide which headers to send?</strong></p>
  
  <p><strong>ADD 2</strong></p>
  
  <p>Maybe it's related to how Tomcat works. I hope someone can shed some light here. Otherwise, I will debug into the source of Tomcat 8 and share the result. But that may take a while.</p>
  
  <p><strong>Related:</strong></p>
  
  <ul>
  <li><p><a href="https://stackoverflow.com/questions/15477742/http-head-and-get-different-result">HTTP HEAD and GET different result</a></p></li>
  <li><p><a href="https://stackoverflow.com/questions/3854842/content-length-header-with-head-requests">Content-Length header with HEAD requests?</a></p></li>
  </ul>