pjfanning opened a new pull request, #1280:
URL: https://github.com/apache/pekko-http/pull/1280

   ### Motivation
   
   Refs #1273.
   
   That issue asks for a way to send a request whose path renders exactly as 
provided, because `Uri` cannot round-trip a percent-encoded path — it decodes 
segments when parsing and re-encodes them with the `pchar-base` keep-set, which 
leaves sub-delims raw, so `%2B` renders back as `+`. AWS SigV4 signs the 
encoded path, so an S3 object key containing `+` or `=` is rejected with 
`SignatureDoesNotMatch` after the round trip.
   
   While investigating I found the issue's premise is only half right. The 
escape hatch it proposes (option 2, "a pre-rendered request target that the 
client renderer honors") **already exists for HTTP/1.1**: 
`HttpRequestRendererFactory` special-cases a `Raw-Request-URI` header and emits 
it verbatim as the request target. It is a `SyntheticHeader`, so it is not also 
rendered as a header line; it is covered by tests in `RequestRendererSpec` and 
documented under "synthetic headers" in `http-model.md`, whose example is 
literally an S3 path.
   
   What is genuinely missing is HTTP/2. `RequestRendering.initialHeaderPairs` 
built `:path` from `request.uri.toHttpRequestTargetOriginForm` unconditionally 
and ignored the header, so the same `HttpRequest` produced a different request 
target depending on which protocol was negotiated.
   
   ### Modification
   
   Take `Raw-Request-URI` into account when building `:path`, mirroring 
HTTP/1.1.
   
   The header needs no new suppression logic: being a `SyntheticHeader` it was 
already excluded from the rendered header block by the existing 
`renderInRequests` filter, so it was silently dropped rather than mis-sent. As 
in HTTP/1.1, the value is used exactly as given — supplying a valid origin-form 
target is the caller's responsibility, and this is stated in the docs.
   
   Also documents, in the existing synthetic-headers section of 
`http-model.md`, that the header is honoured by both clients, why it is needed 
(the `Uri` round-trip loss), and the SigV4 case.
   
   ### Result
   
   `aws-spi-pekko-http`, and any proxy or pass-through use case that must not 
alter the request target, can pass `SdkHttpRequest.encodedPath()` through 
unchanged over HTTP/2 as well as HTTP/1.1.
   
   This does not change the `Uri` model, so the round-trip limitation described 
in #1273 remains as such; it makes the existing escape hatch work uniformly 
across protocols. I'd suggest #1273 stays open if a raw `Uri.Path` 
representation is still wanted — that is a much larger change, since `Path` is 
a sealed ADT matched exhaustively across the codebase and in user code.
   
   ### Tests
   
   Two cases added to `Http2ClientSpec`:
   
   - a request carrying `Raw-Request-URI("/a%2Bb%20c")` sends that value as 
`:path`. The assertion compares the whole pseudo/header set, so it also pins 
that the header itself is not rendered. Verified this fails on `main` — `:path` 
comes out as `/a+b%20c` — and passes with the change.
   - without the header, the path is still re-encoded from the `Uri`. This one 
passes both before and after; it is a characterization test that pins the 
round-trip loss (`/a%2Bb%20c` in, `/a+b%20c` out) which motivates the escape 
hatch.
   
   `sbt "http2-tests/testOnly *Http2ClientSpec *Http2ClientServerSpec 
*Http2PersistentClientSpec *Http2ServerSpec"` — 183 pass. `sbt 
http-core/mimaReportBinaryIssues` — clean (the change is confined to an 
`@InternalApi private[http2]` class). Native `scalafmt` clean.
   
   ### References
   
   Refs #1273.
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to