title: Problem reading request body in servlet
body: <p>I'am writing a HTTP proxy that is part of a test/verification
  system. The proxy filters all requests coming from the client device
  and directs them towards various systems under test.</p>
  
  <p>The proxy is implemented as a servlet where each request is forwarded
  to the target system, it handles both GET and POST. Somtimes the
  response from the target system is altered to fit various test
  conditions, but that is not the part of the problem.</p>
  
  <p>When forwarding a request, all headers are copied except for those
  that is part of the actual HTTP transfer such as Content-Length and
  Connection headers.</p>
  
  <p>If the request is a HTTP POST, then the entity body of the request is
  forwarded as well and here is where it doesnt work sometimes.</p>
  
  <p>The code reading the entity body from the servlet request is the following:</p>
  
  <pre><code>URL url = new URL(targetURL);
  HttpURLConnection conn  = (HttpURLConnection)url.openConnection();
  String method = request.getMethod();
  
  java.util.Enumeration headers = request.getHeaderNames();
  while(headers.hasMoreElements()) {
  
      String headerName = (String)headers.nextElement();
      String headerValue = request.getHeader(headerName);
  
      if (...) { // do various adaptive stuff based on header 
  
      }
  
      conn.setRequestProperty(headerName, headerValue);
  }
  </code></pre>
  
  <p>// here is the part that fails</p>
  
  <pre><code>char postBody[] = new char[1024];
  int len;
  
  if(method.equals("POST")) {
      logger.debug("guiProxy, handle post, read request body");
      conn.setDoOutput(true);
  
      BufferedReader br = request.getReader();
      BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
  
      do {
          logger.debug("Read request into buffer of size: " + postBody.length);
  
          len = br.read(postBody, 0, postBody.length);
          logger.debug("guiProxy, send request body, got " + len + " bytes from request");
  
          if(len != -1) {
              bw.write(postBody, 0, len);
          }
      } while(len != -1);
      bw.close();
  }
  </code></pre>
  
  <p>So what happends is that the first time a POST is received, -1
  characters are read from the request reader, a wireshark trace shows
  that the entity body containing URL encoded post parameters are there
  and it is in one TCP segment so there is no network related
  differences.</p>
  
  <p>The second time, br.read successfully returns the 232 bytes in the
  POST request entity body and every forthcoming request works as well.</p>
  
  <p>The only difference between the first and forthcoming POST requests is
  that in the first one, no cookies are present, but in the second one,
  a cookie is present that maps to the JSESSION.</p>
  
  <p>Can it be a side effect of entity body not being available since the
  request processing in the servlet container allready has read the POST
  parameters, but why does it work on forthcoming requests.</p>
  
  <p>I believe that the solution is of course to ignore the entity body on
  POST requests containing URL encoded data and fetch all parameters
  from the servlet request instead using getParameter and reinsert them
  int the outgoing request.</p>
  
  <p>Allthough that is tricky since the POST request could contain GET
  parameters, not in our application right now, but implementing it
  correctly is some work.</p>
  
  <p>So my question is basically: why do the reader from
  request.getReader() return -1 when reading and an entity body is
  present in the request, if the entity body is not available for
  reading, then getReader should throw an illegal state exception. I
  have also tried with InputStream using getInputStream() with the same
  results.</p>
  
  <p>All of this is tested on apache-tomcat-6.0.18.</p>