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

No WAI Response composers work to send HTTP 103 Early Hints #970

Closed
thomasjm opened this issue Jan 9, 2024 · 3 comments
Closed

No WAI Response composers work to send HTTP 103 Early Hints #970

thomasjm opened this issue Jan 9, 2024 · 3 comments

Comments

@thomasjm
Copy link
Contributor

thomasjm commented Jan 9, 2024

I recently landed snoyberg/http-client#524 (CC @snoyberg) provide HTTP 103 Early Hints support in http-client. Now I'm trying to extend this support to http-reverse-proxy, and running into the following problem.

The idea of HTTP 103 Early Hints is that an HTTP server can send an initial HTTP status code of 103, along with some headers. This means "the full response is still processing, but in the meantime here are some things you as a client can do to start preparing for it." Primarily this is for browsers to start pre-fetching assets that will be needed. The server can send multiple 103 Early Hints sections before it concludes with the full response.

The key issue here is, we want to start sending status lines and headers to the client, but we don't know what the final status will be yet! It might be 200, or some error might happen during processing and it might be something else.

All of the higher-level Response composers in WAI expect a Status up front: responseFile, responseBuilder, responseLbs, and even responseStream. (This last one works only for streaming the body, not the status lines/headers.)

This leaves only responseRaw. I've tried to use this to implement the reverse proxy here, but it doesn't quite work. My attempt actually sends the 103 Early Hints section, but then closes the connection prematurely. I think this is because responseRaw is mainly intended for WebSocket upgrades, and has this line in its documentation:

In the event that you read from the request body before returning a responseRaw, behavior is undefined.

This undefined behavior is inconsistent with using responseRaw as part of a reverse proxy.

I think to fix this, WAI needs a new response composer, maybe a different flavor of responseRaw. Note that the current responseRaw also provides a function to read bytes from the client, which we don't need for this application. Presumably a version without this wouldn't have the undefined behavior issue.

@kazu-yamamoto
Copy link
Contributor

The idea of early hints was proposed by a friend of mine and it was standardized by another friend.
So, I definitely supports this. :-)

@thomasjm Could you implement a prototype so that we can discuss how this feature should be provided?

@thomasjm
Copy link
Contributor Author

thomasjm commented Jan 9, 2024

Sure, I can try. Let me note a few possible problems/breaking changes I foresee:

  • responseStatus :: Response -> H.Status and responseHeaders :: Response -> H.ResponseHeaders: these functions may need to go away or become partial, since the status and headers won't necessarily be known at response construction time.
  • Same for responseToStream, mapResponseHeaders, mapResponseStatus. These functions could potentially still work if they change to return IO rather than a pure return type.

I started sketching out a solution here. This has an API that works for the http-reverse-proxy use-case. However, I'm still running into the issue where the client gets the early headers back and then the connection closes prematurely.

I'm not totally sure why this happens. Could it be the case that once you finish reading the full body of the request, and then do a connSendAll on the connection, it causes the connection to be closed right away? I could use some insight from a Warp expert :)

My work on http-reverse-proxy with the new WAI prototype API can be found here.

@thomasjm
Copy link
Contributor Author

Never mind, I actually got it to work with responseRaw. I think this will still work, although I'm still uncertain about the implications of the "behavior is undefined" thing. If you could shed any light on that it would be appreciated.

Anyway, I've got the tests passing now and opened fpco/http-reverse-proxy#46 !

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

2 participants