How to mock AJAX call with NSURLProtocol?

前端 未结 2 567
独厮守ぢ
独厮守ぢ 2020-12-08 22:43

I have UIWebview that makes AJAX calls to external services. When offline i need to catch theses requests and return local json.

I implemented a NSURLProtocol and i

2条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2020-12-08 23:17

    The problem comes from webkit which blocks the response because of cross domain origin request. Since we mock the response we have to force the Access-Control-Allow-Origin.

    Then we also need to force the content-type of the response.

    Here is where the magic happens :

    NSDictionary *headers = @{@"Access-Control-Allow-Origin" : @"*", @"Access-Control-Allow-Headers" : @"Content-Type"};
    NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:request.URL statusCode:200 HTTPVersion:@"1.1" headerFields:headers];
    

    The final implementation of the protocol :

    #import "EpubProtocol.h"
    
    @implementation EpubProtocol
    
    #pragma mark - NSURLProtocol
    
    + (BOOL)canInitWithRequest:(NSURLRequest *)request {
        BOOL isAwsRequest = [self request:request contains:@"s3.amazonaws.com"];
    
        return isAwsRequest;
    }
    
    + (NSURLRequest*)canonicalRequestForRequest:(NSURLRequest*)theRequest
    {
        return theRequest;
    }
    
    - (void)startLoading {
        NSURLRequest *request = [self request];
    
        //Mock Amazon call
        if([EpubProtocol request:request contains:@"s3.amazonaws.com"]) {
            NSString *path = [[NSBundle bundleForClass:self.class] pathForResource:@"epub1" ofType:@"json"];
            NSData *data = [NSData dataWithContentsOfFile:path];
    
            [self mockRequest:request data:data];
        }
    }
    
    - (void)stopLoading
    {
        NSLog(@"Did stop loading");
    }
    
    
    #pragma mark - Request utils
    
    + (BOOL) request:(NSURLRequest*)request contains:(NSString*)domain {
        NSString *str = [[request URL] absoluteString];
        NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@", domain];
        return [pred evaluateWithObject:str];
    }
    
    
    #pragma mark - Mock responses
    
    
    -(void) mockRequest:(NSURLRequest*)request data:(NSData*)data {
        id client = [self client];
    
        NSDictionary *headers = @{@"Access-Control-Allow-Origin" : @"*", @"Access-Control-Allow-Headers" : @"Content-Type"};
        NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:request.URL statusCode:200 HTTPVersion:@"1.1" headerFields:headers];
    
        [client URLProtocol:self didReceiveResponse:response
         cacheStoragePolicy:NSURLCacheStorageNotAllowed];
        [client URLProtocol:self didLoadData:data];
        [client URLProtocolDidFinishLoading:self];
    }
    
    @end
    

    Nothing special in the JS :

    function loadJSONDoc()
    {
      var url = "https://s3.amazonaws.com/youboox_recette/epub.json";
    
      $.ajax({
          url: url,
          dataType: 'json',
           contentType: "application/json",
          success: function(jsonData){
            alert('success');
            document.getElementById("myDiv").innerHTML='

    '+$.param(jsonData)+'

    '; }, error: function (request, status, error) { alert("failure :" + request.status ); } }); }

提交回复
热议问题