Skip to content

SR-13028: URLSession does not call willPerformHTTPRedirection #2974

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -460,8 +460,8 @@ internal class _HTTPURLProtocol: _NativeProtocol {
}

guard let session = task?.session as? URLSession else { fatalError() }
switch session.behaviour(for: task!) {
case .taskDelegate(let delegate):

if let delegate = session.delegate as? URLSessionTaskDelegate {
// At this point we need to change the internal state to note
// that we're waiting for the delegate to call the completion
// handler. Then we'll call the delegate callback
Expand All @@ -471,7 +471,6 @@ internal class _HTTPURLProtocol: _NativeProtocol {

//TODO: Should the `public response: URLResponse` property be updated
// before we call delegate API

self.internalState = .waitingForRedirectCompletionHandler(response: response, bodyDataDrain: bodyDataDrain)
// We need this ugly cast in order to be able to support `URLSessionTask.init()`
session.delegateQueue.addOperation {
Expand All @@ -482,7 +481,7 @@ internal class _HTTPURLProtocol: _NativeProtocol {
}
}
}
case .noDelegate, .dataCompletionHandler, .downloadCompletionHandler:
} else {
// Follow the redirect. Need to configure new request with cookies, etc.
let configuredRequest = session._configuration.configure(request: request)
task?.knownBody = URLSessionTask._Body.none
Expand Down
27 changes: 27 additions & 0 deletions Tests/Foundation/Tests/TestURLSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,32 @@ class TestURLSession: LoopbackServerTest {
}
}

func test_willPerformRedirect() throws {
let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/redirect/1"
let url = try XCTUnwrap(URL(string: urlString))
let redirectURL = try XCTUnwrap(URL(string: "http://127.0.0.1:\(TestURLSession.serverPort)/jsonBody"))
let delegate = SessionDelegate()
let session = URLSession(configuration: .default, delegate: delegate, delegateQueue: nil)
let expect = expectation(description: "GET \(urlString)")

let task = session.dataTask(with: url) { (data, response, error) in
defer { expect.fulfill() }
XCTAssertNil(error)
XCTAssertNotNil(data)
XCTAssertNotNil(response)
XCTAssertEqual(delegate.redirectionRequest?.url, redirectURL)

let callBacks = [
"urlSession(_:task:willPerformHTTPRedirection:newRequest:completionHandler:)",
]
XCTAssertEqual(delegate.callbacks.count, callBacks.count)
XCTAssertEqual(delegate.callbacks, callBacks)
}

task.resume()
waitForExpectations(timeout: 5)
}

func test_httpNotFound() throws {
let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/404"
let url = try XCTUnwrap(URL(string: urlString))
Expand Down Expand Up @@ -1812,6 +1838,7 @@ class TestURLSession: LoopbackServerTest {
("test_httpRedirectionTimeout", test_httpRedirectionTimeout),
("test_httpRedirectionChainInheritsTimeoutInterval", test_httpRedirectionChainInheritsTimeoutInterval),
("test_httpRedirectionExceededMaxRedirects", test_httpRedirectionExceededMaxRedirects),
("test_willPerformRedirect", test_willPerformRedirect),
("test_httpNotFound", test_httpNotFound),
/* ⚠️ */ ("test_http0_9SimpleResponses", testExpectedToFail(test_http0_9SimpleResponses, "Breaks on Ubunut20.04")),
("test_outOfRangeButCorrectlyFormattedHTTPCode", test_outOfRangeButCorrectlyFormattedHTTPCode),
Expand Down