Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get HTTP headers

How do you retrieve all HTTP headers from a NSURLRequest in Objective-C?

like image 456
Nagra Avatar asked Nov 05 '12 16:11

Nagra


People also ask

How do I set up HTTP headers?

Select the web site where you want to add the custom HTTP response header. In the web site pane, double-click HTTP Response Headers in the IIS section. In the actions pane, select Add. In the Name box, type the custom HTTP header name.

Can I create my own HTTP header?

Yes, you can. But, why would you want to? The HTTP protocol allows you to set your own custom headers. However, it would also mean that your server would need o understand your custom headers.


2 Answers

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]); } } 
like image 134
Harish Avatar answered Oct 13 '22 19:10

Harish


Given NSURLConnection is deprecated from iOS 9, you can use an NSURLSession to get MIME type information from an NSURL or NSURLRequest.

You ask the session to retrieve the URL, then upon receiving the first NSURLResponse (which contains MIME type information) in a delegate callback you cancel the session to prevent it downloading the whole URL.

Here is some bare bones Swift code that does it:

/// Use an NSURLSession to request MIME type and HTTP header details from URL. /// /// Results extracted in delegate callback function URLSession(session:task:didCompleteWithError:). /// func requestMIMETypeAndHeaderTypeDetails() {     let url = NSURL.init(string: "https://google.com/")     let urlRequest = NSURLRequest.init(URL: url!)      let session = NSURLSession.init(configuration: NSURLSessionConfiguration.ephemeralSessionConfiguration(), delegate: self, delegateQueue: NSOperationQueue.mainQueue())      let dataTask = session.dataTaskWithRequest(urlRequest)     dataTask.resume() }  //MARK: NSURLSessionDelegate methods  func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveResponse response: NSURLResponse, completionHandler: (NSURLSessionResponseDisposition) -> Void) {      // Cancel the rest of the download - we only want the initial response to give us MIME type and header info.     completionHandler(NSURLSessionResponseDisposition.Cancel) }  func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {            var mimeType: String? = nil     var headers: [NSObject : AnyObject]? = nil       // Ignore NSURLErrorCancelled errors - these are a result of us cancelling the session in      // the delegate method URLSession(session:dataTask:response:completionHandler:).     if (error == nil || error?.code == NSURLErrorCancelled) {          mimeType = task.response?.MIMEType          if let httpStatusCode = (task.response as? NSHTTPURLResponse)?.statusCode {             headers = (task.response as? NSHTTPURLResponse)?.allHeaderFields              if httpStatusCode >= 200 && httpStatusCode < 300 {                 // All good              } else {                 // You may want to invalidate the mimeType/headers here as an http error                 // occurred so the mimeType may actually be for a 404 page or                 // other resource, rather than the URL you originally requested!                 // mimeType = nil                 // headers = nil             }         }     }      NSLog("mimeType = \(mimeType)")     NSLog("headers = \(headers)")      session.invalidateAndCancel() } 

I've packaged similar functionality in the URLEnquiry project at github which makes it a bit easier to make in-line queries for MIME types and HTTP headers. URLEnquiry.swift is the file of interest that could be dropped into your own project.

like image 21
user2067021 Avatar answered Oct 13 '22 17:10

user2067021