How do you retrieve all HTTP headers from a NSURLRequest
in Objective-C?
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.
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.
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]); } }
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With