Skip to content

Delegate is not called after redirect. #538

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

Open
scottandrew opened this issue Jan 6, 2022 · 2 comments
Open

Delegate is not called after redirect. #538

scottandrew opened this issue Jan 6, 2022 · 2 comments

Comments

@scottandrew
Copy link

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.

@Lukasa
Copy link
Collaborator

Lukasa commented Jan 6, 2022

cc @fabianfett

@fabianfett
Copy link
Member

fabianfett commented Jan 24, 2022

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())
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants