im using a generated axis client to consume a service that requires headers
when using SOAPUI, i add the headers and the request looks like this
POST https://fttoo/service/v3.2/SOAP HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: text/xml;charset=UTF-8
SOAPAction: ""
Authorization: Bearer 123
Content-Length: 270
Host: my host
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
when trying to set the headers with code i'm doing the following
proxy = (SessionServiceImplServiceSoapBindingStub)locator.getSessionService();
proxy._setProperty("Authorization", "Bearer 123");
this is not working well and i get Error 401, when inspecting the proxy object i see that a property called cachedProperties has the value of {Authorization=Bearer 123}
I've also tried proxy._setProperty(HTTPConstants.HEADER_AUTHORIZATION, "Bearer 123");
and also inside the stub, in the _call object....
given the fact that axis 1 is very old i generated a new web client using CXF instead of Axis, this way i was able to use cxf api to place the headers
Related
I am sending a simple POST request with the built-in HttpURLConnection class, but I want to change the way Java separates the headers from the body (look at the outputs of tcpflow -a port 80 below). Here is the code:
// Create HttpURLConnection object
URL url = new URL("http://httpbin.org/post");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// Set request method
connection.setRequestMethod("POST");
// Write body and "Content-Length" header
String body = "This+is+the+body+of+the+post+request.";
connection.setRequestProperty("Content-Length",
String.valueOf(body.length()));
connection.setDoOutput(true);
connection.getOutputStream().write(body.getBytes("US-ASCII"));
// Send request
int responseCode = connection.getResponseCode();
When I execute that code and look at what Java actually sends using tcpflow -a port 80 (prints all requests/responses on port 80), I see the following (I cut away the response):
192.168.178.113.54654-054.225.177.165.00080: POST /post HTTP/1.1
User-Agent: Java/9
Host: httpbin.org
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Content-type: application/x-www-form-urlencoded
Content-Length: 37
192.168.178.113.54654-054.225.177.165.00080: This is the body of the post request.
The headers are correct, the body is correct. But I can see that the body is transferred in a separate connection. I know that this is a problem with java.net.HttpURLConnection because when I try the same with Apache's HttpClient, tcpflow -a port 80 gives me:
192.168.178.113.39708-054.243.202.193.00080: POST /post HTTP/1.1
Content-Length: 37
Host: httpbin.org
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.3 (Java/9)
Accept-Encoding: gzip,deflate
This+is+the+body+of+the+post+request.
Here the body is sent with the headers, separated with just /r/n/r/n. I would like the Java library (java.net.HttpURLConnection) to do the same. Is that possible?
EDIT: I found out that the reason the server rejected my requests was not that the body was in a different packet (packet, not connection, as Julian Reschke pointed out) than the headers but just that I sent the wrong data facepalm.
I have a problem with Google HTTP Client Library for Java (1.22.0).
This is my code
String url = "http://gazetapraca.pl/ogl/2502758";
GenericUrl genericUrl = new GenericUrl(url);
ApacheHttpTransport apacheHttpTransport = new ApacheHttpTransport();
HttpRequest httpRequest = apacheHttpTransport.createRequestFactory().buildGetRequest(genericUrl);
httpRequest.setFollowRedirects(true);
HttpResponse httpResponse = httpRequest.execute();
and httpRequest.execute() throws
com.google.api.client.http.HttpResponseException: 301 Moved Permanently
Below is follow from Wireshark
GET /ogl/2502758 HTTP/1.1
Accept-Encoding: gzip
User-Agent: Google-HTTP-Java-Client/1.22.0 (gzip)
Host: gazetapraca.pl
Connection: Keep-Alive
HTTP/1.1 301 Moved Permanently
Date: Sat, 26 Nov 2016 22:15:52 GMT
Server: Apache
Location: /ogl/2502758/pakowacz+-+mile+widziane+panie
Content-Length: 0
Set-Cookie: JSESSIONID_JOBS=2f1TffY6JYcb6zvBSrQ72fds7rfdsSnHM3sefw6D31Lfr434bnkDmdLQJLvLFZ6zkYBF!-12116034235597; path=/; HttpOnly
Content-Language: pl
P3P: CP="NOI DSP COR NID PSAo OUR IND"
Vary: User-Agent
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
GET /ogl/2502758/pakowacz%20-%20mile%20widziane%20panie HTTP/1.1
Accept-Encoding: gzip
User-Agent: Google-HTTP-Java-Client/1.22.0 (gzip)
Host: gazetapraca.pl
Connection: Keep-Alive
Cookie: JSESSIONID_JOBS=2f1TffY6JYcb6zvBSrQ72fds7rfdsSnHM3sefw6D31Lfr434bnkDmdLQJLvLFZ6zkYBF!-12116034235597
HTTP/1.1 301 Moved Permanently
Date: Sat, 26 Nov 2016 22:15:52 GMT
Server: Apache
Location: /ogl/2502758/pakowacz+-+mile+widziane+panie
Content-Length: 0
Content-Language: pl
P3P: CP="NOI DSP COR NID PSAo OUR IND"
Vary: User-Agent
Keep-Alive: timeout=2, max=99
Connection: Keep-Alive
and repeat a few times.
Maybe the problem is with url, because location is /ogl/2502758/pakowacz+-+mile+widziane+panie and next request method get is /ogl/2502758/pakowacz%20-%20mile%20widziane%20panie.
In other software and library everything is working (google chrome browser, postman - addon to chrome, JSOUP - java library).
Does anyone have an idea how to solve the problem?
This is not your library's fault.
To understand why this problem is occurring, we must first understand the "error" message associated with your problem:
com.google.api.client.http.HttpResponseException: 301 Moved Permanently
So, what does this mean? Well, the last part of the error message, the description says "301 Moved Permanently". What that is referring to is an HTTP Status Code. An HTTP Status Code indicates what the outcome of a specific request is. In this case, the status code was 301, which according to RFC protocol means:
The requested resource has been assigned a new permanent URI and any future references to this resource SHOULD use one of the returned URIs.
So, this means that the URL that you are using is no longer valid, and that you have to use the new URL given to you by the Location response header. Now, it seems that the library that you're using is smart enough to detect this, and initializes a new request to the new URL. That's great and all, but your library that you are using, is incorrectly escaping the url provided by the Location header, and using that for the new request (turning /ogl/2502758/pakowacz+-+mile+widziane+panie into /ogl/2502758/pakowacz%20-%20mile%20widziane%20panie), and the server receiving this request recognizes that those to paths are not the same (even though they should be. So, the server sends another 301 response, telling the client (the library in this case) to use the un-escaped URL instead of the escaped one, even though they should be the same.
Now, why is your library doing this? It turns out that, according to RFC spec, the '+' character is reserved for URIs. That means that that character, along with other characters are only intended for use in URIs for their intended purpose. Therefore, it is not standard to include the '+' character in URIs, unless it is used for a very specific purpose, which it looks like is not the case.
So, this all means that you cannot blame the library for this error, you can only blame the people who developed this site.
The reason that this works in your browser and other places is because those clients do not seem to be escaping the requested URL for you before sending it to the server.
I have read this: compress-responses-in-jersey and have Jersey 2 config:
#ApplicationPath("/jaxrs/")
public class AppConfig extends ResourceConfig {
public AppConfig() {
super(AdvertisementResource.class, MultiPartFeature.class);
packages("jaxrs");
EncodingFilter.enableFor(this, GZipEncoder.class, DeflateEncoder.class);
}
}
I have header Request:
GET http://localhost:8081/jaxrs/admin-adblock
Accept:application/json
Cache-Control:no-cache
Content-Type:application/json
Authorization:Basic c21h...
Accept-Encoding:gzip,deflate
But header response are:
HTTP/1.1 200 OK
Content-Type: application/json
Vary: Accept-Encoding
Server: Jetty(9.2.2.v20140723)
Header in response Content-Encoding:gzip is missing only Vary: Accept-Encoding is appear if I have:
EncodingFilter.enableFor(this, GZipEncoder.class, DeflateEncoder.class);
If I remove compression and comment EncodingFilter row response header are:
HTTP/1.1 200 OK
Content-Type: application/json
Transfer-Encoding: chunked
Server: Jetty(9.2.2.v20140723)
or this:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 369
Server: Jetty(9.2.2.v20140723)
I`m testing with Intellij Rest Client Tool and I`m not sure if I receive compressed response from server?
I have download jersey sources and set breakpoint here and debug rest service web application with Intellij it appears that CONTENT_ENCODING gzip is added here:
response.getHeaders().putSingle(HttpHeaders.CONTENT_ENCODING, contentEncoding);
but its missing in response header from Intellij Rest Client tool..
I have download SoapUI and test the same Rest requests response headers:
HTTP/1.1 200 OK
Content-Type: application/json
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 204
Server: Jetty(9.2.2.v20140723)
The Intellij Rest Client Tool is hiding response headers Content-Encoding and Content-Length..
I have open new issue
I am able to set content type using cxf library but I don't know how to set Authorization header. Whenever I set user name and password then it set Authorization header and encode whole value and add Basic. I don't want to do this. I want to add Authorization header with plain string which ever I provide. Please help me to solve out this problem.
AMPServices services = new AMPServices();
CoreXmlPort coreXmlPort = services.getAMPSoapService();
Client client = ClientProxy.getClient(coreXmlPort);
HTTPConduit httpConduit = (HTTPConduit) client.getConduit();
HTTPClientPolicy httpClientPolicy=httpConduit.getClient();
String contentType=httpClientPolicy.getContentType();
contentType="application/soap+xml; type=vnd.iShip.AMP.SOAP; charset=UTF-8";
httpClientPolicy.setContentType(contentType);
AuthorizationPolicy authorizationPolicy = new AuthorizationPolicy();
authorizationPolicy.setUserName("username");
authorizationPolicy.setPassword("password");
httpConduit.setAuthorization(authorizationPolicy);
It generates following request xml.
POST https://api.iship.com/Root/Enterprises/Pitney%20Bowes/Progistics; HTTP/1.1
Content-Type: application/soap+xml; type=vnd.iShip.AMP.SOAP; charset=UTF-8
Accept: */*
Authorization: Basic aXNoaXAgcGIvd3NkZXZlbDowNzZhNjFjYTM5MDcxODAxODVjNWRkMjM2YTdkMzZhNGQ1ODg5OWFj
User-Agent: Apache CXF 3.1.0
Cache-Control: no-cache
Pragma: no-cache
Host: api.iship.com
Connection: keep-alive
Content-Length: 246
But I want this type of request
POST https://api.iship.com/Root/Enterprises/Pitney%20Bowes/Progistics; HTTP/1.1
Content-Type: application/soap+xml; type=vnd.iShip.AMP.SOAP; charset=UTF-8
Accept: */*
Authorization: username;password
User-Agent: Apache CXF 3.1.0
Cache-Control: no-cache
Pragma: no-cache
Host: api.iship.com
Connection: keep-alive
Content-Length: 246
But I was not able to do it. Please help me to solve out this problem.
Thanks,
Awadhendra
I think you are trying to call is a RestFul Service, so that's why the server side always response with a different content type than you expected (json instead of soap/xml). Is your url endpoint based on http protocol? If yes, do you need send additional parameters to this url?
The issue here is that the client you are using to interact with Webservice expecting XML based Soap Messages , while the service is serving JSON as a return media.
Either convert your client to use the JSON format and communicate using that, or alternatively use the XML based endpoint , consult with webservice provider for that.
When I set "Authorization" header with setHeader from HttpPost then hostname disappears from request and there is always error 400 (bad request) returned. Same code is working fine on pure java (without android) and when I remove setting "Authorization" header also on android it works fine, but I need authorization.
This is a code (domain changed):
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("http://myhost.com/test.php");
post.setHeader("Accept", "application/json");
post.setHeader("User-Agent", "Apache-HttpClient/4.1 (java 1.5)");
post.setHeader("Host", "myhost.com");
post.setHeader("Authorization",getB64Auth());
List <NameValuePair> nvps = new ArrayList <NameValuePair>();
nvps.add(new BasicNameValuePair("data[body]", "test"));
AbstractHttpEntity ent=new UrlEncodedFormEntity(nvps, HTTP.UTF_8);
ent.setContentType("application/x-www-form-urlencoded; charset=UTF-8");
ent.setContentEncoding("UTF-8");
post.setEntity(ent);
post.setURI(new URI("http://myhost.com/test.php"));
HttpResponse response =client.execute(post);
Method getB64Auth() returns "login:password" encoded using Base64 like: "YnxpcYRlc3RwMTulHGhlSGs=" but it's not important.
This is a piece of lighttpd's error.log when above code is invoked on pure java:
2011-02-23 15:37:36: (request.c.304) fd: 8 request-len: 308
POST /test.php HTTP/1.1
Accept: application/json
User-Agent: Apache-HttpClient/4.1 (java 1.5)
Host: myhost.com
Authorization: Basic YnxpcYRlc3RwMTulHGhlSGs=
Content-Length: 21
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Encoding: UTF-8
Connection: Keep-Alive
HTTP/1.1 200 OK
Content-type: text/html
Transfer-Encoding: chunked
and record from access.log (IP changed):
1.1.1.1 myhost.com - [23/Feb/2011:15:37:36 +0100] "POST /test.php HTTP/1.1" 200 32 "-" "Apache-HttpClient/4.1 (java 1.5)"
When the same code is invoked on android, I get this in logs:
POST /test.php HTTP/1.1
Accept: application/json
User-Agent: Apache-HttpClient/4.1 (java 1.5)
Host: myhost.com
Authorization: Basic YnxpcYRlc3RwMTulHGhlSGs=
Content-Length: 21
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Encoding: UTF-8
Connection: Keep-Alive
Expect: 100-Continue
2011-02-23 15:45:10: (response.c.128) Response-Header:
HTTP/1.1 400 Bad Request
Content-Type: text/html
Content-Length: 349
Connection: close
access.log:
1.1.1.1 - - [23/Feb/2011:15:45:10 +0100] "POST /test.php HTTP/1.1" 400 349 "-" "Apache-HttpClient/4.1 (java 1.5)"
How to get Authorization with POST working on android?
When I use HttpURLConnection instead of HttpClient it is no difference.
Thanks to Samuh for a hint :)
There was an extra newline character inserted which has no means in GET requests, but matters in POST ones.
This is proper way to generate Authorization header in android (in getB64Auth in this case):
private String getB64Auth (String login, String pass) {
String source=login+":"+pass;
String ret="Basic "+Base64.encodeToString(source.getBytes(),Base64.URL_SAFE|Base64.NO_WRAP);
return ret;
}
The Base64.NO_WRAP flag was lacking.
use simply this :
String authorizationString = "Basic " + Base64.encodeToString(
("your_login" + ":" + "your_password").getBytes(),
Base64.NO_WRAP); //Base64.NO_WRAP flag
post.setHeader("Authorization", authorizationString);