Preventing Nsurlsession Default Http Headers

Preventing NSURLSession default HTTP headers

I doubt what you're asking for is possible. NSURLSession (and NSURLConnection) automatically provide a number of headers, and that's one of them.

There's also no valid reason to remove them. All three of those headers have been part of the spec since the original HTTP/0.9 spec (https://www.w3.org/Protocols/HTTP/HTRQ_Headers.html). There's absolutely no excuse for any server not either handling those correctly or ignoring them outright.

With that said, if you provide the wrong value for those fields (and the default may be wrong), the server may refuse to give you results. To solve that problem, first figure out what type of data the server is actually going to provide, and specify that value in the Accept header instead of the default.

For example, you might set Accept to "application/json" or one of the other variants (What is the correct JSON content type?) if you're expecting JSON data.

That said, if you really must avoid having those headers sent, you can always open a socket, construct the request manually, and send it. Assuming the server doesn't require chunked encoding, it is pretty easy to do. (Chunked encoding, however, is a horror of Herculean proportions, so if your server sends that back, you'll pretty much have to resort to adding libcurl into your project and using that to make requests instead.)

How to get NSURLSession to return Content-Length(http header) from server. Objective-c, ios

By default the request you are sending has header - Accept-Encoding : gzip, deflate and the server apache in this case don't add the header content-length(by default for larger files). So if you replace that header with value: identity. It will provide the correct size of the file.

Here is the code:

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:myURL];
request.HTTPMethod = @"HEAD";
[request addValue:@"identity" forHTTPHeaderField:@"Accept-Encoding"];

Just have to add the field and you will have the right header in the response like curl -I does.

ios objective c : How to get NSURLSession to return Content-Length(http header) from server

It's because you are returning value of function outside the completion handler, so your function is returns value before it's got response from server. Now you can't return value from completion handler. So you need to create method which have custom completion handler as parameter something like,

 - (void) getContentLength : (void(^)(long long returnValue))completionHandler
{

NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config];

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]];
request.HTTPMethod = @"HEAD";
[request addValue:@"identity" forHTTPHeaderField:@"Accept-Encoding"];

NSURLSessionDownloadTask *uploadTask
= [session downloadTaskWithRequest:request
completionHandler:^(NSURL *url,NSURLResponse *response,NSError *error) {

NSLog(@"handler size: %lld", response.expectedContentLength);
totalContentFileLength = [[NSNumber alloc] initWithFloat:response.expectedContentLength].longLongValue;

completionHandler(totalContentFileLength);

}];
NSLog(@"content length=%lld", totalContentFileLength);
[uploadTask resume];

}

and you can call this method like,

   [self getContentLength:^(long long returnValue) {

NSLog(@"your content length : %lld",returnValue);

}];

NSURLCache, together with NSURLSession, does not respect: Cache-Control: max-age:86000, private, must-revalidate

Problem

The problem is the usage of the Cache-Control response directive must-revalidate.

By omitting must-revalidate you already have the perfect definition of your use case as far as I've understood it:

Cache-Control: max-age=86400, private

This controls how long the requested resource is considered fresh. After this time has elapsed, the answer should no longer come directly from the cache instead the server should be contacted for validation for subsequent requests. In your case since the server supplies an ETag, iOS sends a request with an If-None-Match header to the server.

Verification

To check this, I used your testRestfulAPI method without NSURLCache settings and configured a maximum age of 60 seconds on the server side, so I don't have to wait a day to check the result.

After that, I triggered testRestfulAPI once per second. I always got the desired result from the cache. And Charles showed that the data must come from the cache because the server was not contacted for 60 seconds.

Verification using Charles

RFC 7234

Here is a quote from RFC 7234 (which obsoletes RFC 2616), under 5.2.2.1. it states:

The must-revalidate directive is necessary to support reliable
operation for certain protocol features. In all circumstances a cache
MUST obey the must-revalidate directive; in particular, if a cache
cannot reach the origin server for any reason, it MUST generate a 504
(Gateway Timeout) response.

The must-revalidate directive ought to be used by servers if and only
if failure to validate a request on the representation could result in
incorrect operation, such as a silently unexecuted financial
transaction.

After reading that and if you put yourself in the view of a cache developer, you can well imagine that when a must-revalidate is seen, the original server is always contacted and any additional directives such as max-age are simply ignored. It seems to me that caches often show exactly this behavior in practice.

There is another section in chapter 5.2.2.1. which I will not conceal and which reads as follows:

The "must-revalidate" response directive indicates that once it has become stale, a cache MUST NOT use the response to satisfy subsequent requests without successful validation on the origin server.

This is often interpreted that by specifying max-age together with must-revalidate you can determine when a content is stale (after max-age seconds) and then it must validate at the origin server before it can serve the content.

In practice, however, for the reasons given above, it seems that must-revalidate always leads to a validation of each request on the origin server.

How can I prevent the “User Agent” header of a WKWebView from changing?

  1. For iOS 9, use the customUserAgent property on the web view.

  2. For iOS 8 and earlier, do this instead:

    NSUserDefaults.standardUserDefaults().registerDefaults(["UserAgent" : "BlahBlahBlah"])

How to get HTTP headers

This falls under the easy, but not obvious class of iPhone programming problems. Worthy of a quick post:

The headers for an HTTP connection are included in the NSHTTPURLResponse class. If you have an NSHTTPURLResponse variable you can easily get the headers out as a NSDictionary by sending the allHeaderFields message.

For synchronous requests — not recommended, because they block — it’s easy to populate an NSHTTPURLResponse:

NSURL *url = [NSURL URLWithString:@"http://www.mobileorchard.com"];
NSURLRequest *request = [NSURLRequest requestWithURL: url];
NSHTTPURLResponse *response;
[NSURLConnection sendSynchronousRequest: request returningResponse: &response error: nil];
if ([response respondsToSelector:@selector(allHeaderFields)]) {
NSDictionary *dictionary = [response allHeaderFields];
NSLog([dictionary description]);
}

With an asynchronous request you have to do a little more work. When the callback connection:didReceiveResponse: is called, it is passed an NSURLResponse as the second parameter. You can cast it to an NSHTTPURLResponse like so:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
if ([response respondsToSelector:@selector(allHeaderFields)]) {
NSDictionary *dictionary = [httpResponse allHeaderFields];
NSLog([dictionary description]);
}
}


Related Topics



Leave a reply



Submit