http4s icon indicating copy to clipboard operation
http4s copied to clipboard

Expect 100-continue support

Open rossabaker opened this issue 4 years ago • 3 comments

From a Matrix question. The basic idea behind Expect is that a request can come with an Expect: 100-continue header, and it's up to the server to respond immediately. If it's not ready to respond immediately, it should respond with a status of 100, and then send a subsequent response.

TODO:

  • [ ] blaze-server
  • [ ] ember-server
  • [ ] blaze-client
  • [ ] ember-client

rossabaker avatar Sep 17 '21 19:09 rossabaker

This is tricky. The "MUST" in the RFC suggests that every service (or at least backend) should be prepared to handle this, but this is the first I recall anybody asking for it. It could be expensive for server backends to parse every request for this header to trigger special handling.

We would like to be able to consult the service to send a >= 200 status code if one is known before we start reading the request body. It's all async, so there's no concept of an immediate response vs. a delayed response, so how can we consult the service and respond immediately if the service needs to think about it? Race against an infintesimal timeout?

We don't have a way to send two responses, so this does require backend support. It could probably be handled by a vault attribute with the secondary response, which would also fit nicely into the race model. Then Expect handling could be done as a middleware, and backends would only need to be aware that they're dealing with a 100.

rossabaker avatar Sep 17 '21 19:09 rossabaker

I think this actually a bug. An HTTP/1.1 origin server "MUST" support this.

I don't think the request attribute is the right approach. If an HttpApp returns the 100 status, it will mess with logging and middleware: the "real" response metrics will be much more interesting.

I think we can maintain this on the backend. If a request has an expect header, we can check the expectation. If it expects a 100-continue, we can race the rendering of the response against an effect that writes the 100 status, and then render the response if it loses.

The client is less clearly a bug, but it "SHOULD" withhold the request body until the 100 response is received or a reasonable interval, and it "SHOULD" retry on 417.

I think all of this can be done binary compatibly.

rossabaker avatar Sep 17 '21 23:09 rossabaker