diff --git a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClient+execute.swift b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClient+execute.swift index 6c45a590b..f2680107a 100644 --- a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClient+execute.swift +++ b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClient+execute.swift @@ -75,7 +75,11 @@ extension HTTPClient { try redirectState.redirect(to: redirectURL.absoluteString) currentRedirectState = redirectState - let newRequest = preparedRequest.followingRedirect(to: redirectURL, status: response.status) + let newRequest = currentRequest.followingRedirect( + from: preparedRequest.url, + to: redirectURL, + status: response.status + ) guard newRequest.body.canBeConsumedMultipleTimes else { // we already send the request body and it cannot be send again diff --git a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientRequest+Prepared.swift b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientRequest+Prepared.swift index 7899588e1..bb7659a86 100644 --- a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientRequest+Prepared.swift +++ b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientRequest+Prepared.swift @@ -75,12 +75,16 @@ extension RequestBodyLength { } @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) -extension HTTPClientRequest.Prepared { - func followingRedirect(to redirectURL: URL, status: HTTPResponseStatus) -> HTTPClientRequest { +extension HTTPClientRequest { + func followingRedirect( + from originalURL: URL, + to redirectURL: URL, + status: HTTPResponseStatus + ) -> HTTPClientRequest { let (method, headers, body) = transformRequestForRedirect( - from: self.url, - method: self.head.method, - headers: self.head.headers, + from: originalURL, + method: self.method, + headers: self.headers, body: self.body, to: redirectURL, status: status diff --git a/Tests/AsyncHTTPClientTests/AsyncAwaitEndToEndTests+XCTest.swift b/Tests/AsyncHTTPClientTests/AsyncAwaitEndToEndTests+XCTest.swift index 77b374196..18356698c 100644 --- a/Tests/AsyncHTTPClientTests/AsyncAwaitEndToEndTests+XCTest.swift +++ b/Tests/AsyncHTTPClientTests/AsyncAwaitEndToEndTests+XCTest.swift @@ -39,6 +39,7 @@ extension AsyncAwaitEndToEndTests { ("testDeadline", testDeadline), ("testImmediateDeadline", testImmediateDeadline), ("testInvalidURL", testInvalidURL), + ("testRedirectChangesHostHeader", testRedirectChangesHostHeader), ] } } diff --git a/Tests/AsyncHTTPClientTests/AsyncAwaitEndToEndTests.swift b/Tests/AsyncHTTPClientTests/AsyncAwaitEndToEndTests.swift index 314695e97..906bdaffa 100644 --- a/Tests/AsyncHTTPClientTests/AsyncAwaitEndToEndTests.swift +++ b/Tests/AsyncHTTPClientTests/AsyncAwaitEndToEndTests.swift @@ -400,6 +400,35 @@ final class AsyncAwaitEndToEndTests: XCTestCase { } #endif } + + func testRedirectChangesHostHeader() { + #if compiler(>=5.5) && canImport(_Concurrency) + guard #available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *) else { return } + XCTAsyncTest { + let bin = HTTPBin(.http2(compress: false)) + defer { XCTAssertNoThrow(try bin.shutdown()) } + let client = makeDefaultHTTPClient() + defer { XCTAssertNoThrow(try client.syncShutdown()) } + let logger = Logger(label: "HTTPClient", factory: StreamLogHandler.standardOutput(label:)) + var request = HTTPClientRequest(url: "https://127.0.0.1:\(bin.port)/redirect/target") + request.headers.replaceOrAdd(name: "X-Target-Redirect-URL", value: "https://localhost:\(bin.port)/echohostheader") + + guard let response = await XCTAssertNoThrowWithResult( + try await client.execute(request, deadline: .now() + .seconds(10), logger: logger) + ) else { + return + } + guard let body = await XCTAssertNoThrowWithResult(try await response.body.collect()) else { return } + var maybeRequestInfo: RequestInfo? + XCTAssertNoThrow(maybeRequestInfo = try JSONDecoder().decode(RequestInfo.self, from: body)) + guard let requestInfo = maybeRequestInfo else { return } + + XCTAssertEqual(response.status, .ok) + XCTAssertEqual(response.version, .http2) + XCTAssertEqual(requestInfo.data, "localhost:\(bin.port)") + } + #endif + } } #if compiler(>=5.5.2) && canImport(_Concurrency)