All Products
Search
Document Center

HTTPDNS:Best practices for using HTTPDNS with AFNetworking on iOS

Last Updated:Jun 03, 2026

Integrate HTTPDNS with AFNetworking on iOS for HTTP and HTTPS scenarios, including SNI support.

1. Overview

AFNetworking is a widely used networking framework for iOS. This guide covers integrating HTTPDNS into an AFNetworking-based project.

HTTPDNS basics and iOS-specific technical challenges are covered in Use HTTPDNS in native iOS scenarios.

2. Integration for standard HTTP and non-SNI HTTPS scenarios

Applies to standard HTTP and HTTPS scenarios without Server Name Indication (SNI).

2.1 Create an AFHTTPSessionManager

+ (AFHTTPSessionManager *)sharedAfnManager {
    static AFHTTPSessionManager *manager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [AFHTTPSessionManager manager];
        
        // Configure the security policy.
        AFSecurityPolicy *securityPolicy = [AFSecurityPolicy defaultPolicy];
        securityPolicy.allowInvalidCertificates = NO;
        securityPolicy.validatesDomainName = YES;
        manager.securityPolicy = securityPolicy;
        
        // Configure the serializer.
        manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects: 
            @"application/json", @"text/json", @"text/javascript", @"text/plain", nil];
        manager.requestSerializer.timeoutInterval = 10.0f;
    });
    return manager;
}

2.2 Perform HTTPDNS domain name resolution

+ (NSString *)resolveAvailableIp:(NSString *)host {
    HttpDnsService *httpDnsService = [HttpDnsService sharedInstance];
    HttpdnsResult *result = [httpDnsService resolveHostSyncNonBlocking:host 
                                                             byIpType:HttpdnsQueryIPTypeAuto];
    if (!result) return nil;
    
    if (result.hasIpv4Address) {
        return result.firstIpv4Address;
    } else if (result.hasIpv6Address) {
        return [NSString stringWithFormat:@"[%@]", result.firstIpv6Address];
    }
    return nil;
}

2.3 Send a network request and handle certificate validation

+ (void)httpDnsQueryWithURL:(NSString *)originalUrl 
          completionHandler:(void(^)(NSString *message))completionHandler {
    
    NSURL *url = [NSURL URLWithString:originalUrl];
    NSString *resolvedIpAddress = [self resolveAvailableIp:url.host];

    NSString *requestUrl = originalUrl;
    if (resolvedIpAddress) {
        // Replace the domain name with the resolved IP address.
        requestUrl = [originalUrl stringByReplacingOccurrencesOfString:url.host 
                                                           withString:resolvedIpAddress];
        NSLog(@"HTTPDNS resolution successful. Domain name: %@, IP address: %@", url.host, resolvedIpAddress);
    } else {
        NSLog(@"HTTPDNS resolution failed. Using original URL: %@", url.host);
    }

    AFHTTPSessionManager *manager = [self sharedAfnManager];
    
    // Important: Set the Host header to ensure the server correctly identifies the domain name.
    [manager.requestSerializer setValue:url.host forHTTPHeaderField:@"host"];
    
    // Important: Configure HTTPS certificate validation. Use the original domain name for validation.
    [manager setSessionDidReceiveAuthenticationChallengeBlock:
     ^NSURLSessionAuthChallengeDisposition(NSURLSession *session, 
                                          NSURLAuthenticationChallenge *challenge, 
                                          NSURLCredential **credential) {
        
        if ([challenge.protectionSpace.authenticationMethod 
             isEqualToString:NSURLAuthenticationMethodServerTrust]) {
            
            if ([self evaluateServerTrust:challenge.protectionSpace.serverTrust 
                               forDomain:url.host]) {
                *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
                return NSURLSessionAuthChallengeUseCredential;
            }
        }
        return NSURLSessionAuthChallengePerformDefaultHandling;
    }];
    
    // Send the request.
    [manager GET:requestUrl parameters:nil headers:nil progress:nil 
         success:^(NSURLSessionDataTask *task, id responseObject) {
             NSData *data = [[NSData alloc] initWithData:responseObject];
             NSString *dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
             if (completionHandler) {
                 completionHandler([NSString stringWithFormat:@"Request successful: %@", dataStr]);
             }
         } 
         failure:^(NSURLSessionDataTask *task, NSError *error) {
             if (completionHandler) {
                 completionHandler([NSString stringWithFormat:@"Request failed: %@", error.localizedDescription]);
             }
         }];
}

+ (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(NSString *)domain {
    // Create a certificate validation policy.
    NSMutableArray *policies = [NSMutableArray array];
    if (domain) {
        [policies addObject:(__bridge_transfer id) SecPolicyCreateSSL(true, (__bridge CFStringRef) domain)];
    } else {
        [policies addObject:(__bridge_transfer id) SecPolicyCreateBasicX509()];
    }
    
    // Attach the validation policy to the server certificate.
    SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef) policies);
    
    // Evaluate the certificate trust.
    SecTrustResultType result;
    SecTrustEvaluate(serverTrust, &result);
    
    return (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed);
}

