Java HttpGet doesn't accept gzip - java

I am making an HttpGet to an url and I do not want the server to send the data gzipped. What header should I include in my HttpGet ?
With the default headers, the server sends gzipped data from time to time. I don't want this to happen. Thanks.

You want the Accept-Encoding HTTP request header.
Update: per #Selvin's comment, leave it empty or set it to "identity".
Update: The web application has to cooperate properly to be HTTP compliant, of course. If it's not honoring Accept-Encoding, look at its Content-Encoding HTTP response header. If it's "gzip", just read the response body with Java's GZIPInputStream.html. Then add "gzip" to your Accept-Encoding request header, since your client now handles GZIP. If the web application doesn't set the Content-Encoding header properly, that's another story altogether.

You should set the Accept-Encoding header to identity.

You could try to change the Accept-Encoding header, by removing the gzip|deflate value. If this doesn't work, you should also take into account that server doesn't care if the client supports the gzipped content (which is a bug and should be fixed).

Related

GET call on REST API with Accept as text/csv and content-Type as application/json. In what format should the reponse be?

GET call on REST API with Accept as text/csv and content-Type as application/json. In what format should the reponse be?
Should the response be in JSON format or in CSV format?
In HTTP, the Accept header is used by the client to tell the server what content types they'll accept.
The server will then send back the response and will set the Content-type header telling the client the type of the content actually returned.
You might have noticed that Content-type is also included in some HTTP requests. This is because some type of HTTP requests, like POST or PUT, can send data to the server. In this case the client tells the server the type of the content data, using the Content-type header.
Now to your question, a GET request should not have any Content-type header. I hope this is clear after my explanation above.
As you correctly note, the Accept header is used by HTTP clients to tell the server what content types they'll accept. The server will then send back a response, which will include a Content-Type header telling the client what the content type of the returned content actually is.
However, as you may have noticed, HTTP requests can also contain Content-Type headers. Why? Well, think about POST or PUT requests. With those request types, the client is actually sending a bunch of data to the server as part of the request, and the Content-Type header tells the server what the data actually is (and thus determines how the server will parse it).
In particular, for a POST request resulting from an HTML form submission, the Content-Type of the request will (normally) be one of the standard form content types below, as specified by the enctype attribute on the tag:
application/x-www-form-urlencoded (default, older, simpler, slightly less overhead for small amounts of simple ASCII text, no file upload support)
multipart/form-data (newer, adds support for file uploads, more efficient for large amounts of binary data or non-ASCII text)
source: https://webmasters.stackexchange.com/users/12578/ilmari-karonen
based on that, you should go for the parameter Accept!

What format and content-type is the body of a paypal rest access token call?

I am using Java with Jersey 2.0 client to make a REST call to the paypal REST API. According to the API doc, I should be making a post to: https://api.sandbox.paypal.com/v1/oauth2/token with the Accept: application/json and Accept-Language: en_US. It also indicates that I should pass in the body grant_type=client_credentials. I do all this but I keep getting a 406 or 415. What I can't figure out is what the Content-Type of the post call should be? I've tried text/plain, text/html, application/json, form-url-encoded.. nothing seems to get me a token back. Not sure why their API doc writer didn't include the Content-Type and format of the payload in the documentation. Anyone know what the Content-Type should be for the body of the post?
I'd like to add that when I do any Content-Type other than form-url-encoded, I get back 415, which means mediatype not accepted, however when I pass in anything using form-url-encoded, I get back the 406, which basically tells me the body is not acceptable.
Thanks.
Thanks for bringing up the question.
There was a recent change in the /token call and requests for an access token need to have the content-type set as application/x-www-form-urlencoded. This is done by default in cURL calls.
Updated docs that include a note about this will be going out very soon.
Inbound the OAuth 2 endpoint only accepts "application/x-www-form-urlencoded" or it will throw a 415, the payload then needs to be properly url encoded. Likewise the accepts header needs to contain "application/json", or the service will throw a 406.
For example:
Headers:
Authorization: Basic [base64 encoded]
Content-Type: application/x-www-form-urlencoded
Accepts: application/json
Payload sample:
grant_type=client_credentials&response_type=token

PAGE_CACHE_FILTER_STATE HTTP Header

I can't find information anywhere regarding this HTTP Header: PAGE_CACHE_FILTER_STATE.
When I try to access my RSS feed from a browser, this header has the value of NoCacheRequest, but when I access it from my Java application (URL.openConnection()), I've noticed that it gets set to FromCacheRequest and my RSS doesn't appear to update.
So I have two questions:
What is this HTTP header?
How can I make PAGE_CACHE_FILTER_STATE: NoCacheRequest for all requests?
I've never heard about nor seen PAGE_CACHE_FILTER_STATE before either, so I can't help you out with the actual specifications for it. It looks like a custom header telling you whether a cached version of the content was used or not.
To avoid caching, you could try programmatically adding something different to the URL each time. For example, you might add a random number:
http://www.example.com/feed.rss?no_cache=564482
http://www.example.com/feed.rss?no_cache=984637
You should also try sending the Pragma: no-cache and Cache-Control: no-cache HTTP headers when you request the RSS feed.

HttpClient: disabling chunked encoding

