HTTP Response 411 Length Required, Http Client 4.0.1 Android - android

i'm sending an http request to the google reader api and getting an unusual response code. following the documentation, i've requested an auth code and included it in the header of every request. after performing the login, and getting an auth code, i tried accessing this url, which is part of the documentation:
http://www.google.com/reader/api/0/stream/items/contents
when i send the request, i get a 411 status code, which is supposed to mean "Length Required". the length, as i've found, is supposed to be the length, in octets, of the message body. there is no message body in this request. there is only a single header, the POST parameter i="item id" and the URL itself. i tried setting the "Content-Length" header to "0" and also to "-1" to no avail.
what's really interesting is that this same code worked fine before google changed their authorization procedure. it's apparent they've changed something else...
so my question is what EXACTLY would cause a 411 response code and how can i prevent it?

This error happens only with POST and PUT request types, as these two (sort of) expect to have a request body that includes the request parameters (plain textual as well as attachments).
However as the documentation suggests, this is largely an obsolete value, and realistically the web services should handle requests without relying on Content-Length.
So it's not the problem of a request sender, but it is (I would say) a bug on the service side.
Nevertheless, setting a Content-Length (mind the proper capitalisation) request header to 0 should be the workaround.

Related

Requests not being made from android app, with max-age set

I have an api that returns an object as the response, and an etag and max age as headers. The response looks like this:
HEADERS:
'x-frame-options': 'SAMEORIGIN',
'x-xss-protection': '1; mode=block',
'x-content-type-options': 'nosniff',
'x-download-options': 'noopen',
'strict-transport-security': 'max-age=15778476000; includeSubDomains',
'access-control-allow-origin': '*',
etag: 'c69148a0489a95058e729bde7fd4bf32bf2077b1cba8d4fcf0c2da6e696fa33e',
'cache-control': 'private,max-age=43200'
BODY:
{
id: 1985,
url: "https://example.com",
...
}
The desired scenario is that an android application makes the request to ask for this data. The Api returns the data, along with an max age of 43200 secs.
If a request is made before 43200 secs pass, the application has the data from the last response cached. The application makes the request nevertheless, the back-end service compiles the response data, uses the request's etag to decide whether the response data has changed. If the data has changed, it returns a 200 http status and the data. Otherwise it returns a 403 status and no data.
The application receives the response. It uses fast networking to handle caching (says my android teammate). If a 200 status code was returned, the data are updated. Otherwise the application keeps the old data.
If a request is made after 43200 secs have passed, the application no longer has the cached response or it's etag. The request is made, the data are considered as 'new' even if nothing has changed in the data, the status code 200 is returned along with max-age header as above.
What actually happens:
For some reason, after the first request is processed and the application receives the data, no request is made until 43200 secs have passed. The android developer says they see that the request is made and 0 bytes are returned, but when I monitor the requests in the server I don't see any made towards this API.
This doesn't make sense, since max-age does not imply that no requests are made. It simply instructs the application to keep the data in the cache for the duration.
Am I missing the idea of how cache, etags and max-age work?
Back-end is built in node js, and uses express for routing.
You've only set the max-age and private directives in the Cache-Control header. The actual behaviour you have described is the correct behaviour since max-age directive has no bearing on forcing the cache to validate responses each time a request is made. For that, you have to add the no-cache directive as well to the Cache-Control header.
The no-cache directives tells the cache to always validate the stored response with the origin server before serving it (i.e., the desired behaviour you have described). Upon revalidation, the stored response will be valid for another 43200 secs (max-age). Without the no-cache directive, the HTTP client is free to make use of cached responses. Which I guess is why your friend said the request was made, but 0 bytes were returned (browsers also show 0 bytes for responses served from the cache). And which is also why you didn't observe any incoming requests to the server.
Have a look at this article from Google for a good overview on HTTP caching:
https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching
If you need in-depth detail on how responses are constructed from caches, have a look at the RFC7234 spec: https://www.rfc-editor.org/rfc/rfc7234#section-4

Max HTTP response size in Volley Android

I'm using Volley to make a server call, which can in some cases return a large response - a few megabytes JSON.
When the server response is more "normal" size, everything works, but with a large payload Volley throws a NetworkError without any details attached and logs a weird message - BasicNetwork.performRequest: Unexpected response code 200.
I'm pretty sure the issue is with response size, so my question is whether there a known limit for HTTP request/response size in Android/Volley, or a setting to change it. I know some HTTP libraries have it.
I know the server is fine as there are other clients using the same server endpoint in the same way.
I started debugging inside the library code and found that the response code is indeed 200 and the correct data is being received. The request content is being copied from response stream in chunks, but at some point something goes wrong in the copying.
This is the closest I could get to the original exception. Apparently, a java.net.ProtocolException is getting thrown sometime during the while loop at first breakpoint shown on the picture. You can also see the actual JSON content is there.
Then this exception gets handled and re-thrown a couple more times:

okhttp: how to handle unrequested/unexpected 100 (continue) response from server?

