how java unirest to set content-length - java

java.
I use Unirest.post to post my multipart data. but server shows error to me:
multipart: NextPart: EOF.
I find that, if I set Content-Length I can solve this.
Here the code:
String buff = "my data";
HttpResponse<String> res = Unirest.post(url)
.header("Content-Type", multipart.getContentType().getValue())
.header("Content-Length", String.valueOf(buff.length()))
.body(buff).asString();
But after I add .header("Content-Length", String.valueOf(buff.length())), run java I get error:
org.apache.http.client.ClientProtocolException
How can I solve this?

You need to remove the earlier set content length so that you can set a new one.
#John Rix's answer This code helped solved the problem
private static class ContentLengthHeaderRemover implements HttpRequestInterceptor{
#Override
public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
request.removeHeaders(HTTP.CONTENT_LEN);// fighting org.apache.http.protocol.RequestContent's ProtocolException("Content-Length header already present");
}
}
HttpClient client = HttpClients.custom()
.addInterceptorFirst(new ContentLengthHeaderRemover())
.build();

Related

Okhttp3: Need help to use HeaderInterceptor

I would like to use a global header for all my requests. Therefore I have implemented the following class:
public class HeaderInterceptor {
public Response intercept(Chain chain) throws IOException {
Request request = chain.request()
.newBuilder()
.method("GET", null)
.addHeader("Accept", "application/json")
.addHeader("Basic ", "abcdefghi123456789")
.build();
Response response = chain.proceed(request);
return response;
}
}
Now I would like to do the following in the main()-method:
public static void main(String[] args) throws Exception {
OkHttpClient httpClient = new OkHttpClient.Builder().addInterceptor(MyInterceptor).build();
Request reqAllProjects = new Request.Builder()
.url("https://example.com/projects")
.build();
Response resAllProjects = httpClient.newCall(reqAllProjects).execute();
String responseData = resAllProjects.body().string();
System.out.println(responseData);
}
I'm not sure now how to use my HeaderInterceptor. I guess I'll have to enter it here, right?
OkHttpClient httpClient = new OkHttpClient.Builder().addInterceptor(??MyInterceptor??).build();
I tried something like this: addInterceptor(HeaderInterceptor.intercept()) but this is not working...
Can someone help me please? And does the rest of it look fine? Many thanks in advance!
The interceptor class that you have created doesn't seem to be implementing the Interceptor interface. You need to implement as below
public class HeaderInterceptor implements Interceptor {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request()
.newBuilder()
.addHeader("Accept", "application/json")
.addHeader("Basic ", "abcdefghi123456789")
.build();
Response response = chain.proceed(request);
return response;
}
}
Do note that you should not be modifying the method and body of the request as .method("GET", null) unless you actually need so, as it can result in all the HTTP requests made by the client to make GET requests with null body.
Then add the interceptor while building the client as below
OkHttpClient httpClient = new OkHttpClient.Builder()
.addInterceptor(new HeaderInterceptor()).build();
Have a look at the OkHttp documentation for more info.
Have you checked this question : Okhttp3: Add global header to all requests error
It should be something like
.addInterceptor(new Interceptor())

Unable to set Test.APIKeyAuthToken

This is my code:
public static final String API_TOKEN = "safasfasdfesareasdadasd";
public static final String APIKeyAuthToken = "Auth-Token";
But the Auth-Token is not being found in the header request.
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
Request.Builder requestBuilder = original.newBuilder()
.addHeader("Accept", "application/json")
.addHeader("Content-Type", "application/json");
requestBuilder.addHeader(Test.APIKeyAuthToken, Test.API_TOKEN);
Request request = requestBuilder.build();
return chain.proceed(request);
}
Despite it is rather unclear which API you are even talking about - and what you might mean with "not working" (this is not an error description at all) ...the HTTP header probably should look alike:
.addHeader("Authorization", API_TOKEN)
Just see the API documentation, which string-format is actually being expected... because "not working" might possibly mean, just sending some random header, which the API doesn't accept.

Does java.net.http.HttpClient need closing?

