Get content from HTTP request even if there is no

2019-02-25 08:55发布

问题:

Am testing with a client who send me a HTTP request with no content length header but has a content.

How do I extract this content without the help of contentlength header?

回答1:

I've kept the original answer for completeness, but I've just been looking in the HTTP RFC (2616) section 4.3:

The presence of a message-body in a request is signaled by the inclusion of a Content-Length or Transfer-Encoding header field in the request's message-headers. A message-body MUST NOT be included in a request if the specification of the request method (section 5.1.1) does not allow sending an entity-body in requests. A server SHOULD read and forward a message-body on any request; if the request method does not include defined semantics for an entity-body, then the message-body SHOULD be ignored when handling the request.

So if you haven't got a content length, you must have a Transfer-Encoding (and if you haven't, you should respond with a 400 status to indicate a bad request or 411 ("length required")). At that point, you do what the Transfer-Encoding tells you :)

Now if you're dealing with a servlet API (or a similar HTTP API) it may well handle all this for you - at which point you may be able to use the techique below to read from the stream until it yields no more data, as the API will take care of it (i.e. it won't just be a raw socket stream).

If you could give us more information about your context, that would help.


Original answer

If there's no content length, that means the content continues until the end of the data (when the socket closes).

Keep reading from the input stream (e.g. writing it to a ByteArrayOutputStream to store it, or possibly a file) until InputStream.read returns -1. For example:

byte[] buffer = new byte[8192];
ByteArrayOutputStream output = new ByteArrayOutputStream();
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1)
{
    output.write(buffer, 0, bytesRead);
}
// Now use the data in "output"

EDIT: As has been pointed out in comments, the client could be using a chunked encoding. Normally the HTTP API you're using should deal with this for you, but if you're dealing with a raw socket you'd have to handle it yourself.

The point about this being a request (and therefore the client not being able to close the connection) is an interesting one - I thought the client could just shut down the sending part, but I don't see how that maps to anything in TCP at the moment. My low-level networking knowledge isn't what it might be.

If this answer turns out to be "definitely useless" I'll delete it...



回答2:

If this were a response then the message could be terminated by closing the connection. But that's not an option here because the client still needs to read the response.

Apart from Content-Length:, the other methods of determining content length are:

  • Transfer-Encoding: chunked
  • guesswork

Hopefully it's the former, in which case the request should look something like this:

POST /some/path HTTP/1.1
Host: www.example.com
Content-Type: text/plain
Transfer-Encoding: chunked

25
This is the data in the first chunk

1C
and this is the second one

3
con
8
sequence
0

(shamelessly stolen from the Wikipedia article and modified for a request)

  • each chunk is of the form: hex-encoded length, CRLF, data, CRLF
  • after the final data-carrying chunk comes a zero-length chunk with no data
  • after the zero-length chunk comes optional extra HTTP headers
  • after the optional HTTP headers comes another CRLF


回答3:

See HTTPbis Part1, Section 3.3.



标签: java http header