/** @param sequenceNumber the index of this request on this connection. */
  private RecordedRequest readRequest(InputStream in, int sequenceNumber) throws IOException {
    String request = readAsciiUntilCrlf(in);
    if (request.equals("")) {
      return null; // end of data; no more requests
    }

    List<String> headers = new ArrayList<String>();
    int contentLength = -1;
    boolean chunked = false;
    String header;
    while (!(header = readAsciiUntilCrlf(in)).equals("")) {
      headers.add(header);
      String lowercaseHeader = header.toLowerCase();
      if (contentLength == -1 && lowercaseHeader.startsWith("content-length:")) {
        contentLength = Integer.parseInt(header.substring(15).trim());
      }
      if (lowercaseHeader.startsWith("transfer-encoding:")
          && lowercaseHeader.substring(18).trim().equals("chunked")) {
        chunked = true;
      }
    }

    boolean hasBody = false;
    TruncatingOutputStream requestBody = new TruncatingOutputStream();
    List<Integer> chunkSizes = new ArrayList<Integer>();
    if (contentLength != -1) {
      hasBody = true;
      transfer(contentLength, in, requestBody);
    } else if (chunked) {
      hasBody = true;
      while (true) {
        int chunkSize = Integer.parseInt(readAsciiUntilCrlf(in).trim(), 16);
        if (chunkSize == 0) {
          readEmptyLine(in);
          break;
        }
        chunkSizes.add(chunkSize);
        transfer(chunkSize, in, requestBody);
        readEmptyLine(in);
      }
    }

    if (request.startsWith("GET ")) {
      if (hasBody) {
        throw new IllegalArgumentException("GET requests should not have a body!");
      }
    } else if (request.startsWith("POST ")) {
      if (!hasBody) {
        throw new IllegalArgumentException("POST requests must have a body!");
      }
    } else {
      throw new UnsupportedOperationException("Unexpected method: " + request);
    }

    return new RecordedRequest(
        request,
        headers,
        chunkSizes,
        requestBody.numBytesReceived,
        requestBody.toByteArray(),
        sequenceNumber);
  }
示例#2
0
  /** @param sequenceNumber the index of this request on this connection. */
  private RecordedRequest readRequest(
      Socket socket, InputStream in, OutputStream out, int sequenceNumber) throws IOException {
    String request;
    try {
      request = readAsciiUntilCrlf(in);
    } catch (IOException streamIsClosed) {
      return null; // no request because we closed the stream
    }
    if (request.length() == 0) {
      return null; // no request because the stream is exhausted
    }

    List<String> headers = new ArrayList<String>();
    long contentLength = -1;
    boolean chunked = false;
    boolean expectContinue = false;
    String header;
    while ((header = readAsciiUntilCrlf(in)).length() != 0) {
      headers.add(header);
      String lowercaseHeader = header.toLowerCase(Locale.US);
      if (contentLength == -1 && lowercaseHeader.startsWith("content-length:")) {
        contentLength = Long.parseLong(header.substring(15).trim());
      }
      if (lowercaseHeader.startsWith("transfer-encoding:")
          && lowercaseHeader.substring(18).trim().equals("chunked")) {
        chunked = true;
      }
      if (lowercaseHeader.startsWith("expect:")
          && lowercaseHeader.substring(7).trim().equals("100-continue")) {
        expectContinue = true;
      }
    }

    if (expectContinue) {
      out.write(("HTTP/1.1 100 Continue\r\n").getBytes(Util.US_ASCII));
      out.write(("Content-Length: 0\r\n").getBytes(Util.US_ASCII));
      out.write(("\r\n").getBytes(Util.US_ASCII));
      out.flush();
    }

    boolean hasBody = false;
    TruncatingOutputStream requestBody = new TruncatingOutputStream();
    List<Integer> chunkSizes = new ArrayList<Integer>();
    if (contentLength != -1) {
      hasBody = true;
      transfer(contentLength, in, requestBody);
    } else if (chunked) {
      hasBody = true;
      while (true) {
        int chunkSize = Integer.parseInt(readAsciiUntilCrlf(in).trim(), 16);
        if (chunkSize == 0) {
          readEmptyLine(in);
          break;
        }
        chunkSizes.add(chunkSize);
        transfer(chunkSize, in, requestBody);
        readEmptyLine(in);
      }
    }

    if (request.startsWith("OPTIONS ")
        || request.startsWith("GET ")
        || request.startsWith("HEAD ")
        || request.startsWith("DELETE ")
        || request.startsWith("TRACE ")
        || request.startsWith("CONNECT ")) {
      if (hasBody) {
        throw new IllegalArgumentException("Request must not have a body: " + request);
      }
    } else if (!request.startsWith("POST ") && !request.startsWith("PUT ")) {
      throw new UnsupportedOperationException("Unexpected method: " + request);
    }

    return new RecordedRequest(
        request,
        headers,
        chunkSizes,
        requestBody.numBytesReceived,
        requestBody.toByteArray(),
        sequenceNumber,
        socket);
  }