I need to override the HTTP "Host" Header value in a request sent using Axis2. The end goal is to send the HTTP request to a particular destination, while having the Host Header in the request read as something else.
I have looked this up and found that you can add custom headers, but the method used to do that will not allow you to override any.
http://axis.apache.org/axis2/java/core/api/org/apache/axis2/client/Options.html
Thanks!
Related
I am calling an API, that blacklists certain HttpHeaders including Content-Length which seems to be preset by the HttpClient underneath spring-openfeign.
To properly receive an API response, I'd need to remove the Content-Length header.
The following workarounds had been tried:
I tried to set the header to null or an empty String using the available Feign annotations #Headers, #RequestHeaders
I implemented a RequestInterceptor that creates a copy of the available (immutable) header map, deletes the blacklisted header and sets the Map as requestTemplate.headers(newHeaders). But only new headers can be added and the available ones not modified (seems to be really immutable ;))
I researched on overriding the used HttpClient but wasn't successful until now.
Experienced errors/ issues:
The API I am calling returns a 400 based on their header schema validation.
Code:
In case any code-snippets are needed, I am happy to provide them but to me the issue does not seem to be related to any code issue as I am not running into any exceptions.
Thanks in advance!!
The Apache Http Client included in feign-httpclient will always set the content length header if there is a request body present. One way to address this to configure the Apache Client directly and provide it to Feign via the builder:
This custom client can have an Apache Http Client interceptor applied that allows you to modify the request after it leaves Feign and before Apache sends it. Review their javadoc for more information.
public class Example {
public static void main(String[] args) {
HttpClient httpClient = HttpClients.custom.build();
GitHub github = Feign.builder()
.client(new ApacheHttpClient(httpClient))
.target(GitHub.class, "https://api.github.com");
}
}
FeignClient will preset Content_Length in the request header. In a keep-alive connection mode, either Content-Length or Transfer-Encoding header field must be set to signal the presence of a message body, so you can set Transfer-Encoding=chunked and Content-Length will be ignored by the serverside.
You can refer to rfc7230#section-3.3.1
"The presence of a message body in a request is signaled by a
Content-Length or Transfer-Encoding header field. Request message
framing is independent of method semantics, even if the method does
not define any use for a message body."
"In order to remain persistent, all messages on a connection need
to have a self-defined message length (i.e., one not defined by
closure of the connection), as described in Section 3.3. A server
MUST read the entire request message body or close the connection
after sending its response, since otherwise the remaining data on a
persistent connection would be misinterpreted as the next request.
Likewise, a client MUST read the entire response message body if it
intends to reuse the same connection for a subsequent request."
and from here , you can read:
"All HTTP/1.1 applications that receive entities MUST accept the
"chunked" transfer-coding (section 3.6), thus allowing this mechanism
to be used for messages when the message length cannot be determined
in advance.
Messages MUST NOT include both a Content-Length header field and a
non-identity transfer-coding. If the message does include a non-
identity transfer-coding, the Content-Length MUST be ignored.
When a Content-Length is given in a message where a message-body is
allowed, its field value MUST exactly match the number of OCTETs in
the message-body. HTTP/1.1 user agents MUST notify the user when an
invalid length is received and detected."
Title already says it, when i do an web-api call on my jetty servlet endpoint.
Is it enough to catch the
request.getMethod().equals("OPTIONS")
flag?
Or are there other possibilities to determine if the current request is of type preflight?
Preflight requests are sent as OPTIONS so you can check for that, yes.
But depending on what you are doing (I'm assuming some CORS filter?) you might also want to check if the following headers are present on the preflight: Access-Control-Request-Method (what HTTP method will be used when the actual request is made) and Access-Control-Request-Headers (what HTTP headers will be used when the actual request is made).
even though i have appended my service response with following provided CORS Headers :
resp.setContentType("application/json");
resp.addHeader("Access-Control-Allow-Origin", "*");
resp.addHeader("Access-Control-Allow-Credentials", "true");
resp.addHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS");
resp.addHeader("Access-Control-Allow-Headers", "Origin,accept,content-type");
resp.flushBuffer();
i am still getting below error in the console while trying to access some of the POST web methods in the service through my AngularJS frontend.
XMLHttpRequest cannot load http://192.***.*.***:8080/abc/def/search/vehicleManufacturer. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://192.***.*.***:8085' is therefore not allowed access.
However within the same class, some POST methods without any payloads are responding perfectly. Any suggestions ?
EDIT--------->
Below is my AngularJS client screen code for calling the web method:-
getVehicleModel : function(searchData,$scope){
$http({
method:'POST',
url:'http://192.169.*.***:8085/abc/def/search/vehicleModel',
dataType:'jsonp',
data:searchData
}).
success(function(data){
console.log("vehicle model")
$scope.vehicleModel = data.Response;
});
},
I think the problem here is Preflighted Requests in CORS.
From the Mozilla docs,
Unlike simple requests (discussed above), "preflighted" requests first
send an HTTP request by the OPTIONS method to the resource on the
other domain, in order to determine whether the actual request is safe
to send. Cross-site requests are preflighted like this since they may
have implications to user data. In particular, a request is
preflighted if:
It uses methods other than GET, HEAD or POST. Also, if POST is used to send request data with a Content-Type other than
application/x-www-form-urlencoded,
multipart/form-data
text/plain
e.g. if the POST request sends an XML payload to the server using application/xml or text/xml, then the request is preflighted.
It sets custom headers in the request (e.g. the request uses a header such as X-PINGOTHER)
As explained above, even though you're making a simple POST request, the Content-Type in your request is application/json which is different from the 3 types mentioned above, so it's considered as a Preflight request and an OPTIONS request is fired before your actual POST request.
You can solve this by implementing doOptions in your servlet, just add the headers there and it will work :)
The preflight (OPTIONS) is occurring due to the fact that you are sending a cross-origin ajax request AND specifying an Authorization header with this GET request.
Also (this is not causing an issue) I would suggest removing the contentType option. This doesn't make sense in the context of a GET request. A GET request should not have any content. All data should be included in the query string or, possibly, headers.
The Authorization header will not be sent with the OPTIONS. You must acknowledge it server-side, and then the browser will send the underlying GET. Read more about CORS at https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS .
I was wondering if anyone knows how to send custom HTTP headers using an XmlRpcClient in Java?
I see a custom header can be set using XmlRpcHttpTransport.setRequestHeader() but I don't see a way of tying this in with the XmlRpcClient itself.And I want to know how read response header. I use apache xmlrpc.Can you give me a demo. Thanks. My email :seraphyong#126.com
Is it possible to send HTTP POST request to a webserver and retrieve just headers of response or read just few bytes of the body, so the rest won't be downloaded at all (so it won't consume traffic)? If yes, how?
I know that there is a HEAD method for this, but I need to achieve it by POST method .. well, I am not sure if I need the POST method, I just need to post the data. Maybe if the webserver isn't secured well enough (it doesn't check what method it's used - it's just directly access the post data), is it possible to send "post data" by HEAD request?
There is no built-in HTTP mechanism for this, and HTTP HEAD requests do not allow content in the body. If however you are the one writing the server code then anything is possible.
If this is the case, I would suggest a URL parameter that triggers this behavior. For example:
POST /myURL - This would return the whole response
POST /myURL?body=minimal - Returns the reduced size response that you are looking for.
And you would have to code your server method to construct and return the appropriate response based on the URL parameter.