3. Integration for HTTPS with SNI scenarios

Applies to scenarios that require SNI, such as CDN or shared-IP deployments.

3.1 Configure an AFHTTPSessionManager that supports SNI

+ (AFHTTPSessionManager *)sharedAfnManagerWithSNI {
    static AFHTTPSessionManager *manager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
        
        // Important: Register a custom NSURLProtocol to handle SNI.
        NSMutableArray *protocolsArray = [NSMutableArray arrayWithArray:configuration.protocolClasses];
        [protocolsArray insertObject:[HttpDnsNSURLProtocolImpl class] atIndex:0];
        [configuration setProtocolClasses:protocolsArray];
        
        manager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:configuration];
        
        // Configure the security policy.
        AFSecurityPolicy *securityPolicy = [AFSecurityPolicy defaultPolicy];
        securityPolicy.allowInvalidCertificates = NO;
        securityPolicy.validatesDomainName = YES;
        manager.securityPolicy = securityPolicy;
        
        // Configure the serializer.
        manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects: 
            @"application/json", @"text/json", @"text/javascript", @"text/plain", nil];
        manager.requestSerializer.timeoutInterval = 10.0f;
    });
    return manager;
}

3.2 Perform HTTPDNS domain name resolution

+ (NSString *)resolveAvailableIp:(NSString *)host {
    HttpDnsService *httpDnsService = [HttpDnsService sharedInstance];
    HttpdnsResult *result = [httpDnsService resolveHostSyncNonBlocking:host 
                                                             byIpType:HttpdnsQueryIPTypeAuto];
    if (!result) return nil;
    
    if (result.hasIpv4Address) {
        return result.firstIpv4Address;
    } else if (result.hasIpv6Address) {
        return [NSString stringWithFormat:@"[%@]", result.firstIpv6Address];
    }
    return nil;
}

3.3 Send a network request in an SNI scenario

+ (void)httpDnsQueryWithSNIURL:(NSString *)originalUrl 
             completionHandler:(void(^)(NSString *message))completionHandler {
    
    NSURL *url = [NSURL URLWithString:originalUrl];
    NSString *resolvedIpAddress = [self resolveAvailableIp:url.host];

    NSString *requestUrl = originalUrl;
    if (resolvedIpAddress) {
        requestUrl = [originalUrl stringByReplacingOccurrencesOfString:url.host 
                                                           withString:resolvedIpAddress];
        NSLog(@"HTTPDNS resolution successful. Domain name: %@, IP address: %@", url.host, resolvedIpAddress);
    } else {
        NSLog(@"HTTPDNS resolution failed. Using original URL: %@", url.host);
    }

    AFHTTPSessionManager *manager = [self sharedAfnManagerWithSNI];
    
    // Set the Host header.
    [manager.requestSerializer setValue:url.host forHTTPHeaderField:@"host"];
    
    // Note: Because a custom NSURLProtocol is used, SNI and certificate validation are handled at the protocol layer.
    // Send the request directly.
    [manager GET:requestUrl parameters:nil headers:nil progress:nil 
         success:^(NSURLSessionDataTask *task, id responseObject) {
             NSData *data = [[NSData alloc] initWithData:responseObject];
             NSString *dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
             if (completionHandler) {
                 completionHandler([NSString stringWithFormat:@"Request successful: %@", dataStr]);
             }
         } 
         failure:^(NSURLSessionDataTask *task, NSError *error) {
             if (completionHandler) {
                 completionHandler([NSString stringWithFormat:@"Request failed: %@", error.localizedDescription]);
             }
         }];
}

Note: In SNI scenarios, the NSURLProtocol layer handles certificate validation and domain name resolution automatically. No separate callback is required.

A sample implementation is available in HttpDnsNSURLProtocolImpl.m from the httpdns_ios_demo project.

4. Examples

4.1 Basic HTTPS request

// Standard HTTP request (non-SNI scenario)
[AFNHttpsScenario httpDnsQueryWithURL:@"http://example.com/api/data" 
                    completionHandler:^(NSString *message) {
    NSLog(@"Request result: %@", message);
}];

4.2 Request in an SNI scenario

// Request in an SNI scenario
[AFNHttpsWithSNIScenario httpDnsQueryWithSNIURL:@"https://example.com/api/data" 
                               completionHandler:^(NSString *message) {
    NSLog(@"Request result: %@", message);
}];

5. Summary

Core integration steps:

  1. Initialize AFHTTPSessionManager: Configure basic network parameters.

  2. Perform HTTPDNS domain name resolution: Replace the domain name with a resolved IP address.

  3. Send the network request: Set the Host header and handle HTTPS certificate validation.

Key points

  • Host header: Ensures the server identifies the correct domain.

  • Certificate validation: Use the original domain name, not the IP address, for certificate validation.

  • SNI handling: Use NSURLProtocol for automatic handling in complex scenarios.

  • Fallback policy: Fall back to the system DNS if HTTPDNS resolution fails.

Complete sample code: HTTPDNS iOS Demo.