Comment récupérer tous les en-têtes HTTP à partir d'un NSURLRequest
dans Objective-C?
Cela relève de la classe facile, mais pas évidente, des problèmes de programmation iPhone. Digne d'un petit article:
Les en-têtes d'une connexion HTTP sont inclus dans la classe NSHTTPURLResponse
. Si vous avez une variable NSHTTPURLResponse
, vous pouvez facilement extraire les en-têtes en tant que NSDictionary
en envoyant le message allHeaderFields.
Pour les demandes synchrones - non recommandées, car elles bloquent - il est facile de remplir un 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]);
}
Avec une demande asynchrone, vous devez faire un peu plus de travail. Lorsque le rappel connection:didReceiveResponse:
est appelé, il est passé un NSURLResponse
comme deuxième paramètre. Vous pouvez le convertir en NSHTTPURLResponse
comme ceci:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
if ([response respondsToSelector:@selector(allHeaderFields)]) {
NSDictionary *dictionary = [httpResponse allHeaderFields];
NSLog([dictionary description]);
}
}
Étant donné que NSURLConnection
est obsolète depuis iOS 9, vous pouvez utiliser un NSURLSession
pour obtenir des informations de type MIME à partir d'un NSURL
ou NSURLRequest
.
Vous demandez à la session de récupérer l'URL, puis lors de la réception du premier NSURLResponse
(qui contient des informations de type MIME) dans un rappel délégué, vous annulez la session pour l'empêcher de télécharger l'intégralité de l'URL.
Voici quelques os nus Swift code qui le fait:
/// 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()
}
J'ai intégré des fonctionnalités similaires dans le projet RLEnquiry de github, ce qui facilite un peu les requêtes en ligne pour les types MIME et les en-têtes HTTP. RLEnquiry.Swift est le fichier d'intérêt qui pourrait être déposé dans votre propre projet.
YourViewController.h
@interface YourViewController : UIViewController <UIWebViewDelegate>
@property (weak, nonatomic) IBOutlet UIWebView *yourWebView;
@end
YourViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
//Set the UIWebView delegate to your view controller
self.yourWebView.delegate = self;
//Request your URL
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://website.com/your-page.php"]];
[self.legalWebView loadRequest:request];
}
//Implement the following method
- (void)webViewDidFinishLoad:(UIWebView *)webView{
NSLog(@"%@",[webView.request allHTTPHeaderFields]);
}
Version Swift utilisant Alamofire pour plus d'efficacité. C'est ce qui a fonctionné pour moi:
Alamofire.request(YOUR_URL).responseJSON {(data) in
if let val = data.response?.allHeaderFields as? [String: Any] {
print("\(val)")
}
}