I am using the Apache Commons HttpClient along with Restlet to call a restful web service. Unfortunately, my server (based on Ruby on Rails) does not like the Transfer-Encoding: chunked that HttpClient is using by default.
Is there any way to disable the usage of chunked encoding for POSTs from the client?
As a general rule, for request not to be chunked, you need to specify exact size of post body, which for dynamically generated data means you need to buffer entire response in memory, see its size and only then send it.
Apache client documentation seems to confirm this: AbstractHttpEntity.setChunked() states
Note that the chunked setting is a hint only. If using HTTP/1.0, chunking is never performed. Otherwise, even if chunked is false, HttpClient must use chunk coding if the entity content length is unknown (-1).
As said in Restlet mailing list, in Restlet version 2.1, you can set ClientResource#entityBuffering property to true to cache content in memory and prevent chunked encoding.
The most reliable way, as #Slartibartfast hinted in his answer, is to explicitly switch HttpPost to HTTP 1.0 protocol.
Set apache HttpPost request to HTTP 1.0 protocol (the same for HttpGet, if you need this...):
HttpPost httpPost = new HttpPost(someUrl);
httpPost.setProtocolVersion(HttpVersion.HTTP_1_0); // Since v.4.3 of Apache HttpClient
When creating Multipart post request provide as an input for an attachment not an InputStream (as for HTTP 1.1, which causes chunked encoding), but an array of bytes, which you have to create from the same stream beforehand. This is why content length is known. See org.apache.http.entity.mime.MultipartEntityBuilder.addBinaryBody(String, byte[], ContentType, String)
I tested this for Android development, that required slightly different class names... (see https://github.com/andstatus/andstatus/issues/249 )

jax-ws change Content-type to Content-Type because server is hyper sensitive

I have to connect to a poorly implemented server that only understands Content-Type (capital-T) and not Content-type. How can I ask my JAX-WS client to send Content-Type?
I've tried:
Map<String, List<String>> headers = (Map<String, List<String>>)
((BindingProvider)port).getRequestContext().get(MessageContext.HTTP_REQUEST_HEADERS);
But headers is null. What am I doing wrong?
I have to connect to a poorly implemented server that only understands Content-Type(capital-T) and not Content-type. How can I ask my jax-ws client to send Content-Type?
I've dug this question a bit more and, sadly, I'm afraid the answer is: you can't. Let me share my findings.
First, the code that you'll find in https://jax-ws.dev.java.net/guide/HTTP_headers.html does not give you access to the HTTP headers of the future HTTP request (that hasn't been created at this point), it allows you to set additional HTTP headers for making a request (that will be added to the HTTP request later).
So, don't expect the following code to not return null if you don't put anything before (and actually, you'll only get what you put in there):
((BindingProvider)port).getRequestContext().get(MessageContext.HTTP_REQUEST_HEADERS);
Then, I did a little test based on the code provided in the same link:
AddNumbersImplService service = new AddNumbersImplService();
AddNumbersImpl port = service.getAddNumbersImplPort();
((BindingProvider)port).getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS,
Collections.singletonMap("X-Client-Version",Collections.singletonList("1.0-RC")));
port.addNumbers(3, 5);
And this is what I see in the HTTP request when running the client code:
POST /q2372336/addnumbers HTTP/1.1
Content-type: text/xml;charset="utf-8"
X-client-version: 1.0-RC
Soapaction: ""
Accept: text/xml, multipart/related, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
User-Agent: JAX-WS RI 2.1.6 in JDK 6
Host: localhost:8080
Connection: keep-alive
Content-Length: 249
Do you notice the difference: only the first char of the X-Client-Version header is kept upper cased, the rest is lowered!
And indeed, if you check the class c.s.x.w.t.Headers that is used to represent HTTP request (and response) headers, you'll see that it "normalizes" keys when they are added (in normalize(String)):
/* Normalize the key by converting to following form.
* First char upper case, rest lower case.
* key is presumed to be ASCII
*/
private String normalize (String key) {
...
}
So, while the c.s.x.w.t.h.c.HttpTransportPipe class (my understanding is that this is where the HTTP request is created, this is also where previously added headers will be added to the HTTP request headers) actually adds "Content-Type" as key in a c.s.x.w.t.Headers instance, the key will be modified because of the previously mentioned implementation detail.
I may be wrong but I don't see how this could be changed without patching the code. And the odd part is that I don't think that this "normalizing" stuff is really RFCs compliant (didn't check what RFCs say about headers case though). I'm surprised. Actually, you should raise an issue.
So I see three options here (since waiting for a fix might not be an option):
Patch the code yourself and rebuild JAX-WS RI (with all the drawbacks of this approach).
Try another JAX-WS implementation like CFX for your client.
Let the request go through some kind of custom proxy to modify the header on the fly.
You can modify the HTTP headers from the RequestContext. If you have access to the port object you can cast it to a javax.xml.ws.BindingProvider, which will give you access to the RequestContext.
You might also want to remove the unaccepted "Content-type" header.
This page shows how to do it in a bit more detail: https://jax-ws.dev.java.net/guide/HTTP_headers.html
Let me know if you need more code samples, or if you paste some of your code I can show you how to modify it.

Categories