diff --git a/Rexxar/Decorator/RXRRequestDecorator.m b/Rexxar/Decorator/RXRRequestDecorator.m index f3ab2e8..69c2f2b 100644 --- a/Rexxar/Decorator/RXRRequestDecorator.m +++ b/Rexxar/Decorator/RXRRequestDecorator.m @@ -11,8 +11,19 @@ #import "NSURL+Rexxar.h" +@interface RXRRequestDecorator () + +@property (nonatomic, strong) RXRHTTPRequestSerializer *requestSerializer; + +@end + @implementation RXRRequestDecorator +- (instancetype)init +{ + return [self initWithHeaders:@{} parameters:@{}]; +} + - (instancetype)initWithHeaders:(NSDictionary *)headers parameters:(NSDictionary *)parameters { @@ -20,6 +31,14 @@ - (instancetype)initWithHeaders:(NSDictionary *)headers if (self) { _headers = [headers copy]; _parameters = [parameters copy]; + _requestSerializer = [[RXRHTTPRequestSerializer alloc] init]; + + // Do not encode queries to HTTP body for POST method. + if (![_requestSerializer.HTTPMethodsEncodingParametersInURI containsObject:@"POST"]) { + NSMutableSet *set = [_requestSerializer.HTTPMethodsEncodingParametersInURI mutableCopy]; + [set addObject:@"POST"]; + _requestSerializer.HTTPMethodsEncodingParametersInURI = [set copy]; + } } return self; } @@ -48,24 +67,16 @@ - (NSURLRequest *)decoratedRequestFromOriginalRequest:(NSURLRequest *)originalRe NSMutableDictionary *parameters = [NSMutableDictionary dictionaryWithDictionary:self.parameters]; [self _rxr_addQuery:mutableRequest.URL.query toParameters:parameters]; - // Get parameters from POST request body - // Note: `requestBySerializingRequest:withParameters:error:` method will add query to HTTP body for POST request - if ([mutableRequest.HTTPMethod.uppercaseString isEqualToString:@"POST"] - && mutableRequest.HTTPBody - && [[[mutableRequest valueForHTTPHeaderField:@"Content-Type"] lowercaseString] isEqualToString:@"application/x-www-form-urlencoded"]) { - NSString *bodyQueries = [[NSString alloc] initWithData:mutableRequest.HTTPBody encoding:kCFStringEncodingUTF8]; - [self _rxr_addQuery:bodyQueries toParameters:parameters]; - } - - // Remove query from url because RXRHTTPRequestSerializer will add all the parameters through - // `requestBySerializingRequest:withParameters:error:` method. + // Note: mutableRequest.URL.query has been added to the paramters, _requestSerializer will generate a new NSURLRequest + // object from the parameters every time when it decorates a request. If we don't remove query from URL, request may + // contain duplicated query string if the original request is decorated more than 2 times. NSURLComponents *comp = [[NSURLComponents alloc] initWithURL:mutableRequest.URL resolvingAgainstBaseURL:NO]; comp.query = nil; mutableRequest.URL = comp.URL; - return [[RXRHTTPRequestSerializer serializer] requestBySerializingRequest:[mutableRequest copy] - withParameters:parameters - error:nil]; + return [_requestSerializer requestBySerializingRequest:mutableRequest + withParameters:parameters + error:nil]; } - (void)_rxr_addQuery:(NSString *)query toParameters:(NSMutableDictionary *)parameters