How can I disable default request headers from apache httpclient 4? - java

I am using apache common httpclient 4.3.3 to make http 1.0 request. Here is how I make the request
HttpClient client = HttpClientBuilder.create().build();
HttpPost post = new HttpPost(url);
post.setProtocolVersion(new ProtocolVersion("HTTP", 1, 0));
// trying to remove default headers but it doesn't work
post.removeHeaders("User-Agent");
post.removeHeaders("Accept-Encoding");
post.removeHeaders("Connection");
post.setEntity(new ByteArrayEntity(ba) );
HttpResponse response = client.execute(post);
However, i can see that there are other headers automatically added to my request to the server like
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.3.3 (java 1.5)
Accept-Encoding: gzip,deflate
How can I tell httpclient not to include any other headers? I tried to removed those headers with post.removeHeaders(xxxx) but it doesn't work. Can you show me how?
Thanks,

If you call HttpClientBuilder.create(), you will have a httpClientBuilder.
And httpClientBuilder has a lot config for default headers and this will be used to make intercepters( ex: RequestAcceptEncoding ).
For example, RequestAcceptEncoding, which implements HttpRequestInterceptor, makes Accept-Encoding: gzip,deflate header when HttpProcessor.process() is invoked.
And httpProcessor.process() will be invoked just before invoking
final CloseableHttpResponse response = this.requestExecutor.execute(route, request, context, execAware);
You can see this code at org.apache.http.impl.execchain.ProtocolExec of httpclient-4.3.6 line 193.
If you want to remove Accept-Encoding: gzip,deflate, call HttpClientBuilder.disableContentCompression() like below.
HttpClient client = HttpClientBuilder.create().disableContentCompression().build();
In short, HttpClientBuilder has a lot of flags to disable/enable HttpRequestInterceptor. If you disable/enable those HttpRequestInterceptor, you can exclude/include default headers.
Sorry for my poor English, and hope you get what I mean.

CloseableHttpClient hc = HttpClients.custom()
.setHttpProcessor(HttpProcessorBuilder.create().build())
.build();
The code snippet above demonstrates how to create an HttpClient instance with an empty (no-op) protocol processor, which guarantees no request headers will ever be added to outgoing messages executed by such client

You want to do your 'cleanup' at the end, after HttpClient is done modifying the request. You can do this by calling addInterceptorLast on HttpClientBuilder as below.
HttpClient client = HttpClientBuilder.create().addInterceptorLast(
new HttpRequestInterceptor() {
public void process(HttpRequest request, HttpContext context){
request.removeHeaders("Host");
request.removeHeaders("Connection");
}
}
).build();
I create an anonymous class implementing HttpRequestInterceptor. Take whatever header modifications you need done before the request is sent, and put them in the process method.

I think you could add your implementation of HttpRequestInterceptor with client.addRequestInterceptor()
or (better)
remove all interceptors that add headers to the request (RequestUserAgent, RequestDefaultHeaders, RequestClientConnControl, RequestAcceptEncoding, ...).
Removing them is also easy:
client.removeRequestInterceptorByClass(RequestAcceptEncoding.class);

Related

Howto send PUT request without content and Content-Length header with Apache http client?

I'd like to test (via automated test) how server (and all proxies in-the-middle) responds to a PUT request without body and Content-Length header.
Similar to what curl does
curl -XPUT http://example.com
with Apache HTTP client (4.5.13)
But it looks like it always adds Content-Length header if I specify no body.
Is there any way to do that with Apache HTTP client?
Already tried (no luck)
final HttpPut request = new HttpPut(url);
request.removeHeaders("Content-Length");
Use a request interceptor to modify requests generated by the standard protocol processor
CloseableHttpClient httpClient = HttpClients.custom()
.addInterceptorLast((HttpRequestInterceptor) (request, context) ->
request.removeHeaders(HttpHeaders.CONTENT_LENGTH))
.build();
HttpPut httpPut = new HttpPut("http://httpbin.org/put");
httpClient.execute(httpPut, response -> {
EntityUtils.consume(response.getEntity());
return null;
});

