HTTP Status Code 411 - Length Required

WantToKnow picture WantToKnow · Oct 7, 2013 · Viewed 59.7k times · Source

I try to get data from server. I use NSURLConnectionDelegate, NSURLConnectionDataDelegate. There is code (Objective - C).

-(void)sendRequest
{
NSURL* url = [[NSURL alloc] initWithString:@"http://SomeServer"];

NSMutableURLRequest* request = [[NSMutableURLRequest alloc] init];


NSString* reqBody = [NSString stringWithFormat:@"<tag>Content</tag>"];

NSData* reqData = [reqBody dataUsingEncoding:NSUTF8StringEncoding];

NSInputStream* stream = [NSInputStream inputStreamWithData:reqData];



[request setURL:url];
[request setHTTPBodyStream:stream];
[request setHTTPMethod:@"POST"];

self.wpData = [[NSMutableData alloc] init];
NSURLConnection* conection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

[conection start];

}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {

    [self.wpData setLength:0];    

}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)d {
NSString* str = [[NSString alloc] initWithData:d encoding:NSUTF8StringEncoding];

NSLog(@"RESPONSE DATA: %@",str);
[self.wpData appendData:d];
}

But I get "411 - Length Required" when I use

[request setHTTPBodyStream:stream];

and "HASH (someAddress)" when I use

[request setHTTPBody:reqData];

I tried

[request setHTTPBodyStream:stream];
NSString *postLength = [NSString stringWithFormat:@"%d", [reqData length]];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];

but again "HASH (someAdddress)"

What have I done wrong? Sorry for my English. Thanks :)

Answer

CouchDeveloper picture CouchDeveloper · Oct 7, 2013

What have I done wrong?

Nothing.

HTTP Status Code 411 (Length Required) is sent by the server as a response when it refuses to accept a message without a content-length header, for whatever reason.

A server simply may or may not accept a content without a Content-Length header.

When you set an NSInputStream object as request body via property HTTPBodyStream for the request, NSURLConnection cannot evaluate the length of the body itself anymore. (there is no property length for a stream). Hence, NSURLConnection uses a certain "transfer mode", namely "chunked transfer encoding". This transfer mode should succeed to transmit any body and it does not require a Content-Legth header (actually must not contain one). Alas, the server simply does not accept this type of transfer.

See also: Chunked transfer encoding (wiki).

To solve the issue on the client side:

  • Determine the length of the body yourself (if possible) and set a "Content-Length" header field for the request. If this input stream has been created from a file or from a NSData object, the length can be easily determined. But be sure to set the exact same length as the actual stream content in bytes.

  • Don't use a NSInputStream, but use a NSData object as body and set it via property HTTPBody. When you set the body as a NSData object, NSURLConnection can determine the content length itself, and it will automatically add a Content-Length header with the correct length, unless you set it yourself in the request.