Files
seaweedfs/weed/util/http/query_middleware.go
T
Chris LuandGitHub 76ec1d8f0f s3: accept raw semicolons in query strings (#10305)
* s3: accept raw semicolons in query strings

Go's url.ParseQuery drops any key=value pair containing a raw ';'. A
presigned PUT that signs content-type carries
X-Amz-SignedHeaders=content-type%3Bhost; when a client or proxy decodes
the %3B, the parameter vanished and the upload failed with
MissingFields, while AWS accepts the raw ';' as query data. Re-encode
it before routing so the pair survives parsing and signature
verification.

* iam, iceberg: recover raw-semicolon query pairs on the other listeners

The standalone IAM API verifies SigV4 with a canonical query recomputed
from the parsed query, and Iceberg REST warehouse/parent values may
legally contain ';'. Move the normalization middleware to util/http and
attach it to both routers.
2026-07-10 12:17:35 -07:00

26 lines
771 B
Go

package http
import (
"net/http"
"strings"
)
// EscapeSemicolonsInQuery re-encodes raw ';' in the query string. RFC 3986
// allows ';' in a query and AWS treats it as data, but Go's url.ParseQuery
// drops every key=value pair containing one. Presigned URLs carry
// X-Amz-SignedHeaders=content-type%3Bhost; clients that decode the %3B would
// otherwise lose the parameter entirely and fail signature verification.
func EscapeSemicolonsInQuery(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if strings.Contains(r.URL.RawQuery, ";") {
u := *r.URL
u.RawQuery = strings.ReplaceAll(u.RawQuery, ";", "%3B")
r2 := new(http.Request)
*r2 = *r
r2.URL = &u
r = r2
}
next.ServeHTTP(w, r)
})
}