NSURLConnection response's expectedContentLength -1

999 views Asked by At

*

Note: There are several links on this topic but it didn't work for me, So I have to post the new one here.

*

Basically I'm trying to show the UIProgressView to show the data being fetched from the web service. Now problem is that I'm getting the expectedContentLength for almost all the service that I call from my application and the response headers contains the Content-Length. But for one of the web service's response it doesn't return the expectedContentLength, instead always returns -1.

Following are the response headers that I get for two different web service response :

- Response header for which I get the content length.(Data from service is not huge)

{
    Connection = "Keep-Alive";
    "Content-Length" = 2689;
    "Content-Type" = "application/json";
    Date = "Tue, 23 Jun 2015 08:19:04 GMT";
    "Keep-Alive" = "timeout=5, max=98";
    Server = "Apache/2.4.10 (Win32) OpenSSL/1.0.1i PHP/5.5.15";
    "X-Powered-By" = "PHP/5.5.15";
}

- Response header for which I don't get the content length. (Response contains the huge data, no files to be downloaded just JSON data)

{
    Connection = "Keep-Alive";
    "Content-Type" = "application/json";
    Date = "Tue, 23 Jun 2015 08:12:34 GMT";
    "Keep-Alive" = "timeout=5, max=97";
    Server = "Apache/2.4.10 (Win32) OpenSSL/1.0.1i PHP/5.5.15";
    "Transfer-Encoding" = Identity;
    "X-Powered-By" = "PHP/5.5.15";
}

The Above service response contains huge data. When tested the response on Advanced rest client chrome's extension It gives following response header with "Transfer-Encoding" = chunked;.

Date: Tue, 23 Jun 2015 12:01:20 GMT 
Server: Apache/2.4.10 (Win32) OpenSSL/1.0.1i PHP/5.5.15 
X-Powered-By: PHP/5.5.15
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked 
Content-Type: application/json

I used following links, but none of them helped me: Link1 , Link2 , Link3

Please help me. Thanks!

Updated code: After setting the Content-Lenth header on server side I got the valid response with Content-Length header on Advanced rest client chrome's extension.

Date: Wed, 24 Jun 2015 05:25:48 GMT 
Server: Apache/2.4.10 (Win32) OpenSSL/1.0.1i PHP/5.5.15 
X-Powered-By: PHP/5.5.15
Content-Length: 1272347 
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: application/json

But on client side (i.e in iOS Application) I still didn't get the Content-Lenth header so that I can get the expectedContentLength value. I still get "Transfer-Encoding" = Identity; in the response header on my side. I have also set the Accept-Encoding header in the request as follows :

[req setValue:@"identity;q=0" forHTTPHeaderField:@"Accept-Encoding"];

Is there anything more to be done on either side(server/client).

1

There are 1 answers

0
David H On

I don't know how one gets the content length added at the server side - I had problems with this before, and in one case I had a similar situation as yours - the content length was visible by dumping all headers, but iOS didn't hand it to me in the delegate method. The standard way to get it is via:

- (void)connection:(NSURLConnection *)conn didReceiveResponse:(NSURLResponse *)response
{
  ...
  NSUInteger responseLength = response.expectedContentLength == NSURLResponseUnknownLength ? 1024 : (NSUInteger)response.expectedContentLength;

I actually entered a bug on this: rdar://15605995 "HTTP Get response is 200 but response.expectedContentLength = -1 even when a Content-Length is found in the headers"

2014-01-08 18:49:36.966 DB_Lookup[36824:3f07] YIKES:LEN=22162 {
"Cache-Control" = "must-revalidate";
Connection = "keep-alive";
"Content-Encoding" = gzip;
"Content-Length" = 22162;
"Content-Type" = "text/html; charset=UTF-8";
Date = "Wed, 08 Jan 2014 23:49:09 GMT";
Expires = 0;
"Front-End-Https" = on;
Pragma = "no-cache";
Server = "nginx/1.2.4";
"Strict-Transport-Security" = "max-age=2592000";
Vary = "Accept-Encoding";
"X-Content-Type-Options" = nosniff;
"X-Frame-Options" = SAMEORIGIN;
"X-Powered-By" = <Company>;
"X-<Company>-Server" = "<private>";
"X-XSS-Protection" = "1; mode=block";

}

for this code:

if(response.expectedContentLength == NSURLResponseUnknownLength) { 
    id len = httpResponse.allHeaderFields[@"Content-Length"];
    if(len) {
        responseLength = [len integerValue];
    }
    NSLog(@"YIKES:LEN=%@ %@", len, httpResponse.allHeaderFields);
}

This is going to be really hard for me to special case. I'm accessing an internal company data base, I have to use name/password first, then get a code to my phone (which I later enter) to get in. Is there other info I could grab to help you? How can it be that the content length is clearly there in the header, but you don't see it and return it to me?


Apple closed my bug, saying "Works as Expected". Really!?!?!?!?!?!?!

[I don't know if NSURLSession fixed it or not.]

EDIT: I should have added that in the past, other sites I connected to DID result in a properly set 'expectedContentLength'.