I am using java Apache HttpClient to request a resource (B) with a timeout of 10s. If timeout exceeds Broken pipe is seen at the other application server.
Because of which Nginx at application B is not caching the response. How to gracefully close the connection so that the other app server (B) does not encounter broken pipe exception.
If you're using new enough HttpClient can't you do something like this (I just found a snippet someone else had written ... but see below where I've added ###)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://localhost:8081/test/resource"))
.header("Accept", "application/json")
.POST(HttpRequest.BodyPublishers.ofString("ping!"))
.build();
CompletableFuture<HttpResponse<String>> completableFuture =
client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
completableFuture
.completeOnTimeout(DEFAULT_RESPONSE, 1, TimeUnit.SECONDS) // ### ADD THIS the HttpClientRequest actually continues but the future has timed out so the user of the client progresses ??
.thenApplyAsync(HttpResponse::headers)
.thenAcceptAsync(System.out::println);
HttpResponse<String> response = completableFuture.join();
Related
i'm trying to use the Asynchronous API of the java 11 HttpClient library to GET data from my server. But to be in line with the best practices, I want the client to throttle the request to the server to be a max of 100 requests every minute. How should this be accomplished in java 11 HttpClient library?
In python, there is the aiohttp library that allows you to specify the parameters for throttling the request.
Is there such a thing for java 11 HttpClient library as well?
HttpClient client = HttpClient.newBuilder()
.version(Version.HTTP_2)
.followRedirects(Redirect.SAME_PROTOCOL)
.proxy(ProxySelector.of(new InetSocketAddress("www-proxy.com", 8080)))
.authenticator(Authenticator.getDefault())
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://openjdk.java.net/"))
.timeout(Duration.ofMinutes(1))
.header("Content-Type", "application/json")
.POST(BodyPublishers.ofFile(Paths.get("file.json")))
.build()
client.sendAsync(request, BodyHandlers.ofString())
.thenApply(response -> { System.out.println(response.statusCode());
return response; } )
.thenApply(HttpResponse::body)
.thenAccept(System.out::println);
link: https://openjdk.org/groups/net/httpclient/intro.html
I'm working on a project which requires to call GitHub APIs several times and I reached the limit of 60.
I read that with authentication you get 5000 as limit but I can't understand how I can authenticate my requests in my java program. I got my authentication token on Github and this is the way I'm building the request in java:
// create client
HttpClient client = HttpClient.newHttpClient();
// create request
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.github.com/repos/:owner/:repo/commits"))
.build();
what should I add to the request to authenticate it?
I tried adding the header authToken:myToken but it didn't work.
Solved:
Once I got the token on my GitHub profile > Settings > Developer Settings > Personal Access Tokens, I added the header `"Authorization: Bearer "myToken" " to the http request so the request becomes:
// create client
HttpClient client = HttpClient.newHttpClient();
// create request
HttpRequest request = HttpRequest.newBuilder().header("Authorization","Bearer <myToken>")
.uri(URI.create("https://api.github.com/repos/:owner/:repo/commits"))
.build();
You need to add Http request header Authorization to your request and the header should contain your token. So if your code is written on Java 11 or higher as it appears to be than you need to change your code to:
// create client
HttpClient client = HttpClient.newHttpClient();
// create request
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.github.com/repos/:owner/:repo/commits"))
.header("Authorization", "your-tocken")
.build();
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?
I need to write a small program, that constantly checks if the JSON file on the server has been updated (by some other process) to report the change to the user of the program.
I'm interested in best/correct practice of doing it: how would I implement the idea of "listening" to the file-change?
So far, my idea is:
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(getMessage, 0,1, TimeUnit.SECONDS);
where getMessage is the:
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("url/get_message"))
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
message = response.body();
I'm trying to understand how can I implement the use of a proxy for each request built like the following using Java API:
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.version(HttpClient.Version.HTTP_2)
.uri(URI.createh("https://myurl"))
.timeout(Duration.ofMinutes(2))
.setHeader("User-Agent","Just an user agent")
.GET()
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
I'm seeing from the doc (https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/HttpClient.html#Asynchronous%20Example)
that is possible with Synchronous requests. My code is within a method and it will run with threads parallelly. So how is it possible to set a proxy with Asynchronous Requests? If it is not possible, what's the difference between them?
Solved, it's a bit unclear the doc about that but at the end, I was able to set the proxy when building the client:
HttpClient client = HttpClient.newBuilder().
proxy(ProxySelector.of(new InetSocketAddress("proxy",port))))
.build();
//The request code is identical to what I wrote above.
The method is newBuilder anyway and not Builder.