Skip to content
Go back
Envoy

The CNCF-graduated edge and service proxy — the data plane underneath Istio and many API gateways.

HTTP QUERY method support in Envoy

http: add support for the QUERY method (RFC 10008)

Envoy's HTTP/1 codec rejected the new QUERY method that HTTP/2 and HTTP/3 already forwarded. It now routes QUERY the same way on all three, and enforces the RFC's Content-Type rule.

Status
Merged
Merged
24 Aug 2026
Area
HTTP/1 codec · connection manager
C++
Diff
359 lines added and 9 removed across 23 files

The problem

RFC 10008 registers QUERY: a method that is safe and idempotent like GET, but carries its query in the request body rather than the URL. It exists for searches and filters too large or too structured to fit in a query string.

Envoy’s handling of it depended on the protocol version. HTTP/2 and HTTP/3 keep no method allowlist, so they forwarded it. HTTP/1 rejected it with a 400 (HPE_INVALID_METHOD), because the parser checks the method against a fixed list of known methods that predates the RFC. The same request succeeded or failed depending on how the client connected.

The only workaround was allow_custom_methods. It accepts any token as a method, and the API still marks it as work in progress.

What I changed

Unit tests cover the parser, codec, header validator and connection manager. An integration test routes a QUERY through every combination of downstream and upstream protocol.

Judgement calls

QUERY is safe, but not by Envoy’s definition of safe. The RFC defines QUERY as safe, yet I kept it out of isSafeRequest() on purpose. One reviewer questioned the exclusion and another asked how it would interact with 0-RTT early data. Tracing that through the code showed that callers of isSafeRequest() assume a safe request has no body. That function decides whether a request may be sent as 0-RTT early data, and whether a 425 triggers an automatic retry, which for a request with a body means buffering the body. Marking QUERY safe would have changed both behaviours without anyone deciding to. I left a TODO where the function is implemented and a note at each call site, so a later change can’t alter either behaviour by accident.

Only the missing Content-Type is enforced. The RFC also rejects a Content-Type that doesn’t match the body. Checking that would mean buffering and inspecting the content, and only the origin server knows which query formats it supports. A proxy that guessed would do more harm than good, so the code comment says this was deliberate rather than an oversight.

What review changed

Reviewers moved the change closer to the RFC: they asked for the Content-Type rule to be enforced now rather than later, and for the two new header fields to be registered. My first version put the Content-Type check behind a second runtime guard of its own. The reviewers, and then the maintainer, agreed that one flag was enough: the check can only be reached if HTTP/1 accepts QUERY, and that is already guarded. So the second guard came out.

Outcome

Merged on 24 August 2026, closing #46404. It ships in Envoy’s next minor release after v1.39, with a release note under minor behaviour changes.

Timeline

  1. 1 Aug 2026
    Pull request opened
  2. 24 Aug 2026
    Merged after 23 days in review

All open source work →