Hermod
User friendly HTTP client on top of AFNetworking
Install / Use
/learn @mobilejazz/HermodREADME

Hermod
User friendly HTTP client on top of AFNetworking
Installation
The easiest to import Hermod to your project is by using Cocoa Pods:
pod 'Hermod', '~> 1.0.0'
1. HTTP Client
1.1 Definining the instance
To create a new API client you must specify the host domain as well as the API path where all requests will be directed to.
HMClient *client = [[HMClient alloc] initWithConfigurator:^(HMClientConfigurator *configurator) {
configurator.serverPath = @"http://www.domain.com";
configurator.apiPath = @"/api/v1";
}];
1.2 Creating requests and upload requests
Creating requests with HMClient is very easy. Just create an instnace of HMRequest and configure it.
HMRequest *request = [HMRequest requestWithPath:@"users/hobbies"];
request.HTTPMethod = HMHTTPMethodPUT;
request.parameters = @{"name": "kitesurfing",
"rating": 8,
};
Requests by default use the HMHTTPMethodGET.
To create an upload request, instantiate the HMUploadRequest and add an array of HMUploadTask objects, one per each upload task. Upload requests by default are HMHTTPMethodPOST.
1.3 Performing requests
In order to perform requests, HMClient provides a protocol called HMRequestExecutor that defines the following two methods:
- (void)performRequest:(HMRequest*)request completionBlock:(HMResponseBlock)completionBlock;
- (void)performRequest:(HMRequest*)request apiPath:(NSString*)apiPath completionBlock:(HMResponseBlock)completionBlock;
The first method uses the default apiClient's apiPath, the second method uses a custom apiPath. The response block contains a HMResponse. If error, it is going to be encapsulated inside the HMResponse.
HMClient implements this protocol. Therefore, you can use it directly to perform a request. However, you can build your own request executors and do validation checks and other custom actions in the middle. As a good example of it, HMClient provides an OAuth session handler called HMOAuthSession. This object, which implements the HMRequestExecutor protocol, validates the OAuth state and configures an HMClient instance with the good HTTP authentication headers. To know more about this object, see documentation below.
id <HMRequestExecutor> requestExecutor = _myApiClient;
HMRequest *request = [HMRequest requestWithPath:@"users/reset-password"];
request.httpMethod = HTTPMethodPOST;
request.parameters = @{@"email": email};
[requestExecutor performRequest:request completionBlock:^(HMResponse *response, NSInteger key) {
if (response.error == nil)
{
NSLog(@"Response object: %@", [response.responseObject description]);
}
else
{
NSLog(@"Response error: %@", [response.error description]);
}
}];
1.4 Configuring the API Client
1.4.1 Managing the URL Cache
HMClient implements a basic offline simulation via the URL cache. To configure it, use the default init method of HMClient and set the cacheManagement of the HMClientConfigurator to HMClientCacheManagementOffline. When configured, the app will use the URL Cache to return already cached respones when being offline. By default the cacheManagement is set to HMClientCacheManagementDefault (which ignores the URL cache when being offline).
HMClient *apiClient = [[HMClient alloc] initWithConfigurator:^(HMClientConfigurator *configurator) {
configurator.host = @"http://www.domain.com";
configurator.apiPath = @"/api/v1";
// Use the URLCache to return already cached responses when being offline.
configurator.cacheManagement = HMClientCacheManagementOffline;
}];
1.4.2 Selecting request and response serializers
While configuring a HMClient instance, it is possible to customize the request and response serializers.
HMClient *apiClient = [[HMClient alloc] initWithConfigurator:^(HMClientConfigurator * _Nonnull configurator) {
// Here goes the overall configuration
[...]
// Configuration of request and response serializers
configurator.requestSerializerType = HMClientRequestSerializerTypeJSON;
configurator.responseSerializerType = HMClientResponseSerializerTypeJSON;
}];
The supported serializers are:
Request Serializers
HMClientRequestSerializerTypeJSON: JSON format request (mimetype applicaiton/JSON)HMClientRequestSerializerTypeFormUrlencoded: URL Encoded request (mimetype applicaiton/x-www-form-urlencoded with utf8 charset)
Response Serializers
HMClientResponseSerializerTypeJSON: JSON format response (response object will beNSDictionaryorNSArray)HMClientResponseSerializerTypeRaw: RAW response (response object will beNSData).
By default, request and response serializers are set to JSON format. However, it is possible to change them to the other types.
HMClient only support the listed types above. If there is a need for different type, the library will have to be extended and implemented.
1.4.3 Response dispatch queue
This library is built on top of AFNetworking. Therefore, when performing a request, the response is returned asyncronously in the default dispatch_queue_t selected by AFNetworking, which usually is in the main queue.
HMClient offers the option to set a custom dispatch_queue_t to return its request's responses in. This can be set globaly o per request.
To set it per request, set a dispatch_queue_t inside the HMRequest's completionBlockQueue parameter. If not set (nil), then the response block will be execute on the HMClient's global queue.
HMRequest *request = [HMRequest requestWithPath:@"user/12345"];
request.completionBlockQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
To set the global queue use the HMClientConfigurator object inside the init method. If not set, then the response block will be executed in the default AFNetworking reponse block queue.
HMClient *apiClient = [[HMClient alloc] initWithConfigurator:^(HMClientConfigurator *configurator) {
configurator.host = @"http://www.domain.com";
configurator.apiPath = @"/api/v1";
// Set a custom queue for all response blocks
configurator.completionBlockQueue = dispatch_queue_create("com.myapp.api.completion-queue", DISPATCH_QUEUE_SERIAL);
}];
1.5 Error Handling
Use the HMClientDelegate object to create server-specific errors and manage them.
In the following method, it is possible to specify custom errors depending of the content of the HTTP response. If an error is returned, then HMClient will assume the request failed and will include the error in its HMResponse.
- (NSError*)apiClient:(HMClient*)apiClient errorForResponseBody:(id)responseBody httpResponse:(NSHTTPURLResponse*)httpResponse incomingError:(NSError*)error
{
if ([responseBody isKindOfClass:NSDictionary.class])
{
if (responseBody[@"error_code"])
{
NSInteger errorCode = [responseBody[@"error_code"] integerValue];
NSString *message = responseBody[@"error_message"];
NSDictionary *userInfo = @{CustomApiErrorDomainNameKey: @(errorCode),
NSLocalizedDescriptionKey: message,
};
error = [NSError errorWithDomain:@"CustomApiErrorDomain" code:errorCode userInfo:userInfo];
}
}
return error;
}
Finally, use the method -apiClient:didReceiveErrorInResponse: of HMClientDelegate to globaly manage errors. Typically, you can use it to log errors, show alerts, and even logout the logged-in user if an unauthorized error.
- (void)apiClient:(HMClient*)apiClient didReceiveErrorInResponse:(HMResponse*)response
{
// Manage the error of the response.
}
2. HMOAuthSession (OAuth Support)
In order to support OAuth, Hermod has the class HMOAuthSession. This class will keep the OAuth session alive and perform the fetch and refresh of tokens. Furthermore, it implements the HMRequestExecutor protocol in order to perform requests with OAuth support.
2.1 Configuration
To configure an HMOAuthSession just create a new instnace and use the initWithConfigurator: method as follows:
HMOAuthSession *oauthSession = [[HMOAuthSession alloc] initWithConfigurator:^(HMOAuthSesionConfigurator *configurator) {
configurator.apiClient = apiClient; // <-- configured `HMClient` instance
configurator.apiOAuthPath = @"/api/oauth2/token";
configurator.clientId = @"client_id";
configurator.clientSecret = @"client_secret";
}];
It is required to provide configured HMClient instance, the api path of the OAuth methods, the client ID and client secret.
And that's all. Now the instance is ready to be used:
id <HMRequestExecutor> requestExecutor = _myOauthApiSession;
HMRequest *request = [HMRequest requestWithPath:@"users/reset-password"];
request.httpMethod = HMHTTPMethodPOST;
request.parameters = @{@"email": email};
[requestExecutor performRequest:request completionBlock:^(HMResponse *response, NSInteger key) {
if (response.error == nil)
NSLog(@"Response object: %@", [response.responseObject description]);
else
NSLog(@"Response error: %@", [response.error descriptio


