Search code examples
objective-ccocoa-touchafnetworkingafhttprequestoperation

AFHTTPRequestOperationManager with HTTP and HTTPS base url


I was wondering what is the best option (architecture) for situation where I have same API on HTTP and HTTPS. Is there a way to support HTTP and HTTPS requests in same AFHTTPRequestOperationManager or should I have two subclasses, one for HTTP requests and second for HTTPS requests?

I feel like changing baseURL dynamically is not the best solution


Solution

  • You can hold two AFHTTPClient* objects. One for http and other for secure https. Here is example based on my Requester class.

    -- Requester.h ---

    #import "Foundation/Foundation.h"
    #import "AFNetworking.h"
    
    typedef enum
    {
        MultipartTypeImageJPEG,
        MultipartTypeImagePNG,
        MultipartTypeVideoQuicktime
    } MultipartType;
    
    typedef enum
    {
        HTTPMethodGET,
        HTTPMethodPOST,
        HTTPMethodPUT,
        HTTPMethodDELETE
    } HTTPMethod;
    
    typedef void (^RequestCallback)(NSError *error, NSInteger statusCode, id json);
    
    @interface Requester : NSObject
    
    /**
     * Singleton
     */
    + (instancetype)sharedInstance;
    
    - (void)requestToPath:(NSString *)path
                   method:(HTTPMethod)method
                   params:(NSDictionary *)params
                 complete:(RequestCallback)callback;
    
    - (void)requestMultipartToPath:(NSString *)path
                            method:(HTTPMethod)method
                            params:(NSDictionary *)params
                          fileData:(NSData *)fileData
                          fileName:(NSString *)fileName
                              type:(MultipartType)multyPartType
                          complete:(RequestCallback)callback;
    
    
    - (void)secureRequestToPath:(NSString *)path
                  method:(HTTPMethod)method
                  params:(NSDictionary *)params
                complete:(RequestCallback)callback;
    

    -- Requester.m ---

    #import "Requester.h"
    
    @interface Requester()
    
    @property (nonatomic, strong) AFHTTPClient *httpClient;
    @property (nonatomic, strong) AFHTTPClient *httpClientSecure;
    
    @end
    
    @implementation Requester
    
    + (instancetype)sharedInstance
    {
        static id instance = nil;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            instance = [[self alloc] init];
        });
    
        return instance;
    }
    
    + (void)initialize
    {
        [super initialize];
    
    
        NSURL *baseURL = [NSURL URLWithString:YOUR_BASE_ADDRESS_HTTP];
        NSURL *secureBaseURL = [NSURL URLWithString:YOUR_BASE_ADDRESS_HTTPS];
    
        [Requester sharedInstance].httpClient = [AFHTTPClient clientWithBaseURL:baseURL];
        [Requester sharedInstance].httpClient.parameterEncoding = AFJSONParameterEncoding;
    
        [Requester sharedInstance].httpClientSecure = [AFHTTPClient clientWithBaseURL:secureBaseURL];
        [Requester sharedInstance].httpClientSecure.parameterEncoding = AFJSONParameterEncoding;
    
    }
    
    - (id)init
    {
        self = [super init];
        if (self) {
            //...
        }
        return self;
    }
    
    
    #pragma mak - Request Types
    - (NSMutableURLRequest*)requestWithPathPOST:(NSString*)path withParams:(NSDictionary*)params
    {
        params = [self addRequiredBodyProperties:params];
        NSMutableURLRequest *request = [self.httpClient requestWithMethod:@"POST" path:path parameters:params];
        request.cachePolicy = NSURLRequestReloadIgnoringCacheData;
        request = [self addRequiredHeaderProperties:request];
    
        return request;
    }
    
    - (NSMutableURLRequest*)requestWithPathGET:(NSString*)path withParams:(NSDictionary*)params
    {
        params = [self addRequiredBodyProperties:params];
        NSMutableURLRequest *request = [self.httpClient requestWithMethod:@"GET" path:path parameters:params];
        request.cachePolicy = NSURLRequestReloadIgnoringCacheData;
        request = [self addRequiredHeaderProperties:request];
    
        return request;
    }
    
    - (NSMutableURLRequest*)requestWithPathPUT:(NSString*)path withParams:(NSDictionary*)params
    {
        params = [self addRequiredBodyProperties:params];
        NSMutableURLRequest *request = [self.httpClient requestWithMethod:@"PUT" path:path parameters:params];
        request.cachePolicy = NSURLRequestReloadIgnoringCacheData;
        request = [self addRequiredHeaderProperties:request];
    
        return request;
    }
    
    - (NSMutableURLRequest*)requestWithPathDEL:(NSString*)path withParams:(NSDictionary*)params
    {
        params = [self addRequiredBodyProperties:params];
        NSMutableURLRequest *request = [self.httpClient requestWithMethod:@"DELETE" path:path parameters:params];
        request.cachePolicy = NSURLRequestReloadIgnoringCacheData;
        request = [self addRequiredHeaderProperties:request];
    
        return request;
    }
    
    - (NSMutableURLRequest *)addRequiredHeaderProperties:(NSMutableURLRequest *)request
    {
        NSMutableDictionary *dic = [[request allHTTPHeaderFields] mutableCopy];
    
        // Here adding some header parameters that required on every request
        NSString *deviceId = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
        [dic setObject:deviceId forKey:@"Device-Id"];          
        [dic setObject:@"ios" forKey:@"os"];
    
        [request setAllHTTPHeaderFields:dic];
    
        return request;
    }
    
    - (NSMutableDictionary *)addRequiredBodyProperties:(NSDictionary *)params
    {
        NSMutableDictionary *result = [params mutableCopy];
        if (!result) {
            result = [NSMutableDictionary new];
        }
    
        // Here adding some parameters that required on every request
        if (API_KEY) {
            [result setObject:API_KEY forKey:@"api_key"];
        }
    
    
        return result;
    }
    
    - (NSMutableURLRequest*)requestMultipartWithPath:(NSString*)path method:(NSString *)method withParams:(NSDictionary*)params fileData:(NSData *)fileData fileName:(NSString *)fileName type:(MultipartType)multyPartType
    {
        params = [self addRequiredBodyProperties:params];
    
        NSString *mimeType = @"";
        NSString *name = @"picture";
        switch (multyPartType) {
            case MultipartTypeImageJPEG:
    
                mimeType = @"image/jpeg";
                if (fileName)
                {
                    if ([fileName rangeOfString:@".jpg"].location == NSNotFound && [fileName rangeOfString:@".jpeg"].location == NSNotFound)
                    {
                        fileName = [fileName stringByAppendingString:@".jpg"];
                    }
                }
                break;
            case MultipartTypeImagePNG:
    
                mimeType = @"image/png";
                if (fileName)
                {
                    if ([fileName rangeOfString:@".png"].location == NSNotFound)
                    {
                        fileName = [fileName stringByAppendingString:@".png"];
                    }
                }
    
                break;
            case MultipartTypeVideoQuicktime:
                mimeType = @"video/quicktime";
                name = @"video";
                break;
        }
    
        if (!method || [method isEqualToString:@""])
        {
            method = @"POST";
        }
    
        NSMutableURLRequest *request = [self.httpClient multipartFormRequestWithMethod:method path:path parameters:params constructingBodyWithBlock:^(id formData) {
            [formData appendPartWithFileData:fileData name:name fileName:fileName mimeType:mimeType];
        }];
    
        request = [self addRequiredHeaderProperties:request];
    
        return request;
    }
    
    #pragma mark - Global Requests
    
    - (void)JSONRequestOperationWithRequest:(NSMutableURLRequest *)request callback:(RequestCallback)callback
    {
        [[AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
            if (callback) {
                callback(nil,response.statusCode,O);
            }
    
        } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
            NSLog(@"%@",error.description);
            NSLog(@"%@",JSON);
    
            if (callback) {
                callback(error,response.statusCode,JSON);
            }
        }] start];
    }
    
    #pragma mark -
    
    - (void)requestToPath:(NSString *)path method:(HTTPMethod)method params:(NSDictionary *)params complete:(RequestCallback)callback
    {
        NSMutableURLRequest *request = nil;
        switch (method) {
            case HTTPMethodGET:
                request = [self requestWithPathGET:path withParams:params];
                break;
            case HTTPMethodPUT:
                request = [self requestWithPathPUT:path withParams:params];
                break;
            case HTTPMethodPOST:
                request = [self requestWithPathPOST:path withParams:params];
                break;
            case HTTPMethodDELETE:
                request = [self requestWithPathDEL:path withParams:params];
                break;
        }
    
        [self JSONRequestOperationWithRequest:request callback:callback];
    }
    
    - (void)requestMultipartToPath:(NSString *)path method:(HTTPMethod)method params:(NSDictionary *)params fileData:(NSData *)fileData fileName:(NSString *)fileName type:(MultipartType)multyPartType complete:(RequestCallback)callback
    {
        NSString *methodString = @"";
        switch (method) {
            case HTTPMethodGET:
                methodString = @"GET";
                break;
            case HTTPMethodPUT:
                methodString = @"PUT";
                break;
            case HTTPMethodPOST:
                methodString = @"POST";
                break;
            case HTTPMethodDELETE:
                methodString = @"DELETE";
                break;
        }
    
        NSMutableURLRequest *request = [self requestMultipartWithPath:path method:methodString withParams:params fileData:fileData fileName:fileName type:multyPartType];
        [self JSONRequestOperationWithRequest:request callback:callback];
    }
    
    - (void)secureRequestToPath:(NSString *)path method:(HTTPMethod)method params:(NSDictionary *)params complete:(RequestCallback)callback
    {    
        NSMutableURLRequest *request = nil;
        switch (method) {
            case HTTPMethodGET:
                request = [self.httpClientSecure requestWithMethod:@"GET" path:path parameters:params];
                break;
            case HTTPMethodPUT:
                request = [self.httpClientSecure requestWithMethod:@"PUT" path:path parameters:params];
                break;
            case HTTPMethodPOST:
                request = [self.httpClientSecure requestWithMethod:@"POST" path:path parameters:params];
                break;
            case HTTPMethodDELETE:
                request = [self.httpClientSecure requestWithMethod:@"DELETE" path:path parameters:params];
                break;
        }
    
        AFJSONRequestOperation *oper = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
                                                         success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {                                                         
    
                                                             if (callback) {
                                                                 callback(nil,response.statusCode,JSON);
                                                             }
          } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
              NSLog(@"%@",error.description);
              NSLog(@"%@",JSON);
    
              if (callback) {
                  callback(error,response.statusCode,JSON);
              }
          }];
    
        [oper start];
    }
    @end
    

    Usage:

    For http:

     [[Requester sharedInstance] requestToPath:@"user/authenticate"
                                                           method:HTTPMethodPOST
                                                           params:@{@"username":username,@"password":password}
                                                         complete:^(NSError *error, NSInteger statusCode, id json) {
                                                             if (!error) {
                                                                 //do something with response
                                                             }
    
                                                         }];
    

    For https:

     [[Requester sharedInstance] secureRequestToPath:@"user/authenticate"
                                                           method:HTTPMethodPOST
                                                           params:@{@"username":username,@"password":password}
                                                         complete:^(NSError *error, NSInteger statusCode, id json) {
                                                             if (!error) {
                                                                 //do something with response
                                                             }
    
                                                         }];