async-http-client
async-http-client copied to clipboard
Delegate is not called after redirect.
I am trying to read the header of a request that gets redirected. However it seems that the callback is is never called after the redirect. The new request has no reference to the delegate that was passed.
cc @fabianfett
Hi @scottandrew, sorry for taking such a long time to come back to you. I just tried to verify your described behavior and everything worked as expected for me. Can you maybe post the your code, which causes the issue, here, so that I can have a look... Thanks.
Testcode:
func testDelegateMethodsAreInvokedAfterRedirect() {
let web = NIOHTTP1TestServer(group: self.serverGroup)
defer { XCTAssertNoThrow(try web.stop()) }
let httpClient = HTTPClient(eventLoopGroupProvider: .createNew)
defer { XCTAssertNoThrow(try httpClient.syncShutdown()) }
class TestDelegate: HTTPClientResponseDelegate {
typealias Response = ByteBuffer
var headFuture: EventLoopFuture<HTTPResponseHead> {
self.headPromise.futureResult
}
var bodyFuture: EventLoopFuture<ByteBuffer> {
self.bodyPromise.futureResult
}
private var headPromise: EventLoopPromise<HTTPResponseHead>
private var bodyPromise: EventLoopPromise<ByteBuffer>
private var body: ByteBuffer?
init(eventLoop: EventLoop) {
self.headPromise = eventLoop.makePromise(of: HTTPResponseHead.self)
self.bodyPromise = eventLoop.makePromise(of: ByteBuffer.self)
}
func didReceiveHead(task: HTTPClient.Task<Int>, _ head: HTTPResponseHead) -> EventLoopFuture<Void> {
self.headPromise.succeed(head)
return task.eventLoop.makeSucceededVoidFuture()
}
func didReceiveBodyPart(task: HTTPClient.Task<Response>, _ buffer: ByteBuffer) -> EventLoopFuture<Void> {
if self.body == nil {
self.body = buffer
} else {
var buffer = buffer
self.body!.writeBuffer(&buffer)
}
return task.eventLoop.makeSucceededFuture(())
}
func didFinishRequest(task: HTTPClient.Task<Response>) throws -> ByteBuffer {
return self.body ?? ByteBuffer()
}
func didReceiveError(task: HTTPClient.Task<ByteBuffer>, _ error: Error) {
self.headPromise.fail(error)
self.bodyPromise.fail(error)
}
}
let delegate = TestDelegate(eventLoop: httpClient.eventLoopGroup.any())
var maybeRequest: HTTPClient.Request?
XCTAssertNoThrow(maybeRequest = try HTTPClient.Request(url: "http://localhost:\(web.serverPort)/foo"))
guard let request = maybeRequest else { return XCTFail("Expected to have a request here.") }
let responseFuture = httpClient.execute(request: request, delegate: delegate)
XCTAssertNoThrow(try web.receiveHeadAndVerify { received in
let expected = HTTPRequestHead(
version: .http1_1,
method: .GET,
uri: "/foo",
headers: ["Host": "localhost:\(web.serverPort)"]
)
XCTAssertEqual(expected, received)
})
XCTAssertNoThrow(try web.receiveEnd())
let forwardHTTPResponseHead = HTTPResponseHead(
version: .http1_1,
status: .movedPermanently,
headers: ["Location": "http://localhost:\(web.serverPort)/bar"]
)
XCTAssertNoThrow(try web.writeOutbound(.head(forwardHTTPResponseHead)))
XCTAssertNoThrow(try web.writeOutbound(.end(nil)))
XCTAssertNoThrow(try web.receiveHeadAndVerify { received in
let expected = HTTPRequestHead(
version: .http1_1,
method: .GET,
uri: "/bar",
headers: ["Host": "localhost:\(web.serverPort)"]
)
XCTAssertEqual(expected, received)
})
XCTAssertNoThrow(try web.receiveEnd())
let actualResponseHead = HTTPResponseHead(version: .http1_1, status: .ok, headers: ["content-length": "7"])
let actualResponseBody = ByteBuffer(string: "foo bar")
XCTAssertNoThrow(try web.writeOutbound(.head(actualResponseHead)))
XCTAssertNoThrow(try web.writeOutbound(.body(.byteBuffer(actualResponseBody))))
XCTAssertNoThrow(try web.writeOutbound(.end(nil)))
XCTAssertEqual(try delegate.headFuture.wait(), actualResponseHead)
XCTAssertEqual(try delegate.bodyFuture.wait(), actualResponseBody)
XCTAssertNoThrow(try responseFuture.wait())
}