Skip to content

Improve Expect: 100-continue header handling #135

@yoshuawuyts

Description

@yoshuawuyts

tldr: We're currently always accepting Expect: 100-continue headers, where we should be enabling header validation before we send back an intermediate 100 status code.

Expected behavior

The 100 continue header exists in order to signal to a client that the request has been understood, and all the headers are correct. This enables validating things like encoding, offsets, and authentication before proceeding to transfer a significant amount of data.

The validation of these headers should be defined by end-users, as they are the ones that will know which combination of headers is acceptable.

Current behavior

async-h1 is currently hardcoded to always reply with 100 to the Expect: 100-continue header. This means end-users don't have a chance to validate headers before proceeding.

const EXPECT_HEADER_VALUE: &str = "100-continue";
const EXPECT_RESPONSE: &[u8] = b"HTTP/1.1 100 Continue\r\n\r\n";
async fn handle_100_continue<IO>(req: &Request, io: &mut IO) -> http_types::Result<()>
where
IO: Write + Unpin,
{
if let Some(EXPECT_HEADER_VALUE) = req.header(EXPECT).map(|h| h.as_str()) {
io.write_all(EXPECT_RESPONSE).await?;
}
Ok(())
}

Implementation

We should provide some way for end-users to validate headers before sending back the 100 continue response. I'm not quite sure how to do this, but one option would be to handle only send over 100-continue when the first chunk of the request body is requested. That would indicate that the framework has successfully parsed the headers, and is now ready to receive the body.

If a Response is returned before the Request body has finished, that would likely carry a non-100 status code, and the client would know not to send the request body. So semantically I think that would be the right way to go?

If at all possible I think we should evade exposing the Expect: 100-continue semantics to end-users, since the back and forth dance is quite complex, needs to work out of the box, and doesn't fit well with the req/res model we use in http-rs.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions