web-dev-qa-db-fra.com

Comment obtenir des en-têtes HTTP

Comment récupérer tous les en-têtes HTTP à partir d'un NSURLRequest dans Objective-C?

28
Nagra

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]);
}
}
37
Harish Saran

É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.

4
user2067021

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]);
}
2
Nagra

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)")
    }
}
2
Joseph Francis