Java HTTP Request Size - java

I created object of HTTPRequestBase from package org.apache.http.client.methods
after that I send the object vie CloseableHttpClient
protected CloseableHttpClient httpClient;
HttpRequestBase httpRequest = this.createHttpRequest(request);
this.httpClient.execute(httpRequest, new BasicResponseHandler());
I want to check httpRequest size before I send it. I need it to be limited to a specific number of MB.
How can I check its size?

it's not easy. The header and the body of the request are part of the HTTP application protocol.if your server use ssl,the certificate is sent as part of the SSL / TLS configuration ... before HTTP starts. Even the simple measurement of the amount of data in an HTTP request is tricky. A typical HTTP stack does not assemble the entire request message in one place and does not retain the cumulative total of the data sent. Depending on the HTTP stack you use, you can (in theory) use a custom socket factory and socket flows that count bytes sent.

Related

How to set socket timeout in Java HTTP Client

We want to migrate all our apache-httpclient-4.x code to java-http-client code to reduce dependencies. While migrating them, i ran into the following issue under java 11:
How to set the socket timeout in Java HTTP Client?
With apache-httpclient-4.x we can set the connection timeout and the socket timeout like this:
DefaultHttpClient httpClient = new DefaultHttpClient();
int timeout = 5; // seconds
HttpParams httpParams = httpClient.getParams();
httpParams.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, timeout * 1000);
httpParams.setParameter(CoreConnectionPNames.SO_TIMEOUT, timeout * 1000);
With java-http-client i can only set the connection timeout like this:
HttpClient httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(5))
.build()
But i found no way to set the socket timeout. Is there any way or an open issue to support that in the future?
You can specify it at the HttpRequest.Builder level via the timeout method:
HttpClient httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(5))
.build();
HttpRequest httpRequest = HttpRequest.newBuilder()
.uri(URI.create("..."))
.timeout(Duration.ofSeconds(5)) //this
.build();
httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
If you've got connected successfully but not able to receive a response at the desired amount of time, java.net.http.HttpTimeoutException: request timed out will be thrown (in contrast with java.net.http.HttpConnectTimeoutException: HTTP connect timed out which will be thrown if you don't get a successful connection).
There doesn't seem to be a way to specify a timeout on the flow of packets (socket timeout) on the Java Http Client.
I found an enhancement request on OpenJDK which seems to cover this possibility - https://bugs.openjdk.org/browse/JDK-8258397
Content from the link
The HttpClient lets you set a connection timeout (HttpClient.Builder) and a request timeout (HttpRequest.Builder). However the request timeout will be cancelled as soon as the response headers have been read. There is currently no timeout covering the reception of the body.
A possibility for the caller is to make use of the CompletableFuture API (get/join will accept a timeout, or CF::orTimeout can be called).
IIRC - in that case, it will still be the responsibility of the caller to cancel the request. We might want to reexamine and possibility change that.
The disadvantage here is that some of our BodyHandlers (ofPublisher, ofInputStream) will return immediately - so the CF API won't help in this case.
This might be a good thing (or not).
Another possibility could be to add a body timeout on HttpRequest.Builder. This would then cover all cases - but do we really want to timeout in the case of ofInputStream or ofPublisher if the caller doesn't read the body fast enough?

Java httpClient streaming request

I'm trying to reproduce some behavior provide by my front end app by using a java http client.
I'm trying to send (stream) binary data from httpClient to server over PUT request. So content type is application/octet-stream. I've to send an unknown amount of data that is incoming.
Firstly, I used Apache HttpClient because it can handle digest authentication easily (that's is a requirement). For it, I use ContentProducer that enable writing directly to the OutputStream.
Below is an example:
HttpPut sendDataReq= new HttpPut(
HTTP_URI);
ContentProducer myContentProducer = new ContentProducer() {
#Override
public void writeTo(OutputStream out) throws IOException
{
out.write("ContentProducer rocks!".getBytes());
out.write(("Time requested: " + new Date()).getBytes());
}
};
HttpEntity myEntity = new EntityTemplate(myContentProducer);
sendDataReq.setEntity(myEntity );
HttpResponse response= httpClient.execute(sendDataReq);
I expect from this piece of code to stream request (AND NOT RESPONSE) from client to server.
By using Wireshark, I'm able to see my PUT request but it is send over TCP protocol and then nothing. When I try to listen using my front end web app, I can see that the PUT request is sent over HTTP protocol with 0 content length, data is then sent bytes by bytes (packet of some amount of bytes) over HTTP protocol with a log info: CONTINUATION.
Also, I tried with httpUrlConnection but there is no digestAuthentication implementation. So, I give up to use it.
Any hints of what is bad in my ContentProducer and how to accomplish it? Using other java HTTP clients? I can provide Wireshark log of what is expected and what I have.

Is it necessary to read data before close http response?

Is it necessary to read request data before calling the close method of response inside a http server in java?
I have a http server written by sun's http server. When I receive a http request, I just simply do the following steps:
write my text to response body
close the response
Does it matter to read the request body before closing the response?
Note that I have too many http requests on my server. (10000 call/sec.)
My benchmark says if request body does not have too much data, there is no big difference between two methods. I didn't get any timeout and other type of exceptions using both methods.
This is the time benchmark result for 1M request using 100 concurrent threads (10000 request per thread) on both methods:
Don't read request body: 210,581ms
Read request body: 206,599ms

Example of a Protocol Buffer being sent in http by java

You set content-type to application/x-protobuf, then you serialize the protocol buffer, and then put the binary data into an http body. Send it to server/client!
What is a standard way to program such a task in java?
You can also use Jetty HTTP client, it's as easy as
ContentResponse response = httpClient.newRequest("http://domain.com/upload")
.method(HttpMethod.POST)
.content(new InputStreamContentProvider(new FileInputStream("serialized_protocol.bin")), "application/x-protobuf")
.send();
See http://www.eclipse.org/jetty/documentation/9.4.x/http-client-api.html#http-client-content

multiple http requests when processing streaming response using httpcomponents

I'm a newbie to http and Apache's HttpComponents API.
I need to process a streaming response of an http request using Apache's HttpComponents, while there may be additional http requests made on that connection. For example, a POST request is initially made to http://mystreams.net, which later follows with additional requests, while throughout I have to listen and process the streaming response. I need to hold the same initial connection I made.
How can I do that? I was able to create a simple HttpClient and do a simple HttpPost request and then process the response entity that is non-streaming, but how do I hold on to it when it continues to stream data and at the same time make new requests to the same address using the same context (ie cookies)?
Is your streaming data coming back as a single HTTP response? If so, you won't be able to receive other responses on that connection until it is done. But you could take the cookies from that response (while it is still streaming the entity to you) and use them to make other requests on another connection.
HttpEntity entity = httpclient.execute(httpget).getEntity();
InputStream is = entity.getContent()
when calling the stream, use a new Thread, and make subsequent requests in the main thread (or, better, in separate thread for reach)
Also check here

Categories

Resources