代码之家  ›  专栏  ›  技术社区  ›  fernyb

在WebKit中,如何获取资源的内容?

  •  7
  • fernyb  · 技术社区  · 16 年前

    我一直在编写一个mac应用程序来检查每个HTTP请求,所以我使用webview来加载请求。

    问题是,我似乎不知道如何获取每个资源项的内容。

    我正在尝试通过 WebResourceLoadDelegate 方法:

    - (void)webView:(WebView *)sender resource:(id)identifier didFinishLoadingFromDataSource:(WebDataSource *)dataSource
    

    这似乎不起作用。

    我也在看 [dataSource data] 但这只给了我请求的HTML,而不是资源项的数据。

    关于如何获取资源的内容有什么想法吗?

    2 回复  |  直到 14 年前
        1
  •  18
  •   J. Perkins    15 年前

    是的,这应该是可行的,而且似乎很久以前就有了。您可以通过实现一个定制的nsurlprotocol来解决这个问题。

    首先,您需要弄清楚您对拦截感兴趣的请求(或者所有请求,不管是什么)。我在WebResourceLoadDelegate中执行此操作。如果我关心这个请求,我会用自己的一个来替换它,把自己作为一个财产。稍后我将在nsurlprotocol中使用该属性。

    - (NSURLRequest*) webView:(WebView*)sender 
                     resource:(id)identifier 
              willSendRequest:(NSURLRequest*)request 
             redirectResponse:(NSURLResponse*)redirectResponse     
               fromDataSource:(WebDataSource*)dataSource
    {
        // Am I interested in this request?
        if (/* figure out if you want it or not */) {
            NSMutableURLRequest* newRequest = [[request mutableCopy] autorelease];
            [NSURLProtocol setProperty:self forKey:@"MyApp" inRequest:newRequest];
            return newRequest;
        }
        else {  
            // Not interested, let it go through normally
            return request;
        }
    }
    

    我的nsurlprotocol看起来像这样。

    @interface MyURLProtocol : NSURLProtocol {
        id _delegate;
        NSURLConnection* _connection;
        NSMutableData* _data;
    }
    @end
    

    在我的nsurlprotocol子类中,我可以使用附加属性来查看是否应该拦截响应。

    + (BOOL) canInitWithRequest:(NSURLRequest*)request
    {   
        id delegate = [NSURLProtocol propertyForKey:@"MyApp" inRequest:request];
        return (delegate != nil);
    }
    

    在initwithrequest中,我将委托移动到我的nsurlprotocol实例中,并从请求中移除属性。当我实际尝试加载这个请求时,这会阻止无限循环。

    - (id) initWithRequest:(NSURLRequest*)theRequest 
            cachedResponse:(NSCachedURLResponse*)cachedResponse 
                    client:(id<NSURLProtocolClient>)client
    {
        // Move the delegate from the request to this instance
        NSMutableURLRequest* req = (NSMutableURLRequest*)theRequest;    
        _delegate = [NSURLProtocol propertyForKey:@"MyApp" inRequest:req];  
        [NSURLProtocol removePropertyForKey:@"MyApp" inRequest:req];
    
        // Complete my setup
        self = [super initWithRequest:req cachedResponse:cachedResponse client:client];
        if (self) {
            _data = [[NSMutableData data] retain];
        }
        return self;
    }
    

    剩下的是股票URL加载的东西。

    - (void) startLoading
    {
        _connection = [[NSURLConnection connectionWithRequest:[self request] delegate:self] retain];
    }
    
    - (void) stopLoading
    {
        [_connection cancel];
    }
    
    - (void)connection:(NSURLConnection*)conn didReceiveResponse:(NSURLResponse*)response 
    {
        [[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:[[self request] cachePolicy]];
        [_data setLength:0];
    }
    
    - (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data
    {
        [[self client] URLProtocol:self didLoadData:data];
        [_data appendData:data];
    }
    
    - (void)connectionDidFinishLoading:(NSURLConnection*)conn
    {
        [[self client] URLProtocolDidFinishLoading:self];
    
        // Forward the response to your delegate however you like
        if (_delegate && [_delegate respondsToSelector:@selector(...)]) {
            [_delegate ... withRequest:[self request] withData:_data];
        }
    }
    
    - (NSURLRequest*)connection:(NSURLConnection*)connection willSendRequest:(NSURLRequest*)theRequest redirectResponse:(NSURLResponse*)redirectResponse
    {
        return theRequest;
    }
    
    - (void)connection:(NSURLConnection*)conn didFailWithError:(NSError*)error 
    {
        [[self client] URLProtocol:self didFailWithError:error];
    }
    
        2
  •  0
  •   amrit_neo    15 年前

    在那个委托方法中使用这个

      for(NSString *s in [dataSource subresources])
            NSLog(@"resource : %@",s);
    

    它将显示WebDataSource中正在下载的所有资源