I'm trying to parse an HTTP request using the apache httpcore components and want to grab the body of the request. It looks like the default DefaultHttpRequestParser
doesn't parse the body/entity from its input stream. Is there a class that will do this?
Unfortunately I can't use the entire stack and need to pull the request straight from this input stream.
My parsing code is below. Looking at some of the other answers it appears that the body of the request should be available as an entity. However, every time I try to get at the entity it is null.
Debugging I see that the buffer has read but not used the body and that DefaultHttpRequestParser
seems to just read the header. Is there a parse I should be using to parse the entire input?
InputStream is = socket.getInputStream();
HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
SessionInputBufferImpl buf = new SessionInputBufferImpl(metrics, 2048);
buf.bind(is);
DefaultHttpRequestParser reqParser = new DefaultHttpRequestParser(buf);
HttpRequest req = reqParser.parse();
if (req instanceof HttpEntityEnclosingRequest) {
entity = ((HttpEntityEnclosingRequest)query).getEntity();
//... entity is always null
If I read the input stream I end up with:
POST / HTTP/1.1
User-Agent: curl/Q.XX.0 (linux-gnu) libcurl/Q.XX.0 OpenSSL/X.Y.Z zlib/A.B.C.D libidn/E.FF librtmp/G.H
Host: localhost:8088
Accept: */*
Content-Length: 333
Content-Type: multipart/form-data; boundary=----------------------------39203c7982df
------------------------------39203c7982df
Content-Disposition: form-data; name="fileupload"; filename="grun.sh"
Content-Type: application/octet-stream
#!/bin/bash -x
java -classpath lib/antlr-4.4-complete.jar:build/classes org.antlr.v4.runtime.misc.TestRig Typegroup "AHI" -tree
------------------------------39203c7982df--
[Update] Oleg has a good answer, but can I associate the body with the request or do I now need to pass two things around, the body and the stream? I'll be looking into
I got the following to work, but it's deprecated in the latest release.
...
HttpEntityEnclosingRequest ereq = (HttpEntityEnclosingRequest) req;
@SuppressWarnings("deprecation")
EntityDeserializer ed =
new EntityDeserializer(new LaxContentLengthStrategy());
@SuppressWarnings("deprecation")//ack!
HttpEntity ent = ed.deserialize(buf, req);
ereq.setEntity(ent);
return ereq;
Combining Oleg's solution with the above I ended up with:
HttpEntityEnclosingRequest ereq = (HttpEntityEnclosingRequest) req;
ContentLengthStrategy contentLengthStrategy =
StrictContentLengthStrategy.INSTANCE;
long len = contentLengthStrategy.determineLength(req);
InputStream contentStream = null;
if (len == ContentLengthStrategy.CHUNKED) {
contentStream = new ChunkedInputStream(buf);
} else if (len == ContentLengthStrategy.IDENTITY) {
contentStream = new IdentityInputStream(buf);
} else {
contentStream = new ContentLengthInputStream(buf, len);
}
BasicHttpEntity ent = new BasicHttpEntity();
ent.setContent(contentStream);
ereq.setEntity(ent);
return ereq;