Stream: git-wasmtime

Topic: wasmtime / PR #14432 serve: answer 400, not 500, for an H...


view this post on Zulip Wasmtime GitHub notifications bot (Sep 26 2026 at 17:46):

xia-chao opened PR #14432 from xia-chao:serve-host-400 to bytecodealliance:main:

wasmtime serve returns 500 when an HTTP/1.1 request has no Host header.
RFC 9112 section 3.2 says it should be a 400, so this changes it to that.
Only the status code changes; whether such a request should be refused at all
was settled in #8923 and is left alone.

view this post on Zulip Wasmtime GitHub notifications bot (Sep 26 2026 at 17:46):

xia-chao requested pchickey for a review on PR #14432.

view this post on Zulip Wasmtime GitHub notifications bot (Sep 26 2026 at 17:46):

xia-chao requested wasmtime-core-reviewers for a review on PR #14432.

view this post on Zulip Wasmtime GitHub notifications bot (Sep 26 2026 at 17:50):

xia-chao edited PR #14432:

wasmtime serve returns 500 when an HTTP/1.1 request has no Host header.
RFC 9112 section 3.2 says it should be a 400, so this changes it to that.
Only the status code changes; whether such a request should be refused at all
was settled in #8923

view this post on Zulip Wasmtime GitHub notifications bot (Sep 26 2026 at 18:54):

xia-chao updated PR #14432.

view this post on Zulip Wasmtime GitHub notifications bot (Sep 28 2026 at 18:41):

:repeat: pchickey submitted PR review:

I think this comes down to an architectural decision for whether the guest or host code is responsible for enforcing the RFC invariant. De facto in this implementation, if hyper didn't enforce an RFC invariant, then it would be up to the guest to enforce it. That's not a principled decision, it was just the way things shook out, and other hosts very likely end up handling broken RFC invariants differently than the exact way hyper handles them.

So, we could enforce this particular RFC invariant here, but then the questions are:

  1. why, exactly, do we not enforce it for p3? The comment here doesn't make sense to me, because in p2 the guest is also capable of observing whether authority is none.
  2. what other RFC invariants is our implementation not enforcing in the host? Do we add them all here?
  3. What from this do we need to feed into specification of the wasi-http implementation?

Want to call this out to other maintainers here, cc @lann

view this post on Zulip Wasmtime GitHub notifications bot (Sep 28 2026 at 19:06):

lann commented on PR #14432:

If new_incoming_request is going to validate host/authority presence then by spec it should be returning a 400. Pragmatically I'm not sure where that would make a difference.

view this post on Zulip Wasmtime GitHub notifications bot (Sep 28 2026 at 19:12):

xia-chao commented on PR #14432:

Fair — the comment was wrong. I tested both worlds: the proxy path already fails on a Host-less request, we just turned the 500 into a 400. The service path doesn't fail, it just never gets the host. Happy to look into that instead if you'd rather.

view this post on Zulip Wasmtime GitHub notifications bot (Sep 28 2026 at 19:12):

xia-chao edited a comment on PR #14432:

Fair — the comment was wrong. I tested both worlds: the proxy path already fails on a Host-less request, we just turned the 500 into a 400. The service path doesn't fail, it just never gets the host.

view this post on Zulip Wasmtime GitHub notifications bot (Sep 28 2026 at 19:13):

xia-chao commented on PR #14432:

though it also can't see the host at all. Should I drop this, or dig into that?

view this post on Zulip Wasmtime GitHub notifications bot (Sep 28 2026 at 19:16):

xia-chao edited a comment on PR #14432:

Should I drop this, or dig into that?

view this post on Zulip Wasmtime GitHub notifications bot (Sep 28 2026 at 19:31):

lann commented on PR #14432:

Could you say more about your motivation for this change?

view this post on Zulip Wasmtime GitHub notifications bot (Sep 28 2026 at 19:34):

xia-chao commented on PR #14432:

RFC 9112 §3.2 says an HTTP/1.1 request without Host must get 400, and §3.3 lets the server reject an empty authority, so rejecting is fine — ours just surfaces as a 500 with "worker trapped or panicked", which reads as our bug. Only the status code changes.

view this post on Zulip Wasmtime GitHub notifications bot (Sep 28 2026 at 19:41):

