1af9dc58a448
encode S3 keys once so repos with spaces sign correctly (3.0.7)
- time
- 2026-09-23 21:40 UTC · 2 weeks ago
- machine
- koh2
- agent
- claude-opus-5-5
- session
- koh 3 review fixes
- parent
- 69c3ac67d7c8
↓ koh-1af9dc58.tar.gzatlas at this save
files changed4 files
VERSION+1 −1src/remote/s3_test.v+8 −2src/remote/sigv4.v+4 −4v.mod+1 −1src/remote/s3_test.v+8 −2
@@ -77,9 +77,15 @@7777 assert parts.host == 's3.fr-par.scw.cloud'7878 assert parts.path == '/bucket/repo/objects/abc'7979 80- // Slashes in the key stay slashes; anything else is encoded.81- spaces := split_url('https://example.com/bucket/a file.txt')80+ // The URL arrives as it will be sent, already encoded: splitting it must81+ // not encode it a second time.82+ spaces := split_url('https://example.com/bucket/a%20file.txt')8283 assert spaces.path == '/bucket/a%20file.txt'84+85+ // A repo named after a folder with a space: the path that is signed is the86+ // path that is sent, encoded once.87+ s3 := new_s3('https://s3.fr-par.scw.cloud', 'bucket', 'fr-par', 'key', 'secret')!88+ assert split_url(s3.url_for('my repo/head', '')).path == '/bucket/my%20repo/head'8389 8490 // An endpoint with a path prefix keeps it.8591 prefixed := split_url('https://example.com/prefix/bucket/key?x=1')src/remote/sigv4.v+4 −4
@@ -91,9 +91,9 @@9191 path string // canonical URI, already encoded9292 }9393 94-// split_url takes a URL apart for the canonical request. The path is encoded95-// here, and the caller builds its URL from these same parts, so the URL the96-// server sees and the URL that was signed cannot drift.94+// split_url takes a URL apart for the canonical request. The URL is the one95+// that will be sent, already encoded by its builder, so its path is signed as96+// it stands: encoding it again would sign `%2520` for a `%20` on the wire.9797 pub fn split_url(url string) UrlParts {9898 mut rest := url9999 if at := rest.index('://') {@@ -110,7 +110,7 @@110110 }111111 return UrlParts{112112 host: host113- path: encode(path, true)113+ path: path114114 }115115 }116116 v.mod+1 −1
@@ -1,6 +1,6 @@11 Module {22 name: 'koh3'3- version: '3.0.6'3+ version: '3.0.7'44 description: 'One SQLite file per repo, one line of history.'55 license: 'MIT'66 }