how to properly make a POST request using Java Apache HttpClient?

I am trying to use a web API in a Java program using Apache HttpClient5.
Using a simple request with curl:
curl -X POST -H "x-api-user: d904bd62-da08-416b-a816-ba797c9ee265" -H "x-api-key: xxxxxxxxxxx" https://habitica.com/api/v3/user/class/cast/valorousPresence
I get the expected response and effect.
Using my Java code:
URI uri = new URIBuilder()
.setScheme("https")
.setHost("habitica.com")
.setPath("/api/v3/user/class/cast/valorousPresence")
.build();
Logger logger = LoggerFactory.getLogger(MyClass.class);
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
HttpPost httpPost = new HttpPost(uri);
httpPost.addHeader(new BasicHeader("x-api-user",getApiUser()));
httpPost.addHeader(new BasicHeader("x-api-key", getApiKey()));
CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
logger.info(httpResponse.toString());
return httpResponse.getCode();
The output I get when running the Java call is
411 Length Required HTTP/1.0
I'm sure I'm not constructing the POST call correctly, how should it be done? I've tried specifying Content-Type and that has no effect. Trying to set Content-Length in the code causes compilation errors (as I understand it, this is handled behind the scenes by HttpClient5).
All my GET requests using HttpClient5 work fine.
A POST always has a payload (content). A POST without content is unusual, so are you sure you didn't forget something?
You need to call setEntity() to set the payload, even if it is empty, because it is the entity that sets the Content-Length header.
E.g. you could call httpPost.setEntity(new StringEntity("")), which sets Content-Type: text/plain and Content-Length: 0.

Add Proxy to HttpRequest in java

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.

How to set the default header for all requests in apache http client?

For example the default user agent could be set like:
client.getParams().setParameter(CoreProtocolPNames.USER_AGENT, someName);
But how to set the "Accept" header?
HttpClient 4.3 now allows configuring a collection of default headers on the client itself:
Header header = new BasicHeader(HttpHeaders.CONTENT_TYPE, "application/json");
List<Header> headers = Lists.newArrayList(header);
HttpClient client = HttpClients.custom().setDefaultHeaders(headers).build();
HttpUriRequest request = RequestBuilder.get().setUri(SAMPLE_URL).build();
client.execute(request);
Now, all requests executed by that client will be send with the default headers.
Hope that helps.

How to set HTTP Request Header "authentication" using HTTPClient?

I want to set the HTTP Request header "Authorization" when sending a POST request to a server.
How do I do it in Java? Does HttpClient have any support for it?
http://www.w3.org/Protocols/HTTP/HTRQ_Headers.html#z9
The server requires me to set some specific value for the authorization field:
of the form ID:signature which they will then use to authenticate the request.
Thanks
Ajay
Below is the example for setting request headers
HttpPost post = new HttpPost("someurl");
post.addHeader(key1, value1));
post.addHeader(key2, value2));
Here is the code for a Basic Access Authentication:
HttpPost request = new HttpPost("http://example.com/auth");
request.addHeader("Authorization", "Basic ThisIsJustAnExample");
And then just an example of how to execute it:
HttpParams httpParams = new BasicHttpParams();
HttpProtocolParams.setVersion(httpParams, HttpVersion.HTTP_1_1);
HttpConnectionParams.setConnectionTimeout(httpParams, 3000);
HttpClient httpclient = null;
httpclient = new DefaultHttpClient(httpParams);
HttpResponse response = httpclient.execute(request);
Log.d("Log------------", "Status Code: " + response.getStatusLine().getStatusCode());
This question is "answered" here:
Http Basic Authentication in Java using HttpClient?
There are many ways to do this. It was frustrating for me to try to find the answer. I found that the best was the Apache docs for HttpClient.
Note: answers will change over time as the libraries used will have deprecated methods.
http://hc.apache.org/httpcomponents-client-4.5.x/tutorial/html/authentication.html

Categories

Resources