pchickey commented on PR #14432:

@xia-chao Its possible to modify your guest code to give the correct status, correct?

view this post on Zulip Wasmtime GitHub notifications bot (Sep 28 2026 at 19:42):

lann commented on PR #14432:

@xia-chao Its possible to modify your guest code to give the correct status, correct?

No, that's the whole problem. wasmtime-wasi-http bails before it gets to the guest: https://github.com/bytecodealliance/wasmtime/blob/1bc343e789c52f09e8a511605e6adc1559bc09d2/crates/wasi-http/src/p2/types.rs#L92

view this post on Zulip Wasmtime GitHub notifications bot (Sep 28 2026 at 19:45):

xia-chao commented on PR #14432:

No — the host rejects it before the guest runs: "invalid HTTP request missing authority in URI and host header". A duplicate or invalid Host does reach the guest.

view this post on Zulip Wasmtime GitHub notifications bot (Sep 28 2026 at 19:48):

xia-chao deleted a comment on PR #14432:

Should I drop this, or dig into that?

view this post on Zulip Wasmtime GitHub notifications bot (Sep 28 2026 at 19:51):

lann edited a comment on PR #14432:

@xia-chao Its possible to modify your guest code to give the correct status, correct?

No, that's the whole problem; wasmtime-wasi-http bails before it gets to the guest: https://github.com/bytecodealliance/wasmtime/blob/1bc343e789c52f09e8a511605e6adc1559bc09d2/crates/wasi-http/src/p2/types.rs#L92

view this post on Zulip Wasmtime GitHub notifications bot (Sep 28 2026 at 19:56):

xia-chao commented on PR #14432:

It's a bug, not a preference.

view this post on Zulip Wasmtime GitHub notifications bot (Sep 28 2026 at 21:28):

pchickey commented on PR #14432:

OK, I apologize, I missed that, now I understand what both of you are saying.

We don't want to duplicate the logic of detecting this 400 Bad Request. Instead, we should change the place the bad request is detected to also include what status code Wasmtime serve should respond with. So, instead of this patch, the architecture I'd like to see is:

  1. add a pub struct ErrorResponse { status: StatusCode } impl ErrorResponse { pub fn new(status: HttpStatusCode) -> Self {...} pub fn status(&self) -> StatusCode {...} } to wasmtime-wasi-http, with derive Debug, impls Display ("error response: {}"), and impl std::error::Error. This struct has opaque fields so that we can extend it in the future with more, if applicable.
  2. change the bail linked to have, additionally, .context(ErrorResponse::new(StatusCode::BAD_REQUEST))
  3. in the Err case handler in wasmtime-cli's serve.rs, try to downcast the error to an ErrorResponse and get the status, with a default to 500 if the downcast fails. Put that status that into the status code of the response, as well as the html response body. The current hard-coded 500 response body should become a template. Use https://docs.rs/http/latest/http/status/struct.StatusCode.html#method.canonical_reason for the non-numeric description.

view this post on Zulip Wasmtime GitHub notifications bot (Sep 28 2026 at 22:51):

pchickey edited a comment on PR #14432:

OK, I apologize, I missed that, now I understand what both of you are saying.

We don't want to duplicate the logic of detecting this 400 Bad Request. Instead, we should change the place the bad request is detected to also include what status code Wasmtime serve should respond with. So, instead of this patch, the architecture I'd like to see is:

  1. add a pub struct ErrorResponse { status: StatusCode } impl ErrorResponse { pub fn new(status: StatusCode) -> Self {...} pub fn status(&self) -> StatusCode {...} } to wasmtime-wasi-http, with derive Debug, impls Display ("error response: {}"), and impl std::error::Error. This struct has opaque fields so that we can extend it in the future with more, if applicable.
  2. change the bail linked to have, additionally, .context(ErrorResponse::new(StatusCode::BAD_REQUEST))
  3. in the Err case handler in wasmtime-cli's serve.rs, try to downcast the error to an ErrorResponse and get the status, with a default to 500 if the downcast fails. Put that status that into the status code of the response, as well as the html response body. The current hard-coded 500 response body should become a template. Use https://docs.rs/http/latest/http/status/struct.StatusCode.html#method.canonical_reason for the non-numeric description.

Last updated: Oct 11 2026 at 04:10 UTC