Uri cannot preserve percent-encoded path segments, breaking AWS SigV4 in aws-spi-pekko-http

未关闭
#1,273 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

还没有人认领这个 Issue。

评估

难度
5/5
预计耗时
一周以上
新手友好度
45/100
Issue 类型
功能
描述清晰度
基本清楚
活跃度
活跃
技术栈
aws, scala
领域
networking

调研方向

从 UriParser 和 Uri.scala 开始,重点查看 renderPath 和 encode,以追踪百分号编码的路径段在哪里被解码或重新编码。然后检查 HttpRequest 渲染器以及 aws-spi-pekko-http 对 SdkHttpRequest 的使用。完成的标准是 SDK 的 encodedPath 可以以逐字节相同的形式到达 wire,包括已编码的 pchar 字符和字面百分号。

由索引模型根据 Issue 内容生成。

描述

Problem

Uri cannot round-trip a percent-encoded path. Parsing decodes %XX triplets in path segments (UriParser), and UriRendering.renderPath re-encodes segments with the pchar-base keep-set ("pchar without percent"). Two consequences:

  • A percent-encoded pchar character can never be rendered back in encoded form: %2B becomes +, %3D becomes =, etc. (sub-delims, : and @ are kept raw by the renderer).
  • A literal % in a Path segment is always re-encoded to %25, so constructing Uri.Path from the still-encoded string does not work either.
Uri("https://b.s3.amazonaws.com/a%2Bb%20c%3Dx/d?x=%2B7&y=a+b").toString
// https://b.s3.amazonaws.com/a+b%20c=x/d?x=%2B7&y=a+b

The query is preserved verbatim via rawQueryString; the path is not. There is no raw-path escape hatch in the Uri model or the client request renderer, so no downstream construction can produce a byte-identical request target.

Why it matters

pekko-connectors aws-spi-pekko-http implements the AWS SDK async HTTP client SPI with Http().singleRequest. The SDK signs the request (SigV4) with the URI-encoded path it built, e.g. /a%2Bb for S3 object key a+b; the transport must send that path byte-identically. After the Uri round trip the wire path is /a+b, and S3 — which verifies the signature against the path as received, without normalization — rejects the request with SignatureDoesNotMatch. Any S3 object key containing sub-delims characters (+ = ! ( ) , ; ' & $ @ : *) is affected. The same applies to any proxy/pass-through use case that must not alter the request target.

Proposal

Add a way to send a request whose path renders exactly as provided. Options, roughly in order of preference:

  1. A raw Uri.Path representation (e.g. a segment/path variant flagged as already-encoded) that renderPath emits verbatim.
  2. An HttpRequest attribute carrying a pre-rendered request target that the client renderer honors (analogous in spirit to the server-side raw-request-uri-header).

With either, aws-spi-pekko-http can pass SdkHttpRequest.encodedPath() through untouched.

References
  • UriParser percent-decodes matched strings when a % was seen.
  • Uri.scala renderPath/encode: keep-set is pchar-base (excludes %), so encoded pchars are irrecoverable and literal % double-encodes.
主要语言
Scala
星标
198
派生
56
平均合并
2 天 2 小时
30 天内合并 PR
55

环境准备

  • 没有 Dockerfile 或 Docker Compose 文件
  • 没有 Pull Request 模板
  • 阅读贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

apache/pekko-http 的其他 Issue

查看 apache/pekko-http 的全部 Issue

相似的 Issue

更多 Scala Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。