Skip to content

Commit e2dd12e

Browse files
authored
Merge pull request #289 from sberrevoets/master
Drop special headers from redirected requests
2 parents da33b32 + 29ff8d8 commit e2dd12e

File tree

3 files changed

+96
-21
lines changed

3 files changed

+96
-21
lines changed

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@
33
## [Future release]
44
* Enabled application extension API only.
55
[@lightsprint09](https://github.com/lightsprint09)
6-
* Disabled a flaky redirect test and adding the known issue with redirects to the README.
6+
* Disabled a flaky redirect test and adding the known issue with redirects to the README.
77
[@jeffctown](https://github.com/jeffctown)
88
[#301](https://github.com/AliSoftware/OHHTTPStubs/pull/301)
99
* Added `isMethodHEAD()` to the `Swift` helpers.
1010
[@Simon-Kaz](https://github.com/Simon-Kaz)
1111
[#294](https://github.com/AliSoftware/OHHTTPStubs/pull/294)
12+
* Fixed issue with not preserving correct headers when following 3xx
13+
redirects.
14+
[@sberrevoets](https://github.com/sberrevoets)
1215

1316
## [6.1.0](https://github.com/AliSoftware/OHHTTPStubs/releases/tag/6.1.0)
1417

OHHTTPStubs/Sources/OHHTTPStubs.m

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -360,12 +360,30 @@ - (id)initWithRequest:(NSURLRequest *)request cachedResponse:(NSCachedURLRespons
360360

361361
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request
362362
{
363-
return request;
363+
return request;
364364
}
365365

366366
- (NSCachedURLResponse *)cachedResponse
367367
{
368-
return nil;
368+
return nil;
369+
}
370+
371+
/** Drop certain headers in accordance with
372+
* https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1411532-httpadditionalheaders
373+
*/
374+
- (NSMutableURLRequest *)clearAuthHeadersForRequest:(NSMutableURLRequest *)request {
375+
NSArray* authHeadersToRemove = @[
376+
@"Authorization",
377+
@"Connection",
378+
@"Host",
379+
@"Proxy-Authenticate",
380+
@"Proxy-Authorization",
381+
@"WWW-Authenticate"
382+
];
383+
for (NSString* header in authHeadersToRemove) {
384+
[request setValue:nil forHTTPHeaderField:header];
385+
}
386+
return request;
369387
}
370388

371389
- (void)startLoading
@@ -442,13 +460,16 @@ - (void)startLoading
442460
case 301:
443461
case 302:
444462
case 307:
445-
case 308:
463+
case 308: {
446464
//Preserve the original request method and body, and set the new location URL
447465
mReq = [self.request mutableCopy];
448466
[mReq setURL:redirectLocationURL];
467+
468+
mReq = [self clearAuthHeadersForRequest:mReq];
469+
449470
redirectRequest = (NSURLRequest*)[mReq copy];
450471
break;
451-
472+
}
452473
default:
453474
redirectRequest = [NSURLRequest requestWithURL:redirectLocationURL];
454475
break;

OHHTTPStubs/UnitTests/Test Suites/NSURLSessionTests.m

Lines changed: 67 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)