TLDR: Is there a way to force OkHttp to correctly handle unexpected/unrequested 100 Continue HTTP responses?
I'm using OkHttp 3.8.1 on Android to POST to a poorly-behaved server.
Even though the request does not include an "Expect: 100-continue" header, the web server returns a 100 Continue response. Rather than continuing to send the request body, then getting the actual (200) response, OkHttp stops there and sends back the 100 Continue response in my okhttp.Callback.
I tried explicitly including "Expect: 100-continue" in the request to trigger OkHttp's logic, but the server (possibly due to some bug) claims the header is malformed and rejects the request. I also tried sending "Expect:" (no value), but the server still sends the 100 Continue response and OkHttp stops there.
Other HTTP clients (I've tested 3 so far) can talk to that server just fine. They handle the 100 Continue response correctly even though they didn't see "Expect: 100-continue" in the request header. Is there an option I can set, or an interceptor I can write, to make OkHttp do the same?
Sounds like something we can fix in OkHttp. This is weird and the server is broken, but if other clients handle it OkHttp should too.
Please report a bug there?

Retrofit incorrect response error on android

When i call any webService with expired token,the service returns code 498 with error message "your tokken is expired"..BUT the retrofit gives the response code 500 with error message " internel server error".
response.code() //500 instead of 498
I tested the same url with postman and its working fine but the issue is only with retrofit.
I am using same services on IOS with AFNetworking and its also working fine there.
Any body can help to figure out why this is happening? thanks in advance.
This is not a full answer, but it's too big for a comment.
5xx codes are server errors, this means that the server is crashing, not the app nor is retrofit buggy. The issue most likely is in the server, but can be caused by retrofit - yes, that's true.
My experience with all the questions that say: "I tried this insert random network call here with postman and it works, but retrofit returns 500" is because postman adds headers by default, which retrofit doesn't. The server implementation then expects these headers to be set and due to a faulty implementation crashes if said headers are missing.
I would check the headers retrofit is sending and the headers postman is sending and compare both and make sure which one crashes the server.
It can also be that OkHttp (Retrofit uses OkHttp under the hood) is adding some headers which the server cannot cope with. This would be stranger to me, but not impossible. I think it adds for example by default gzip and some servers might not handle this correctly.
If you have access to the server, than it might even be worth checking there the logs. They might point you right away to the issue.
I'm sorry but I cannot point you directly to the problem. These are just tips to get you started. Hope they help.

How to get a HEAD of a Retrofit call from an api endpoint that requires field in the request body?

I am trying to examine the headers of a response from an API call made via Retrofit 2.0.2 before actually downloading the content.
My API interface looks like the following:
#Headers({"Accept: application/json", "Origin: http://www.example.com"})
#HEAD("profiles")
Call<Void> getProfileHeaders(#Field("puids") String puid);
Please note that the API call requires me to specify in the body a field called puids=%{UUID} list of UUIDs in order to return a response.
If I would like to download the data without examining the headers first, I would just call an interface like this:
#Headers({"Accept: application/json", "Origin: http://www.example.com"})
#FormUrlEncoded
#POST("profiles")
Call<String> getProfile(#Field("puids") String puid);
Now the issue is that when I try to use the getProfileHeader() endpoint, I get the following RuntimeException:
java.lang.IllegalArgumentException: #Field parameters can only be used with form encoding. (parameter #1)
In order to use the #Field parameters (as I suppose a POST method would normally would do if required), I would have to explicitly specify that I use #FormUrlEncoded, but I can't make a #HEAD call with that.
I am a bit puzzled how could I achieve what I want and what am I missing?
Basically I would like to know how can I examine a retrofit call's response headers before downloading the actual body, of an API endpoint that requires field parameters?
Cheers!
Ok, I just realized that my confusion originates from a couple of misunderstandings:
#HEAD is an HTTP method to usually verify the hyperlinks validity and the server's response to a GET call. It does not work with POST request and it is theoretically incorrect.
Taken from RFC2616 of the HTTP/1.1 definitions:
The HEAD method is identical to GET except that the server MUST NOT
return a message-body in the response. The metainformation contained
in the HTTP headers in response to a HEAD request SHOULD be identical
to the information sent in response to a GET request. This method can
be used for obtaining metainformation about the entity implied by the
request without transferring the entity-body itself. This method is
often used for testing hypertext links for validity, accessibility,
and recent modification.
The response to a HEAD request MAY be cacheable in the sense that the
information contained in the response MAY be used to update a
previously cached entity from that resource. If the new field values
indicate that the cached entity differs from the current entity (as
would be indicated by a change in Content-Length, Content-MD5, ETag or
Last-Modified), then the cache MUST treat the cache entry as stale.
When making a POST request by definition we already calculated the response server-side and taken the time to download the body in consideration.
One of the function's of the POST method, as defined in RFC2616 is:
Providing a block of data, such as the result of submitting a form, to a data-handling process;
Hence verifying the header in order not do download the body beats the purpose of this.
As mentioned by #Radek above, using interceptors on GET request to modify and/or examine requests on the fly would do the work, but at that point we could also initiate a HEAD method request.
The solution to this problem would be to better align to the standard definitions defined in RFC2616 by making changes on the server-side to instead of returning block of raw data as a POST response, make it to return a resource that would be than called in a GET/HEAD request then. All just refactor the service call to use GET instead of POST.
Okhttp which is used by retrofit has Interceptors which let you modify or examine requests on the fly. Check out the github documentation

Categories

Resources