2015-09-18 15:02:15 -07:00
// AFHTTPSessionManager . m
2017-03-09 20:10:44 -08:00
// Copyright ( c ) 2011 – 2016 Alamofire Software Foundation ( http : // alamofire . org / )
2015-09-18 15:02:15 -07:00
//
// Permission is hereby granted , free of charge , to any person obtaining a copy
// of this software and associated documentation files ( the "Software" ) , to deal
// in the Software without restriction , including without limitation the rights
// to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
// copies of the Software , and to permit persons to whom the Software is
// furnished to do so , subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software .
//
// THE SOFTWARE IS PROVIDED "AS IS" , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
// IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
// LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE .
# import "AFHTTPSessionManager.h"
# import "AFURLRequestSerialization.h"
# import "AFURLResponseSerialization.h"
# import < Availability . h >
2017-03-09 20:10:44 -08:00
# import < TargetConditionals . h >
2015-09-18 15:02:15 -07:00
# import < Security / Security . h >
# import < netinet / in . h >
# import < netinet6 / in6 . h >
# import < arpa / inet . h >
# import < ifaddrs . h >
# import < netdb . h >
2017-03-09 20:10:44 -08:00
# if TARGET_OS _IOS || TARGET_OS _TV
2015-09-18 15:02:15 -07:00
# import < UIKit / UIKit . h >
# elif TARGET_OS _WATCH
# import < WatchKit / WatchKit . h >
# endif
@ interface AFHTTPSessionManager ( )
@ property ( readwrite , nonatomic , strong ) NSURL * baseURL ;
@ end
@ implementation AFHTTPSessionManager
@ dynamic responseSerializer ;
+ ( instancetype ) manager {
return [ [ [ self class ] alloc ] initWithBaseURL : nil ] ;
}
- ( instancetype ) init {
return [ self initWithBaseURL : nil ] ;
}
- ( instancetype ) initWithBaseURL : ( NSURL * ) url {
return [ self initWithBaseURL : url sessionConfiguration : nil ] ;
}
- ( instancetype ) initWithSessionConfiguration : ( NSURLSessionConfiguration * ) configuration {
return [ self initWithBaseURL : nil sessionConfiguration : configuration ] ;
}
- ( instancetype ) initWithBaseURL : ( NSURL * ) url
sessionConfiguration : ( NSURLSessionConfiguration * ) configuration
{
self = [ super initWithSessionConfiguration : configuration ] ;
if ( ! self ) {
return nil ;
}
// Ensure terminal slash for baseURL path , so that NSURL + URLWithString : relativeToURL : works as expected
if ( [ [ url path ] length ] > 0 && ! [ [ url absoluteString ] hasSuffix : @ "/" ] ) {
url = [ url URLByAppendingPathComponent : @ "" ] ;
}
self . baseURL = url ;
self . requestSerializer = [ AFHTTPRequestSerializer serializer ] ;
self . responseSerializer = [ AFJSONResponseSerializer serializer ] ;
return self ;
}
# pragma mark -
- ( void ) setRequestSerializer : ( AFHTTPRequestSerializer < AFURLRequestSerialization > * ) requestSerializer {
NSParameterAssert ( requestSerializer ) ;
_requestSerializer = requestSerializer ;
}
- ( void ) setResponseSerializer : ( AFHTTPResponseSerializer < AFURLResponseSerialization > * ) responseSerializer {
NSParameterAssert ( responseSerializer ) ;
[ super setResponseSerializer : responseSerializer ] ;
}
2017-03-09 20:10:44 -08:00
@ dynamic securityPolicy ;
- ( void ) setSecurityPolicy : ( AFSecurityPolicy * ) securityPolicy {
if ( securityPolicy . SSLPinningMode ! = AFSSLPinningModeNone && ! [ self . baseURL . scheme isEqualToString : @ "https" ] ) {
NSString * pinningMode = @ "Unknown Pinning Mode" ;
switch ( securityPolicy . SSLPinningMode ) {
case AFSSLPinningModeNone : pinningMode = @ "AFSSLPinningModeNone" ; break ;
case AFSSLPinningModeCertificate : pinningMode = @ "AFSSLPinningModeCertificate" ; break ;
case AFSSLPinningModePublicKey : pinningMode = @ "AFSSLPinningModePublicKey" ; break ;
}
NSString * reason = [ NSString stringWithFormat : @ "A security policy configured with `%@` can only be applied on a manager with a secure base URL (i.e. https)" , pinningMode ] ;
@ throw [ NSException exceptionWithName : @ "Invalid Security Policy" reason : reason userInfo : nil ] ;
}
[ super setSecurityPolicy : securityPolicy ] ;
}
2015-09-18 15:02:15 -07:00
# pragma mark -
- ( NSURLSessionDataTask * ) GET : ( NSString * ) URLString
parameters : ( id ) parameters
success : ( void ( ^ ) ( NSURLSessionDataTask * task , id responseObject ) ) success
failure : ( void ( ^ ) ( NSURLSessionDataTask * task , NSError * error ) ) failure
{
2017-03-09 20:10:44 -08:00
return [ self GET : URLString parameters : parameters progress : nil success : success failure : failure ] ;
}
- ( NSURLSessionDataTask * ) GET : ( NSString * ) URLString
parameters : ( id ) parameters
progress : ( void ( ^ ) ( NSProgress * _Nonnull ) ) downloadProgress
success : ( void ( ^ ) ( NSURLSessionDataTask * _Nonnull , id _Nullable ) ) success
failure : ( void ( ^ ) ( NSURLSessionDataTask * _Nullable , NSError * _Nonnull ) ) failure
{
NSURLSessionDataTask * dataTask = [ self dataTaskWithHTTPMethod : @ "GET"
URLString : URLString
parameters : parameters
uploadProgress : nil
downloadProgress : downloadProgress
success : success
failure : failure ] ;
2015-09-18 15:02:15 -07:00
[ dataTask resume ] ;
return dataTask ;
}
- ( NSURLSessionDataTask * ) HEAD : ( NSString * ) URLString
parameters : ( id ) parameters
success : ( void ( ^ ) ( NSURLSessionDataTask * task ) ) success
failure : ( void ( ^ ) ( NSURLSessionDataTask * task , NSError * error ) ) failure
{
2017-03-09 20:10:44 -08:00
NSURLSessionDataTask * dataTask = [ self dataTaskWithHTTPMethod : @ "HEAD" URLString : URLString parameters : parameters uploadProgress : nil downloadProgress : nil success : ^ ( NSURLSessionDataTask * task , __unused id responseObject ) {
2015-09-18 15:02:15 -07:00
if ( success ) {
success ( task ) ;
}
} failure : failure ] ;
[ dataTask resume ] ;
return dataTask ;
}
- ( NSURLSessionDataTask * ) POST : ( NSString * ) URLString
parameters : ( id ) parameters
success : ( void ( ^ ) ( NSURLSessionDataTask * task , id responseObject ) ) success
failure : ( void ( ^ ) ( NSURLSessionDataTask * task , NSError * error ) ) failure
{
2017-03-09 20:10:44 -08:00
return [ self POST : URLString parameters : parameters progress : nil success : success failure : failure ] ;
}
- ( NSURLSessionDataTask * ) POST : ( NSString * ) URLString
parameters : ( id ) parameters
progress : ( void ( ^ ) ( NSProgress * _Nonnull ) ) uploadProgress
success : ( void ( ^ ) ( NSURLSessionDataTask * _Nonnull , id _Nullable ) ) success
failure : ( void ( ^ ) ( NSURLSessionDataTask * _Nullable , NSError * _Nonnull ) ) failure
{
NSURLSessionDataTask * dataTask = [ self dataTaskWithHTTPMethod : @ "POST" URLString : URLString parameters : parameters uploadProgress : uploadProgress downloadProgress : nil success : success failure : failure ] ;
2015-09-18 15:02:15 -07:00
[ dataTask resume ] ;
return dataTask ;
}
2017-03-09 20:10:44 -08:00
- ( NSURLSessionDataTask * ) POST : ( NSString * ) URLString
parameters : ( nullable id ) parameters
constructingBodyWithBlock : ( nullable void ( ^ ) ( id < AFMultipartFormData > _Nonnull ) ) block
success : ( nullable void ( ^ ) ( NSURLSessionDataTask * _Nonnull , id _Nullable ) ) success
failure : ( nullable void ( ^ ) ( NSURLSessionDataTask * _Nullable , NSError * _Nonnull ) ) failure
{
return [ self POST : URLString parameters : parameters constructingBodyWithBlock : block progress : nil success : success failure : failure ] ;
}
2015-09-18 15:02:15 -07:00
- ( NSURLSessionDataTask * ) POST : ( NSString * ) URLString
parameters : ( id ) parameters
constructingBodyWithBlock : ( void ( ^ ) ( id < AFMultipartFormData > formData ) ) block
2017-03-09 20:10:44 -08:00
progress : ( nullable void ( ^ ) ( NSProgress * _Nonnull ) ) uploadProgress
2015-09-18 15:02:15 -07:00
success : ( void ( ^ ) ( NSURLSessionDataTask * task , id responseObject ) ) success
failure : ( void ( ^ ) ( NSURLSessionDataTask * task , NSError * error ) ) failure
{
NSError * serializationError = nil ;
NSMutableURLRequest * request = [ self . requestSerializer multipartFormRequestWithMethod : @ "POST" URLString : [ [ NSURL URLWithString : URLString relativeToURL : self . baseURL ] absoluteString ] parameters : parameters constructingBodyWithBlock : block error : & serializationError ] ;
if ( serializationError ) {
if ( failure ) {
dispatch_async ( self . completionQueue ? : dispatch_get _main _queue ( ) , ^ {
failure ( nil , serializationError ) ;
} ) ;
}
return nil ;
}
2017-03-09 20:10:44 -08:00
__block NSURLSessionDataTask * task = [ self uploadTaskWithStreamedRequest : request progress : uploadProgress completionHandler : ^ ( NSURLResponse * __unused response , id responseObject , NSError * error ) {
2015-09-18 15:02:15 -07:00
if ( error ) {
if ( failure ) {
failure ( task , error ) ;
}
} else {
if ( success ) {
success ( task , responseObject ) ;
}
}
} ] ;
[ task resume ] ;
return task ;
}
- ( NSURLSessionDataTask * ) PUT : ( NSString * ) URLString
parameters : ( id ) parameters
success : ( void ( ^ ) ( NSURLSessionDataTask * task , id responseObject ) ) success
failure : ( void ( ^ ) ( NSURLSessionDataTask * task , NSError * error ) ) failure
{
2017-03-09 20:10:44 -08:00
NSURLSessionDataTask * dataTask = [ self dataTaskWithHTTPMethod : @ "PUT" URLString : URLString parameters : parameters uploadProgress : nil downloadProgress : nil success : success failure : failure ] ;
2015-09-18 15:02:15 -07:00
[ dataTask resume ] ;
return dataTask ;
}
- ( NSURLSessionDataTask * ) PATCH : ( NSString * ) URLString
parameters : ( id ) parameters
success : ( void ( ^ ) ( NSURLSessionDataTask * task , id responseObject ) ) success
failure : ( void ( ^ ) ( NSURLSessionDataTask * task , NSError * error ) ) failure
{
2017-03-09 20:10:44 -08:00
NSURLSessionDataTask * dataTask = [ self dataTaskWithHTTPMethod : @ "PATCH" URLString : URLString parameters : parameters uploadProgress : nil downloadProgress : nil success : success failure : failure ] ;
2015-09-18 15:02:15 -07:00
[ dataTask resume ] ;
return dataTask ;
}
- ( NSURLSessionDataTask * ) DELETE : ( NSString * ) URLString
parameters : ( id ) parameters
success : ( void ( ^ ) ( NSURLSessionDataTask * task , id responseObject ) ) success
failure : ( void ( ^ ) ( NSURLSessionDataTask * task , NSError * error ) ) failure
{
2017-03-09 20:10:44 -08:00
NSURLSessionDataTask * dataTask = [ self dataTaskWithHTTPMethod : @ "DELETE" URLString : URLString parameters : parameters uploadProgress : nil downloadProgress : nil success : success failure : failure ] ;
2015-09-18 15:02:15 -07:00
[ dataTask resume ] ;
return dataTask ;
}
- ( NSURLSessionDataTask * ) dataTaskWithHTTPMethod : ( NSString * ) method
URLString : ( NSString * ) URLString
parameters : ( id ) parameters
2017-03-09 20:10:44 -08:00
uploadProgress : ( nullable void ( ^ ) ( NSProgress * uploadProgress ) ) uploadProgress
downloadProgress : ( nullable void ( ^ ) ( NSProgress * downloadProgress ) ) downloadProgress
2015-09-18 15:02:15 -07:00
success : ( void ( ^ ) ( NSURLSessionDataTask * , id ) ) success
failure : ( void ( ^ ) ( NSURLSessionDataTask * , NSError * ) ) failure
{
NSError * serializationError = nil ;
NSMutableURLRequest * request = [ self . requestSerializer requestWithMethod : method URLString : [ [ NSURL URLWithString : URLString relativeToURL : self . baseURL ] absoluteString ] parameters : parameters error : & serializationError ] ;
if ( serializationError ) {
if ( failure ) {
dispatch_async ( self . completionQueue ? : dispatch_get _main _queue ( ) , ^ {
failure ( nil , serializationError ) ;
} ) ;
}
return nil ;
}
__block NSURLSessionDataTask * dataTask = nil ;
2017-03-09 20:10:44 -08:00
dataTask = [ self dataTaskWithRequest : request
uploadProgress : uploadProgress
downloadProgress : downloadProgress
completionHandler : ^ ( NSURLResponse * __unused response , id responseObject , NSError * error ) {
2015-09-18 15:02:15 -07:00
if ( error ) {
if ( failure ) {
failure ( dataTask , error ) ;
}
} else {
if ( success ) {
success ( dataTask , responseObject ) ;
}
}
} ] ;
return dataTask ;
}
# pragma mark - NSObject
- ( NSString * ) description {
return [ NSString stringWithFormat : @ "<%@: %p, baseURL: %@, session: %@, operationQueue: %@>" , NSStringFromClass ( [ self class ] ) , self , [ self . baseURL absoluteString ] , self . session , self . operationQueue ] ;
}
# pragma mark - NSSecureCoding
+ ( BOOL ) supportsSecureCoding {
return YES ;
}
2017-03-09 20:10:44 -08:00
- ( instancetype ) initWithCoder : ( NSCoder * ) decoder {
2015-09-18 15:02:15 -07:00
NSURL * baseURL = [ decoder decodeObjectOfClass : [ NSURL class ] forKey : NSStringFromSelector ( @ selector ( baseURL ) ) ] ;
NSURLSessionConfiguration * configuration = [ decoder decodeObjectOfClass : [ NSURLSessionConfiguration class ] forKey : @ "sessionConfiguration" ] ;
if ( ! configuration ) {
NSString * configurationIdentifier = [ decoder decodeObjectOfClass : [ NSString class ] forKey : @ "identifier" ] ;
if ( configurationIdentifier ) {
# if ( defined ( __IPHONE _OS _VERSION _MIN _REQUIRED ) && __IPHONE _OS _VERSION _MIN _REQUIRED >= 80000 ) || ( defined ( __MAC _OS _X _VERSION _MIN _REQUIRED ) && __MAC _OS _X _VERSION _MIN _REQUIRED >= 1100 )
configuration = [ NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier : configurationIdentifier ] ;
# else
configuration = [ NSURLSessionConfiguration backgroundSessionConfiguration : configurationIdentifier ] ;
# endif
}
}
self = [ self initWithBaseURL : baseURL sessionConfiguration : configuration ] ;
if ( ! self ) {
return nil ;
}
self . requestSerializer = [ decoder decodeObjectOfClass : [ AFHTTPRequestSerializer class ] forKey : NSStringFromSelector ( @ selector ( requestSerializer ) ) ] ;
self . responseSerializer = [ decoder decodeObjectOfClass : [ AFHTTPResponseSerializer class ] forKey : NSStringFromSelector ( @ selector ( responseSerializer ) ) ] ;
2017-03-09 20:10:44 -08:00
AFSecurityPolicy * decodedPolicy = [ decoder decodeObjectOfClass : [ AFSecurityPolicy class ] forKey : NSStringFromSelector ( @ selector ( securityPolicy ) ) ] ;
if ( decodedPolicy ) {
self . securityPolicy = decodedPolicy ;
}
2015-09-18 15:02:15 -07:00
return self ;
}
- ( void ) encodeWithCoder : ( NSCoder * ) coder {
[ super encodeWithCoder : coder ] ;
[ coder encodeObject : self . baseURL forKey : NSStringFromSelector ( @ selector ( baseURL ) ) ] ;
if ( [ self . session . configuration conformsToProtocol : @ protocol ( NSCoding ) ] ) {
[ coder encodeObject : self . session . configuration forKey : @ "sessionConfiguration" ] ;
} else {
[ coder encodeObject : self . session . configuration . identifier forKey : @ "identifier" ] ;
}
[ coder encodeObject : self . requestSerializer forKey : NSStringFromSelector ( @ selector ( requestSerializer ) ) ] ;
[ coder encodeObject : self . responseSerializer forKey : NSStringFromSelector ( @ selector ( responseSerializer ) ) ] ;
2017-03-09 20:10:44 -08:00
[ coder encodeObject : self . securityPolicy forKey : NSStringFromSelector ( @ selector ( securityPolicy ) ) ] ;
2015-09-18 15:02:15 -07:00
}
# pragma mark - NSCopying
2017-03-09 20:10:44 -08:00
- ( instancetype ) copyWithZone : ( NSZone * ) zone {
2015-09-18 15:02:15 -07:00
AFHTTPSessionManager * HTTPClient = [ [ [ self class ] allocWithZone : zone ] initWithBaseURL : self . baseURL sessionConfiguration : self . session . configuration ] ;
HTTPClient . requestSerializer = [ self . requestSerializer copyWithZone : zone ] ;
HTTPClient . responseSerializer = [ self . responseSerializer copyWithZone : zone ] ;
2017-03-09 20:10:44 -08:00
HTTPClient . securityPolicy = [ self . securityPolicy copyWithZone : zone ] ;
2015-09-18 15:02:15 -07:00
return HTTPClient ;
}
@ end