objective-cmacosproxynsurlsessionnsurlsessionconfiguration

NSUrlSession proxy request fails with error code 310 (kCFErrorHTTPSProxyConnectionFailure)


I'm trying to send a POST request to a specific URL through a proxy server. To test that the code I'm writing is working, I installed squidman on my machine and started a proxy server on port 33074. I tested the proxy server by changing the network settings to use the proxy when making HTTP/HTTPS requests and it's working ok.

Now I wrote the following code:

    NSDictionary* proxyConfig = @{
        (NSString*) kCFNetworkProxiesHTTPSEnable: @(1),
        (NSString*) kCFNetworkProxiesHTTPSProxy: @"127.0.0.1",
        (NSString*) kCFNetworkProxiesHTTPSPort: @"33074",
    };

    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
    [sessionConfig setTimeoutIntervalForRequest:60];
    [sessionConfig setConnectionProxyDictionary:proxyConfig];

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    [request setURL:[NSURL URLWithString:@"https://the-host-where-im-posting"]];
    [request setHTTPMethod:@"POST"];
    [request setValue:[[NSString alloc] initWithFormat:@"%lu",length] forHTTPHeaderField:@"Content-Length"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    [request setHTTPBody:data];

    NSURLSession *session = [self createHttpSession];
    NSURLSessionDataTask* dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
        if(httpResponse.statusCode == 200){
            //...
        } else {
            LOGERROR(@"Error: %@", error);
        }
    }

The problem is that the request is not successfull and the following error is logged:

Error: Error Domain=kCFErrorDomainCFNetwork Code=310 "(null)" UserInfo={_kCFStreamErrorCodeKey=-2096, _kCFStreamErrorDomainKey=4}

Additional Info:
1. It should be noted that the requests submits perfectly without setting the proxyConfig dictionary.
2. A similar error gets reported if I'm trying to submit the request using HTTP through the proxy (by correspondingly changing the keys in the proxyConfig dictionary) with a small diff in the Err Code and _kCFStreamErrorCodeKey: 306 instead of 310 and -2094 instead of -2096.
3. The process making the request runs as a daemon.

What exactly am I doing wrong ? What am I missing ?


Solution

  • I was setting the kCFNetworkProxiesHTTPSPort field from the proxyConfig dictionary to a value of type NSString. After carefully reading the documentation for it I observed the following:

    Key for the port number associated with the HTTPS proxy; value is a CFNumber which is the port number.

    The library was encountering an object that was not a CFNumber and was using the default port for HTTPS communication to connect to the proxy instead (443). That's bad error handling imho. It was essentially silently trying to make a request using a port that I was not aware of. Changing the proxyConfig dictionary to the following fixed the problem:

    NSDictionary* proxyConfig = @{
        (NSString*) kCFNetworkProxiesHTTPSEnable: @(1),
        (NSString*) kCFNetworkProxiesHTTPSProxy: @"127.0.0.1",
        (NSString*) kCFNetworkProxiesHTTPSPort: @(33074),
    };