Skip to content
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

proposal: net/http/httpest: add ResponseRecorder.EnableFullDuplex #65120

Open
DavidArchibald opened this issue Jan 16, 2024 · 3 comments
Open
Labels
Milestone

Comments

@DavidArchibald
Copy link

Proposal Details

It can be difficult to test code that expects to be able to use EnableFullDuplex because httptest.(*ResponseRecorder) doesn't implement EnableFullDuplex.

@gopherbot gopherbot added this to the Proposal milestone Jan 16, 2024
@seankhliao seankhliao changed the title proposal: net/http/httpest: consider adding (*ResponseRecorder).EnableFullDuplex proposal: net/http/httpest: add ResponseRecorder.EnableFullDuplex Jan 16, 2024
@ianlancetaylor
Copy link
Contributor

CC @neild

@neild
Copy link
Contributor

neild commented Feb 6, 2024

ResponseRecorder doesn't implement SetReadDeadline or SetWriteDeadline either. Should it implement every possible http.ResponseController method? (Serious question, I don't know the answer.)

It would be trivial to add an EnableFullDuplex method that records its state in a ResponseRecorder.FullDuplex field the way ResponseRecorder.Flush does. I'm not sure this really aids much in testing, however; tests that only verify that a method has been caller are generally pretty low value.

Furthermore, ResponseRecorder is fundamentally a recorder. A full-duplex handler is one where the response is read concurrently with the request being sent. ResponseRecorder doesn't support this use case well, because there's no way to incrementally consume the response body.

I think most full-duplex handlers would be better tested with a httptest.Server, which permits testing the actual handler behavior in a realistic fashion.

@DavidArchibald
Copy link
Author

DavidArchibald commented Feb 9, 2024

I don't personally have useful for SetReadDeadline or SetWriteDeadline. However in my opinion and in terms of consistency it should probably be included if possible.

The main reason why I'm advocating for FullDuplex to be added is because I write endpoints that try to stream part of the body while returning a response simultaneously.

I think most full-duplex handlers would be better tested with a httptest.Server, which permits testing the actual handler behavior in a realistic fashion.

I honestly had thought that httptest.Server was using ResponseRecorder under the hood or something similar. Thank you for fixing that assumption. I ended up switching my code to use httptest.Server but it's more verbose code to do exactly what was happening before; I want to treat the endpoint as a black box and with some request body what is the overall output?

Here's what my code looked like before:

recorder := httptest.NewResponseRecorder()

r := &http.Request{URL: ..., Body: ...}
someHandlerToTest(w, r)

checkResponse(recorder)

And switching it to this is much longer:

s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	handler(w, r)
}))

u, err := url.JoinPath(s.URL, "...")
require.NoError(t, err)

url, err := url.Parse(u)
require.NoError(t, err)

r := &http.Request{URL: url, Body: ...}

resp, err := http.DefaultClient.Do(r)
require.NoError(t, err)

body, err := io.ReadAll(resp.Body)
require.NoError(t, err)

It gets more complicated because of course sending a request to the http.Server is more complicated. You might, like me, seemingly have to use url.JoinPath to get a route and url.Parse to parse it, and then io.ReadAll seems necessary to get the same thing that ResponseRecorder gives with String.

Maybe the simplicity with implementing full duplex on the ResponseRecorder a good enough reason to implement this? But it seems like using httptest.NewServer is a workable solution.

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

No branches or pull requests

4 participants