skip to Main Content

How to programmatically monitor all incoming and outgoing requests that my app is making using URLSession?

The goal is to see data like URL, headers and body of those requests.

Perhaps something similar to this but using code within my app.

This should work in production and should be able to listen to the requests made by third party libraries, too.

2

Answers


  1. you can have a look at the source of Moya.
    enter image description here

    Login or Signup to reply.
  2. The goal is to see data like URL, headers and body of those requests

    If you want to track only requests (but not responses), then it’s as simple as adding an extra layer of NSURLProtocol to the session object. Since public API of the NSURLSession accepts tasks only, you can limit tracking to canInitWithTask: method:

    @interface TDWWatcherProtocol : NSURLProtocol
    
    @end
    
    @implementation TDWWatcherProtocol
    
    #pragma mark NSURLProtocol
    
    + (BOOL)canInitWithTask:(NSURLSessionTask *)task {
        [self p_printRequestData:task.originalRequest];
        return NO;
    }
    
    + (BOOL)canInitWithRequest:(NSURLRequest *)request {
        // no-op
        return NO;
    }
    
    #pragma mark Private
    
    + (void)p_printRequestData:(NSURLRequest *)request {
        NSLog(@"==========================");
        NSString *httpMethods = request.HTTPMethod ? request.HTTPMethod : @"GET";
        NSLog(@"Request: %@ %@", httpMethods,  request.URL);
        NSLog(@"Headers: %@", request.allHTTPHeaderFields);
        if (request.HTTPBody && request.HTTPBody.length) {
            NSLog(@"Body: %@", [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding]);
        }
    }
    
    @end
    

    You cannot omit implementation of canInitWithRequest: because in this case URL loading system will forward it to the base implementation of NSURLProtocol, which throws an error (the class is considered abstract). You provide your custom protocol to a NSURLSession instance by incorporating it to the configuration’s protocolClasses property:

    NSURLSessionConfiguration *configuration = NSURLSessionConfiguration.defaultSessionConfiguration;
    NSMutableArray<Class> *protocolClasses = [configuration.protocolClasses mutableCopy];
    [protocolClasses addObject:[TDWWatcherProtocol class]];
    configuration.protocolClasses = protocolClasses;
    NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
    

    If you additionally want to track all requests made by the sharedSession instance you must register your class globally with NSURLProtocol helper methods:

    [NSURLProtocol registerClass:[TDWWatcherProtocol class]];
    

    This also makes URL loading system to forward web views to requests to your protocol class.


    You may want to track canInitWithRequest: invocations as well, but be advised that in this case you will also get modified requests from internal implementation in addition to the original requests.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search