Skip to content

TRACE: add the missing standard HTTP method - #1325

Open
SSE4 wants to merge 2 commits into
userver-framework:developfrom
SSE4:trace-http-method
Open

SSE4 wants to merge 2 commits into
userver-framework:developfrom
SSE4:trace-http-method

Conversation

@SSE4

@SSE4 SSE4 commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

The problem

server::http::HttpMethod names every method of RFC 9110 except one. TRACE
parses fine — llhttp has known HTTP_TRACE forever — but userver maps it to
kUnknown, and kUnknown is not routable. So:

  • an incoming TRACE / HTTP/1.1 gets a 405 from the routing layer, before
    any of your code runs;
  • putting TRACE in a handler's method: list does not help either — it
    throws at service start, because HttpMethodFromString does not know the
    string.

The result is not "userver denies TRACE by policy", it is "userver cannot
express TRACE at all". There is no opt-in to reach for.

When this is useful

  • Emulating or replacing a legacy backend. This is what I needed it for: a
    test target previously served by nginx that answers TRACE like any other
    request. Without kTrace the userver replacement is not behaviour-compatible.
  • Being a target for security tooling. WAF/scanner test rigs and XST
    (Cross-Site Tracing) checks need a backend that actually answers TRACE;
    a framework-level 405 makes the rig untestable.
  • Debugging a proxy chain. TRACE is the standard "show me what the
    intermediaries did to my request" tool (RFC 9110 §9.3.8). A service that wants
    to implement the loopback echo — or a deliberately trimmed version of it —
    currently cannot, however much it wants to.
  • Interop and conformance suites that expect a definite, handler-controlled
    answer rather than whatever the framework decided on your behalf.

What changes

kTrace is added to the enum, to the string conversions, to the llhttp mapping
and to kHandlerMethods. That is all — it makes TRACE expressible:

handler-something:
    path: /*
    method: GET,POST,TRACE   # used to throw at start; now routes

Default behaviour is unchanged. A handler that does not list TRACE still
answers 405, exactly as today. Nothing becomes reachable by accident, which
matters here: TRACE reflecting a credentialed request is the XST problem, and it
stays a per-handler opt-in.

Deliberately out of scope

The RFC message/http loopback echo. Answering TRACE correctly is the handler's
business, the same way userver does not auto-implement OPTIONS semantics for
you (beyond the explicit implicit-http-options fallback). The framework only
needs to stop being unable to route the method.

The second commit

feat core: allow sending TRACE requests with the HTTP client — mirrors the
addition in clients::http::HttpMethod, so both sides of the framework cover
the same method set and HttpMethodFromString("TRACE") stops throwing on the
client. Separate commit; drop it if you would rather keep the change
server-side only.

Tests

Unit tests for ToString / HttpMethodFromString / IsHandlerMethod, TRACE
added to the HTTP/1.1 parser parametrization, and a functional test in the
http2server suite — HTTP/2 reads the method from the :method pseudo-header
instead of llhttp, so it is a genuinely separate path.

@apolukhin

Copy link
Copy Markdown
Member

LGTM

@robot-magpie

robot-magpie Bot commented Sep 16, 2026

Copy link
Copy Markdown

Many thanks for the PR! @apolukhin is now importing your pull request into our internal upstream repository.

SSE4 added 2 commits October 6, 2026 13:00
TRACE is a standard HTTP method (RFC 9110 9.3.8) that llhttp parses fine,
but server::http::HttpMethod had no value for it: an incoming TRACE was
mapped to kUnknown and routing answered 405, and "TRACE" in a handler
'method:' list threw at service start.

Add kTrace to the enum, to the string conversions, to the llhttp mapping
and to kHandlerMethods, so a handler can register for TRACE and receive
it like any other method. Answering with the RFC message/http loopback
echo stays up to the handler - the framework only needs to be able to
route the method.

HTTP/2 takes the method from the ':method' pseudo-header rather than from
llhttp, so it is covered by a separate functional test.
Mirrors the server-side TRACE support in clients::http::HttpMethod, so
the enum and HttpMethodFromString() cover the same set of methods on both
sides. TRACE carries no request body, so it is sent as a custom request
just like DELETE and OPTIONS.
@SSE4
SSE4 force-pushed the trace-http-method branch from 6b12f5d to b706811 Compare October 6, 2026 06:22

This branch has not been deployed

No deployments
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

Successfully merging this pull request may close these issues.

2 participants