@@ -105,17 +105,19 @@ - (void)_test_NSURLSession:(NSURLSession*)session
105105
106106- (void )_test_redirect_NSURLSession : (NSURLSession *)session
107107 httpMethod : (NSString *)requestHTTPMethod
108+ headers : (NSDictionary *)headers
108109 jsonBody : (NSDictionary *)json
109110 delays : (NSTimeInterval )delay
110111 redirectStatusCode : (int )redirectStatusCode
111- completion : (void (^)(NSString * redirectedRequestMethod, id redirectedRequestJSONBody, NSHTTPURLResponse *redirectHTTPResponse, id finalJSONResponse, NSError *errorResponse))completion
112+ completion : (void (^)(NSString * redirectedRequestMethod, NSDictionary * redirectedRequestHeaders, id redirectedRequestJSONBody, NSHTTPURLResponse *redirectHTTPResponse, id finalJSONResponse, NSError *errorResponse))completion
112113{
113114 if ([NSURLSession class ])
114115 {
115116 const NSTimeInterval requestTime = delay;
116117 const NSTimeInterval responseTime = delay;
117118
118119 __block __strong NSString * capturedRedirectedRequestMethod = nil ;
120+ __block __strong NSDictionary * capturedRedirectedRequestHeaders = nil ;
119121 __block __strong id capturedRedirectedRequestJSONBody = nil ;
120122 __block __strong NSHTTPURLResponse * capturedRedirectHTTPResponse = nil ;
121123 __block __strong id capturedResponseJSONBody = nil ;
@@ -139,6 +141,7 @@ - (void)_test_redirect_NSURLSession:(NSURLSession*)session
139141 return [[[request URL ] path ] isEqualToString: @" /newlocation" ];
140142 } withStubResponse: ^OHHTTPStubsResponse *(NSURLRequest *redirectedRequest) {
141143 capturedRedirectedRequestMethod = redirectedRequest.HTTPMethod ;
144+ capturedRedirectedRequestHeaders = redirectedRequest.allHTTPHeaderFields ;
142145 if (redirectedRequest.OHHTTPStubs_HTTPBody ) {
143146 capturedRedirectedRequestJSONBody = [NSJSONSerialization JSONObjectWithData: redirectedRequest.OHHTTPStubs_HTTPBody options: 0 error: NULL ];
144147 } else {
@@ -155,6 +158,7 @@ - (void)_test_redirect_NSURLSession:(NSURLSession*)session
155158 // Building the initial request.
156159 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: [NSURL URLWithString: @" foo://unknownhost:666/oldlocation" ]];
157160 request.HTTPMethod = requestHTTPMethod;
161+ request.allHTTPHeaderFields = headers;
158162 if (requestBody)
159163 {
160164 request.HTTPBody = requestBody;
@@ -193,7 +197,7 @@ - (void)_test_redirect_NSURLSession:(NSURLSession*)session
193197 [task resume ];
194198
195199 [self waitForExpectationsWithTimeout: (requestTime+responseTime)*2 +0.1 handler: nil ];
196- completion (capturedRedirectedRequestMethod, capturedRedirectedRequestJSONBody,
200+ completion (capturedRedirectedRequestMethod, capturedRedirectedRequestHeaders, capturedRedirectedRequestJSONBody,
197201 capturedRedirectHTTPResponse,
198202 capturedResponseJSONBody, capturedResponseError);
199203 }
@@ -214,8 +218,8 @@ - (void)test_SharedNSURLSession
214218 XCTAssertEqualObjects (jsonResponse, json, @" Unexpected data received" );
215219 }];
216220
217- [self _test_redirect_NSURLSession: session httpMethod: @" GET" jsonBody: nil delays: 0.1 redirectStatusCode: 301
218- completion: ^(NSString *redirectedRequestMethod, id redirectedRequestJSONBody, NSHTTPURLResponse *redirectHTTPResponse, id finalJSONResponse, NSError *errorResponse)
221+ [self _test_redirect_NSURLSession: session httpMethod: @" GET" headers: nil jsonBody: nil delays: 0.1 redirectStatusCode: 301
222+ completion: ^(NSString *redirectedRequestMethod, NSDictionary *redirectedRequestHeaders, id redirectedRequestJSONBody, NSHTTPURLResponse *redirectHTTPResponse, id finalJSONResponse, NSError *errorResponse)
219223 {
220224 XCTAssertEqualObjects (redirectedRequestMethod, @" GET" , @" Expected redirected request to use GET method" );
221225 XCTAssertNil (redirectedRequestJSONBody, @" Expected redirected request to have empty body" );
@@ -245,8 +249,8 @@ - (void)test_NSURLSessionDefaultConfig
245249 XCTAssertEqualObjects (jsonResponse, json, @" Unexpected data received" );
246250 }];
247251
248- [self _test_redirect_NSURLSession: session httpMethod: @" GET" jsonBody: nil delays: 0.1 redirectStatusCode: 301
249- completion: ^(NSString *redirectedRequestMethod, id redirectedRequestJSONBody, NSHTTPURLResponse *redirectHTTPResponse, id finalJSONResponse, NSError *errorResponse)
252+ [self _test_redirect_NSURLSession: session httpMethod: @" GET" headers: nil jsonBody: nil delays: 0.1 redirectStatusCode: 301
253+ completion: ^(NSString *redirectedRequestMethod, NSDictionary *redirectedRequestHeaders, id redirectedRequestJSONBody, NSHTTPURLResponse *redirectHTTPResponse, id finalJSONResponse, NSError *errorResponse)
250254 {
251255 XCTAssertEqualObjects (redirectedRequestMethod, @" GET" , @" Expected redirected request to use GET method" );
252256 XCTAssertNil (redirectedRequestJSONBody, @" Expected redirected request to have empty body" );
@@ -272,8 +276,8 @@ - (void)test_NSURLSessionDefaultConfig_notFollowingRedirects
272276 NSURLSessionConfiguration * config = [NSURLSessionConfiguration defaultSessionConfiguration ];
273277 NSURLSession *session = [NSURLSession sessionWithConfiguration: config delegate: delegate delegateQueue: nil ];
274278
275- [self _test_redirect_NSURLSession: session httpMethod: @" GET" jsonBody: nil delays: 0.1 redirectStatusCode: 301
276- completion: ^(NSString *redirectedRequestMethod, id redirectedRequestJSONBody, NSHTTPURLResponse *redirectHTTPResponse, id finalJSONResponse, NSError *errorResponse)
279+ [self _test_redirect_NSURLSession: session httpMethod: @" GET" headers: nil jsonBody: nil delays: 0.1 redirectStatusCode: 301
280+ completion: ^(NSString *redirectedRequestMethod, NSDictionary *redirectedRequestHeaders, id redirectedRequestJSONBody, NSHTTPURLResponse *redirectHTTPResponse, id finalJSONResponse, NSError *errorResponse)
277281 {
278282 XCTAssertNil (redirectedRequestMethod, @" Expected no redirected request to fire" );
279283 XCTAssertNil (redirectedRequestJSONBody, @" Expected no redirected request to fire" );
@@ -313,8 +317,8 @@ - (void)test_NSURLSessionDefaultConfig_MethodAndDataRetentionOnRedirect
313317 NSURLSessionTestDelegate* delegate = [NSURLSessionTestDelegate delegateFollowingRedirects: YES fulfillOnCompletion: nil ];
314318 NSURLSession *session = [NSURLSession sessionWithConfiguration: config delegate: delegate delegateQueue: nil ];
315319
316- [self _test_redirect_NSURLSession: session httpMethod: method jsonBody: json delays: 0.0 redirectStatusCode: statusCode
317- completion: ^(NSString *redirectedRequestMethod, id redirectedRequestJSONBody, NSHTTPURLResponse *redirectHTTPResponse, id finalJSONResponse, NSError *errorResponse)
320+ [self _test_redirect_NSURLSession: session httpMethod: method headers: nil jsonBody: json delays: 0.0 redirectStatusCode: statusCode
321+ completion: ^(NSString *redirectedRequestMethod, NSDictionary *redirectedRequestHeaders, id redirectedRequestJSONBody, NSHTTPURLResponse *redirectHTTPResponse, id finalJSONResponse, NSError *errorResponse)
318322 {
319323 XCTAssertEqualObjects (redirectedRequestMethod, method,
320324 @" Expected the HTTP method to be unchanged after %d redirect" , statusCode);
@@ -338,8 +342,8 @@ - (void)test_NSURLSessionDefaultConfig_MethodAndDataRetentionOnRedirect
338342 NSURLSessionTestDelegate* delegate = [NSURLSessionTestDelegate delegateFollowingRedirects: YES fulfillOnCompletion: nil ];
339343 NSURLSession *session = [NSURLSession sessionWithConfiguration: config delegate: delegate delegateQueue: nil ];
340344
341- [self _test_redirect_NSURLSession: session httpMethod: method jsonBody: json delays: 0.0 redirectStatusCode: 303
342- completion: ^(NSString *redirectedRequestMethod, id redirectedRequestJSONBody, NSHTTPURLResponse *redirectHTTPResponse, id finalJSONResponse, NSError *errorResponse)
345+ [self _test_redirect_NSURLSession: session httpMethod: method headers: nil jsonBody: json delays: 0.0 redirectStatusCode: 303
346+ completion: ^(NSString *redirectedRequestMethod, NSDictionary *redirectedRequestHeaders, id redirectedRequestJSONBody, NSHTTPURLResponse *redirectHTTPResponse, id finalJSONResponse, NSError *errorResponse)
343347 {
344348 XCTAssertEqualObjects (redirectedRequestMethod, @" GET" , @" Expected 303 redirected request HTTP method to be reset to GET" );
345349 XCTAssertNil (redirectedRequestJSONBody, @" Expected 303-redirected request to have empty body" );
@@ -356,6 +360,53 @@ - (void)test_NSURLSessionDefaultConfig_MethodAndDataRetentionOnRedirect
356360 NSLog (@" /!\\ Test skipped because the NSURLSession class is not available on this OS version. Run the tests a target with a more recent OS.\n " );
357361 }
358362}
363+
364+ - (void )test_NSURLSessionDefaultConfig_HeaderRetentionPolicyOnRedirect {
365+ if ([NSURLSessionConfiguration class ] && [NSURLSession class ])
366+ {
367+ NSArray <NSString *>* allMethods = @[@" GET" , @" HEAD" , @" POST" , @" PATCH" , @" PUT" ];
368+
369+ /* * 301, 302, 307, 308: GET, HEAD, POST, PATCH, PUT should all maintain most HTTP headers unchanged **/
370+ for (NSNumber * redirectStatusCode in @[@301 , @302 , @307 , @308 ]) {
371+ int statusCode = redirectStatusCode.intValue ;
372+ for (NSString * method in allMethods) {
373+
374+ NSURLSessionConfiguration * config = [NSURLSessionConfiguration defaultSessionConfiguration ];
375+ NSURLSessionTestDelegate* delegate = [NSURLSessionTestDelegate delegateFollowingRedirects: YES fulfillOnCompletion: nil ];
376+ NSURLSession *session = [NSURLSession sessionWithConfiguration: config delegate: delegate delegateQueue: nil ];
377+
378+ NSDictionary *headers = @{
379+ @" Authorization" : @" authorization" ,
380+ @" Connection" : @" connection" ,
381+ @" Preserved1" : @" preserved"
382+ @" Host" : @" host" ,
383+ @" Proxy-Authenticate" : @" proxy-authenticate" ,
384+ @" Proxy-Authorization" : @" proxy-authorization" ,
385+ @" Preserved2" : @" preserved" ,
386+ @" WWW-Authenticate" : @" www-authenticate" ,
387+ };
388+ [self _test_redirect_NSURLSession: session httpMethod: method headers: headers jsonBody: nil delays: 0.0 redirectStatusCode: statusCode
389+ completion: ^(NSString *redirectedRequestMethod, NSDictionary *redirectedRequestHeaders, id redirectedRequestJSONBody, NSHTTPURLResponse *redirectHTTPResponse, id finalJSONResponse, NSError *errorResponse)
390+ {
391+ XCTAssertNil (redirectedRequestHeaders[@" Authorization" ], @" Authorization header is preserved when following redirects" );
392+ XCTAssertNil (redirectedRequestHeaders[@" Connection" ], @" Connection header is preserved when following redirects" );
393+ XCTAssertNil (redirectedRequestHeaders[@" Host" ], @" Host header is preserved when following redirects" );
394+ XCTAssertNil (redirectedRequestHeaders[@" Proxy-Authenticate" ], @" Proxy-Authenticate header is preserved when following redirects" );
395+ XCTAssertNil (redirectedRequestHeaders[@" Proxy-Authorization" ], @" Proxy-Authorization header is preserved when following redirects" );
396+ XCTAssertNil (redirectedRequestHeaders[@" WWW-Authenticate" ], @" WWW-Authenticate header is preserved when following redirects" );
397+ XCTAssertEqual (redirectedRequestHeaders[@" Preserved1" ], @" preserved" , @" Regular header is not preserved when following redirects" );
398+ XCTAssertEqual (redirectedRequestHeaders[@" Preserved2" ], @" preserved" , @" Regular header is not preserved when following redirects" );
399+ }];
400+
401+ [session finishTasksAndInvalidate ];
402+ }
403+ }
404+ }
405+ else
406+ {
407+ NSLog (@" /!\\ Test skipped because the NSURLSession class is not available on this OS version. Run the tests a target with a more recent OS.\n " );
408+ }
409+ }
359410#endif
360411
361412- (void )test_NSURLSessionEphemeralConfig
@@ -371,8 +422,8 @@ - (void)test_NSURLSessionEphemeralConfig
371422 XCTAssertEqualObjects (jsonResponse, json, @" Unexpected data received" );
372423 }];
373424
374- [self _test_redirect_NSURLSession: session httpMethod: @" GET" jsonBody: json delays: 0.1 redirectStatusCode: 301
375- completion: ^(NSString *redirectedRequestMethod, id redirectedRequestJSONBody, NSHTTPURLResponse *redirectHTTPResponse, id finalJSONResponse, NSError *errorResponse)
425+ [self _test_redirect_NSURLSession: session httpMethod: @" GET" headers: nil jsonBody: json delays: 0.1 redirectStatusCode: 301
426+ completion: ^(NSString *redirectedRequestMethod, NSDictionary *redirectedRequestHeaders, id redirectedRequestJSONBody, NSHTTPURLResponse *redirectHTTPResponse, id finalJSONResponse, NSError *errorResponse)
376427 {
377428 XCTAssertEqualObjects (redirectedRequestMethod, @" GET" , @" Expected the HTTP method of redirected request to be GET" );
378429 XCTAssertEqualObjects (redirectedRequestJSONBody, json, @" Expected redirected request to have the same body as the original request" );
@@ -404,8 +455,8 @@ - (void)test_NSURLSessionDefaultConfig_Disabled
404455 XCTAssertNil (jsonResponse, @" Data should not have been received as stubs should be disabled" );
405456 }];
406457
407- [self _test_redirect_NSURLSession: session httpMethod: @" GET" jsonBody: json delays: 0.1 redirectStatusCode: 301
408- completion: ^(NSString *redirectedRequestMethod, id redirectedRequestJSONBody, NSHTTPURLResponse *finalHTTPResponse, id finalJSONResponse, NSError *errorResponse)
458+ [self _test_redirect_NSURLSession: session httpMethod: @" GET" headers: nil jsonBody: json delays: 0.1 redirectStatusCode: 301
459+ completion: ^(NSString *redirectedRequestMethod, NSDictionary *redirectedRequestHeaders, id redirectedRequestJSONBody, NSHTTPURLResponse *finalHTTPResponse, id finalJSONResponse, NSError *errorResponse)
409460 {
410461 // Stubs were disabled for this session, so we should get an error instead of the stubs data
411462 XCTAssertNotNil (errorResponse, @" Expected error but none found" );
0 commit comments