Send custom headers with UIWebView loadRequest

筅森魡賤 提交于 2019-12-29 14:28:55

问题


I want to be able to send some extra headers with my UIWebView loadRequest method.

I have tried:

NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.reliply.org/tools/requestheaders.php"]];
[req addValue:@"hello" forHTTPHeaderField:@"aHeader"];

[self.theWebView loadRequest:req];

I have also tried subclassing the UIWebView and intercepting the - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType method.

In that method I had a block of code which looked like this:

NSMutableURLRequest *newRequest = [request mutableCopy];
for(NSString *key in [customHeaders allKeys]) {
    [newRequest setValue:[customHeaders valueForKey:key] forHTTPHeaderField:key];
}
[self loadRequest:newRequest];

But for some unknown reason it was causing the web view to not load anything (blank frame) and the error message NSURLErrorCancelled (-999) comes up (all known fixes don't fix it for me).

So I am at a loss as to what to do. How can I send a custom header along with a UIWebView request?

Many thanks!


回答1:


I found that this was the way to add headers to my UIWebView request - override this delegate method:

- (BOOL) webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType) navigationType

With this code:

BOOL headerIsPresent = [[request allHTTPHeaderFields] objectForKey:@"my custom header"]!=nil;

if(headerIsPresent) return YES;

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    dispatch_async(dispatch_get_main_queue(), ^{
        NSURL *url = [request URL];
        NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];

        // set the new headers
        for(NSString *key in [self.customHeaders allKeys]){
            [request addValue:[self.customHeaders objectForKey:key] forHTTPHeaderField:key];
        }

        // reload the request
        [self loadRequest:request];
    });
});
return NO;



回答2:


The answer by Thomas will not work for (most of the) webpages with multiple iFrames. The solution will load an iFrame request over the full UIWebView. E.g. in case it calls loadRequest for a Google advt. (which is in some small iFrame) the advt. is loaded all over the UIWebView & nothing else.




回答3:


I find another way, Can use NSURLProtocol .

-(BOOL)webView:(IMYVKWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    NSMutableDictionary* mapObject = [NSMutableDictionary dictionary];
    mapObject[@"headers"] = request.allHTTPHeaderFields;
    mapObject[@"navigationType"] = @(navigationType);
    [webViewRequestMap setObject:mapObject forKey:request.URL.absoluteString];
    return YES;
}

webViewRequestMap is Static NSMutableDictionary*

in Your Custom NSURLProtocol code:

    @interface IMYCustomURLProtocol : NSURLProtocol
@end
@implementation IMYCustomURLProtocol 
+(void)load
{
     [NSURLProtocol registerClass:self];
}
+ (BOOL)canInitWithRequest:(NSURLRequest *)request
{
    NSString* urlString = request.URL.absoluteString;
    NSDictionary* dictionary = webViewReuqestMap[urlString];
    if (dictionary)
    {
        [webViewRequestMap removeObjectForKey:urlString];
        if ([request isKindOfClass:[NSMutableURLRequest class]]) {
           [(id)request setValue:@"HAHA" forHTTPHeaderField:@"MeiYou Co.,Ltd"];
        }
    }
    return NO;
}
@end



回答4:


Here is a complete implementation using NSURLProticol. You can put this code anywhere you like (e.i. its own or add to existing source file) and it should work. The two key methods to customize are canInitWithRequest: and canonicalRequestForRequest:.

static NSString * const NSURLProtocolHandledKey = @"NSURLProtocolHandledKey";

@interface WTCURLProtocol : NSURLProtocol<NSURLSessionDelegate>
@property (atomic,strong,readwrite) NSURLSessionDataTask *task;
@property (nonatomic,strong) NSURLSession *session;
@end

@implementation WTCURLProtocol
+(void)load
{
  [NSURLProtocol registerClass:self];
}

+ (BOOL)canInitWithRequest:(NSURLRequest *)request
{
  // customize here by returning true for URLs that you want to handle
  return [request.URL.absoluteString hasPrefix:WEB_BASE_URL];
}

+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request
{
  NSMutableURLRequest *newRequest = request.mutableCopy;
  [NSURLProtocol setProperty:@YES forKey:NSURLProtocolHandledKey inRequest:newRequest];

  // customize here by setting your custom headers
  [newRequest setValue:@"ABCDEFGHIJKLMNOPQRSTUVWXYZ" forHTTPHeaderField:@"API-TOKEN"];

  return newRequest;
}

- (void)startLoading
{
  NSURLSessionConfiguration *configure = [NSURLSessionConfiguration defaultSessionConfiguration];
  NSOperationQueue *queue = [[NSOperationQueue alloc] init];

  self.session  = [NSURLSession sessionWithConfiguration:configure delegate:self delegateQueue:queue];
  self.task = [self.session dataTaskWithRequest:self.request];
  [self.task resume];
}

- (void)stopLoading
{
  [self.session invalidateAndCancel];
  self.session = nil;
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
  if (error != nil) {
    [self.client URLProtocol:self didFailWithError:error];
  }else
  {
    [self.client URLProtocolDidFinishLoading:self];
  }
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
 completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
{
  [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];

  completionHandler(NSURLSessionResponseAllow);
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
  [self.client URLProtocol:self didLoadData:data];
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask willCacheResponse:(NSCachedURLResponse *)proposedResponse completionHandler:(void (^)(NSCachedURLResponse * _Nullable))completionHandler
{
  completionHandler(proposedResponse);
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)newRequest completionHandler:(void (^)(NSURLRequest *))completionHandler
{
  NSMutableURLRequest *redirectRequest = [newRequest mutableCopy];
  [[self class] removePropertyForKey:NSURLProtocolHandledKey inRequest:redirectRequest];
  [[self client] URLProtocol:self wasRedirectedToRequest:redirectRequest redirectResponse:response];

  [self.task cancel];
  [[self client] URLProtocol:self didFailWithError:[NSError errorWithDomain:NSCocoaErrorDomain code:NSUserCancelledError userInfo:nil]];
}

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler
{
  if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
    NSURLCredential *card = [[NSURLCredential alloc] initWithTrust:challenge.protectionSpace.serverTrust];
    completionHandler(NSURLSessionAuthChallengeUseCredential,card);
  }
}

@end



来源:https://stackoverflow.com/questions/12844598/send-custom-headers-with-uiwebview-loadrequest

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!