I have an NSURLConnection and in didReceiveResponse I'm checking [response expectedContentLength] and getting really large values like 18446744073709551615. There's no way this is correct. The download is about 3k bytes, and when I expect the same request in fiddler, I see a (correct) content length header in the response of about 3k bytes.
To avoid this problem, set header field "Accept-Encoding" to #"gzip;q=0". that tells the server that you do not accept gzip, and will if possible send uncompressed.
The answer, related to the comments, is that it's because the result is gzip encoded. Oddly, the value for the expectedContentLength seems to be junk, and cannot be trusted. If the result is gzip encoded, then NSURLConnection cannot properly determine the size of the unencoded result.
Related
I'm using NSURLSession's dataTaskWithRequest to perform an HTTP GET with Accept-Encoding: gzip. NSURLSession will automatically un-gzip the gzipped stream. How can I get the original response's content length (i.e. the length before un-gzipping)? Note that:
NSURLResponse's expectedContentLength is the length after un-gzipping it.
NSURLSessionTask's countOfBytesReceived property is the same value as expectedContentLength
While the header Content-Length can be obtained from NSHTTPURLResponse, it's not available with HTTP 1.1's chunked transfer encoding.
I have a HEAD request to certain image with If-modified-since HTTP header, in order to check if image is actually modified. If modified, then i just send GET request for this image.
It used to work fine for iOS 7, And it works now for iOS 7. But for iOS 8 i got
Error Domain=AFNetworkingErrorDomain Code=-1016 "Request failed: unacceptable content-type: image/png"
So the same code works for ios7 and for ios8- don't. Any ideas?
First, you don't need to make a HEAD request. An appropriate NSURLRequestCachePolicy can accomplish the same thing.
Second, the error is caused by an unacceptable content type being sent by the response for the response serializer. For image/png, use AFImageResponseSerializer, or set the appropriate acceptableContentTypes property for the response serializer of your choice.
Thanks Matt for showing the way. I removed HEAD request. Now i use AFHTTPRequestOperation with AFImageResponseSerializer. Also i set 'If-Modified-Since' header in NSMutableURLRequest with setValue:forHTTPHeaderField method. This date is stored in userdefaults, where key is URL, and value is the date where this URL was modified.
I'm sure there should be much better way for this, like using NSURLCache, but i couldn't do it.
I am working on a app in which I have to find size of web service response and response type is id. Please suggest me a suitable answer to fetch size of id object.
Here in this code I have to find the size of value.
-(void)getOneTimeWebpayCardsHandler:(id) value
{
YPGetOneTimeWebpayCardsResponse* result = (YPGetOneTimeWebpayCardsResponse*)value;
}
If it is just a simple object without any extra internal allocations, this should work:
#import <malloc/malloc.h>
NSLog(#"response size: %zd", malloc_size(response));
If I understand your question correctly:
You might check the HTTP headers of the response:
Content-Type: The value of this header specifies the MIME type, e.g. application/json and possibly additional parameters, like "charset", e.g. application/json; charset=utf-8 of the response data.
Content-Length: The value of this header specifies the length in bytes of the response data.
See also NSHTTPURLResponse and NSURLResponse in the original documentation.
I have written a web-service using Erlang and Mochiweb. The web service returns a lot of results and takes some time to finish the computation.
I'd like to return results as soon as the program finds it, instead of returning them when it found them all.
edit:
i found that i can use a chunked request to stream result, but seems that i can't find a way to close the connection. so any idea on how to close a mochiweb request?
To stream data of yet unknown size with HTTP 1.1 you can use HTPP chunked transfer encoding. In this encoding each chunk of data prepended by its size in hexadecimal. Last chunk is a zero-length chunk, with the chunk size coded as 0, but without any data.
If client doesn't support HTTP 1.1 server can send data as binary chunks and close connection at the end of the stream.
In MochiWeb it's all works as following:
HTTP response should be started with Response = Request:respond({Code, ResponseHeaders, chunked}) function. (By the way, look at the code comments);
Then chunks can be send to client with Response:write_chunk(Data) function. To indicate client the end of the stream chunk of zero length should be sent: Response:write_chunk(<<>>).
When handling of current request is over MochiWeb decides should connection be closed or can be reused by HTTP persistent connection.
How i can determine the size in bytes of a remote file hosted in the web, before download it, using Delphi?
Thanks In advance.
You could use Indy.
First include IdHTTP.
You can retrieve the size this way:
procedure TFormMain.Button1Click(Sender: TObject);
var
Http: TIdHTTP;
begin
Http := TIdHTTP.Create(nil);
try
Http.Head('http://live.sysinternals.com/ADExplorer.exe');
ShowMessage(IntToStr(Http.Response.ContentLength));
finally
Http.Free;
end;
end;
Short answer: use the HTTP HEAD command, available in the TIdHttp component of Indy Delphi.
Details:
HTTP protocol defines a HEAD method.
9.4 HEAD
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.
HEAD Asks for the response identical to the one that would correspond to a GET request, but without the response body, retrieving the complete response headers, without the entire content.
The HTTP response headers retrieved are documented in List of HTTP headers on Wikipedia.
http://en.wikipedia.org/wiki/List_of_HTTP_headers
HTTP Headers form the core of an HTTP request,
and are very important in an HTTP response.
They define various characteristics of the data
that is requested or the data that has been provided.
The headers are separated from the request or
response body by a blank line. HTTP headers
can be near-arbitrary strings, but only some
are commonly understood.
One of the headers that is always present for a valid URL to retrieve a content is
the Content-Length header.
14.13 Content-Length
The Content-Length entity-header field indicates the
size of the entity-body, in decimal number of OCTETs,
sent to the recipient or, in the case of the HEAD method,
the size of the entity-body that would have been sent
had the request been a GET.
Content-Length = "Content-Length" ":" 1*DIGIT
An example is
Content-Length: 3495
Applications SHOULD use this field to indicate the
transfer-length of the message-body, unless this is
prohibited by the rules in section 4.4.
Any Content-Length greater than or equal to zero is a
valid value. Section 4.4 describes how to determine
the length of a message-body if a Content-Length is not given.
Note that the meaning of this field is significantly
different from the corresponding definition in MIME,
where it is an optional field used within the
"message/external-body" content-type. In HTTP,
it SHOULD be sent whenever the message's length
can be determined prior to being transferred,
unless this is prohibited by the rules in section 4.4.
From Delphi, drop a TIdHttp component to your form. And paste the following code in one of your delphi event process methods.
var
url: string; // must contain a fully qualified url
contentLength: integer;
begin
....
contentLength:=0;
try
Idhttp1.Head(url);
contentLength:=idhttp1.response.ContentLength;
except end;
....
Be aware that not ALL servers will return a valid content size for a head request. If the content length = 0, then you will ONLY know if you issue a GET request. For example the HEAD request against the Google logo returns a 0 content-length, however a GET returns the proper length, but also retrieves the image. Some servers will return content-length as the length of the packet following the header.
You can use Synapse to get at this information also. Note that the data is transfered, but the buffer is thrown away. This is a much more reliable method, but at the cost of additional bandwidth.
var
HTTP : tHTTPSend;
begin
HTTP := THTTPSend.Create;
try
HTTP.HTTPMethod('GET',url);
DownloadSize := HTTP.DownloadSize;
finally
HTTP.Free;
end;
end;