I'm using the new java.net.http.HttpClient and from my tests after about 378026 times of calling it, I start to get the following:
Caused by: java.net.ConnectException: Cannot assign requested address
at java.net.http/jdk.internal.net.http.common.Utils.toConnectException(Utils.java:964)
at java.net.http/jdk.internal.net.http.PlainHttpConnection.connectAsync(PlainHttpConnection.java:179)
at java.net.http/jdk.internal.net.http.AsyncSSLConnection.connectAsync(AsyncSSLConnection.java:56)
at java.net.http/jdk.internal.net.http.Http2Connection.createAsync(Http2Connection.java:369)
at java.net.http/jdk.internal.net.http.Http2ClientImpl.getConnectionFor(Http2ClientImpl.java:127)
at java.net.http/jdk.internal.net.http.ExchangeImpl.get(ExchangeImpl.java:88)
at java.net.http/jdk.internal.net.http.Exchange.establishExchange(Exchange.java:293)
at java.net.http/jdk.internal.net.http.Exchange.responseAsyncImpl0(Exchange.java:425)
at java.net.http/jdk.internal.net.http.Exchange.responseAsyncImpl(Exchange.java:330)
at java.net.http/jdk.internal.net.http.Exchange.responseAsync(Exchange.java:322)
at java.net.http/jdk.internal.net.http.MultiExchange.responseAsyncImpl(MultiExchange.java:304)
at java.net.http/jdk.internal.net.http.MultiExchange.lambda$responseAsync0$2(MultiExchange.java:250)
at java.base/java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1072)
at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:506)
at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1705)
at java.net.http/jdk.internal.net.http.HttpClientImpl$DelegatingExecutor.execute(HttpClientImpl.java:153)
at java.base/java.util.concurrent.CompletableFuture.completeAsync(CompletableFuture.java:2591)
at java.net.http/jdk.internal.net.http.MultiExchange.responseAsync(MultiExchange.java:204)
at java.net.http/jdk.internal.net.http.HttpClientImpl.sendAsync(HttpClientImpl.java:632)
Below is the class that I use:
public class JavaHttpClient {
HttpClient httpClient = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(30))
.followRedirects(HttpClient.Redirect.ALWAYS).build();
public String getRequest(String incomingUrl) throws IOException, InterruptedException {
HttpRequest request = HttpRequest.newBuilder().uri(URI.create(incomingUrl)).GET().build();
HttpResponse<String> response = httpClient.send(request, BodyHandlers.ofString());
return response.body();
}
}
I don't understand why this is happening. I assume something is being left open that should have been closed?
The HttpClient will close all opened connections when it's no longer referenced and there's no operations in progress (all responses have been received).

How to avoid sending Cookie header in java unirest requests?

I noticed that using unirest java library cookies are by default sent in requests after being set in responses (just like any browser does). Is there any way to avoid it?
Example:
public class Main {
private static HttpResponse<JsonNode> doRequest() throws UnirestException {
try {
HttpResponse<JsonNode> jsonResponse = Unirest
.get("http://example.com")
.header("Accept", "application/json").asJson();
return jsonResponse;
} catch (UnirestException e) {
throw e;
}
}
public static void main(String[] args) throws UnirestException {
//first request receive a set-cookie header in response
doRequest();
//second request send a Cookie header with the cookie set by the first one: can I avoid this?
doRequest();
}
}
It is probably due to a default setting on the underlying HttpClient implementation. Setting a custom HttpClient seems to work:
HttpClient httpClient = HttpClients.custom()
.disableCookieManagement()
.build();
Unirest.setHttpClient(httpClient);
Looks like
Unirest.config().enableCookieManagement(false);
solves the problem.

CRest / How to configure to accecpt only JSON responce

I am using CRest to deserialize a JSON stream on Android. My first steps looks very promising.
To get the JSON stream from the server and not the XML one I use the following construct:
(Accept: application/json)
#EndPoint("http://localhost:8080/myserver/rest")
#Param(name = "Accept", value = "application/json", dest = Destination.HEADER)
public interface VersionService {
#ConnectionTimeout(10000)
#Path("/version")
VersionTO getVersion();
}
This works but it's a bit annoying to copy the "Param thing" for every service.
Is there a better way to configure all Services at one place only to return JSON?
Well I'm afraid there isn't any simple way in the current version, but feel free to open a request on the issue tracker.
Cheers,
Laurent
I faced a similar situation where I used a custom HTTP client. In your case it could look like as follows:
DefaultHttpClient client = new DefaultHttpClient();
client.addRequestInterceptor(new HttpRequestInterceptor() {
public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
request.addHeader("Accept", "application/json");
}
});
CRestBuilder builder = new CRestBuilder();
builder.expectsJson();
builder.setRestService(new HttpClientRestService(client));
Another option is to set default parameter for ClientPNames.DEFAULT_HEADERS of the custom HttpClient instance.
Details can be found on http://hc.apache.org/httpcomponents-client-ga/tutorial/html/httpagent.html.

Categories