in oss/signer/v4.go [109:209]
func (s *SignerV4) calcCanonicalRequest(signingCtx *SigningContext, additionalHeaders []string) string {
request := signingCtx.Request
/*
Canonical Request
HTTP Verb + "\n" +
Canonical URI + "\n" +
Canonical Query String + "\n" +
Canonical Headers + "\n" +
Additional Headers + "\n" +
Hashed PayLoad
*/
//Canonical Uri
uri := "/"
if signingCtx.Bucket != nil {
uri += *signingCtx.Bucket + "/"
}
if signingCtx.Key != nil {
uri += *signingCtx.Key
}
canonicalUri := escapePath(uri, false)
//Canonical Query
query := strings.Replace(request.URL.RawQuery, "+", "%20", -1)
values := make(map[string]string)
var params []string
for query != "" {
var key string
key, query, _ = strings.Cut(query, "&")
if key == "" {
continue
}
key, value, _ := strings.Cut(key, "=")
values[key] = value
params = append(params, key)
}
sort.Strings(params)
var buf strings.Builder
for _, k := range params {
if buf.Len() > 0 {
buf.WriteByte('&')
}
buf.WriteString(k)
if len(values[k]) > 0 {
buf.WriteByte('=')
buf.WriteString(values[k])
}
}
canonicalQuery := buf.String()
//Canonical Headers
var headers []string
buf.Reset()
addHeadersMap := make(map[string]bool)
for _, k := range additionalHeaders {
addHeadersMap[strings.ToLower(k)] = true
}
for k := range request.Header {
lowk := strings.ToLower(k)
if isDefaultSignedHeader(lowk) {
headers = append(headers, lowk)
} else if _, ok := addHeadersMap[lowk]; ok {
headers = append(headers, lowk)
}
}
sort.Strings(headers)
for _, k := range headers {
headerValues := make([]string, len(request.Header.Values(k)))
for i, v := range request.Header.Values(k) {
headerValues[i] = strings.TrimSpace(v)
}
buf.WriteString(k)
buf.WriteString(":")
buf.WriteString(strings.Join(headerValues, ","))
buf.WriteString("\n")
}
canonicalHeaders := buf.String()
//Additional Headers
canonicalAdditionalHeaders := strings.Join(additionalHeaders, ";")
hashPayload := unsignedPayload
if val := request.Header.Get(contentSha256Header); val != "" {
hashPayload = val
}
buf.Reset()
buf.WriteString(request.Method)
buf.WriteString("\n")
buf.WriteString(canonicalUri)
buf.WriteString("\n")
buf.WriteString(canonicalQuery)
buf.WriteString("\n")
buf.WriteString(canonicalHeaders)
buf.WriteString("\n")
buf.WriteString(canonicalAdditionalHeaders)
buf.WriteString("\n")
buf.WriteString(hashPayload)
return buf.String()
}