Skip to content

Commit

Permalink
Support duplicate URL parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
Acconut committed Nov 25, 2024
1 parent b16a03e commit 1715f5e
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 15 deletions.
21 changes: 11 additions & 10 deletions transloadit.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ type SignedSmartCDNUrlOptions struct {
// Input value that is provided as `${fields.input}` in the template
Input string
// Additional parameters for the URL query string. Can be nil.
URLParams map[string]string
URLParams url.Values
// Expiration time of the signature in milliseconds. Defaults to 1 hour.
ExpiresIn int64
}
Expand All @@ -269,14 +269,13 @@ func (client *Client) CreateSignedSmartCDNUrl(opts SignedSmartCDNUrlOptions) str
expiresIn = int64(time.Hour.Seconds() * 1000) // 1 hour
}

// Convert URLParams to url.Values
queryParams := make(map[string]string, len(opts.URLParams)+2)
for key, value := range opts.URLParams {
queryParams[key] = value
queryParams := make(url.Values, len(opts.URLParams)+2)
for key, values := range opts.URLParams {
queryParams[key] = values
}

queryParams["auth_key"] = client.config.AuthKey
queryParams["exp"] = fmt.Sprintf("%d", (now().Unix()*1000)+expiresIn)
queryParams.Set("auth_key", client.config.AuthKey)
queryParams.Set("exp", fmt.Sprintf("%d", (now().Unix()*1000)+expiresIn))

// Build query string with sorted keys
queryParamsKeys := make([]string, 0, len(queryParams))
Expand All @@ -287,7 +286,9 @@ func (client *Client) CreateSignedSmartCDNUrl(opts SignedSmartCDNUrlOptions) str

var queryParts []string
for _, k := range queryParamsKeys {
queryParts = append(queryParts, url.QueryEscape(k)+"="+url.QueryEscape(queryParams[k]))
for _, v := range queryParams[k] {
queryParts = append(queryParts, url.QueryEscape(k)+"="+url.QueryEscape(v))
}
}
queryString := strings.Join(queryParts, "&")

Expand All @@ -296,9 +297,9 @@ func (client *Client) CreateSignedSmartCDNUrl(opts SignedSmartCDNUrlOptions) str
// Create signature using SHA-256
hash := hmac.New(sha256.New, []byte(client.config.AuthSecret))
hash.Write([]byte(stringToSign))
signature := hex.EncodeToString(hash.Sum(nil))
signature := url.QueryEscape("sha256:" + hex.EncodeToString(hash.Sum(nil)))

signedURL := fmt.Sprintf("https://%s.tlcdn.com/%s/%s?%s&sig=sha256:%s",
signedURL := fmt.Sprintf("https://%s.tlcdn.com/%s/%s?%s&sig=%s",
workspaceSlug, templateSlug, inputField, queryString, signature)

return signedURL
Expand Down
13 changes: 8 additions & 5 deletions transloadit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"math/rand"
"net/url"
"os"
"strings"
"testing"
Expand Down Expand Up @@ -135,17 +136,19 @@ func TestCreateSignedSmartCDNUrl(t *testing.T) {
AuthSecret: "foo_secret",
})

params := url.Values{}
params.Add("foo", "bar")
params.Add("aaa", "42") // This must be sorted before `foo`
params.Add("aaa", "21")

url := client.CreateSignedSmartCDNUrl(SignedSmartCDNUrlOptions{
Workspace: "foo_workspace",
Template: "foo_template",
Input: "foo/input",
URLParams: map[string]string{
"foo": "bar",
"aaa": "42", // This must be sorted as the first parameter.
},
URLParams: params,
})

expected := "https://foo_workspace.tlcdn.com/foo_template/foo%2Finput?aaa=42&auth_key=foo_key&exp=1714525200000&foo=bar&sig=sha256:995dd1aae135fb77fa98b0e6946bd9768e0443a6028eba0361c03807e8fb68a5"
expected := "https://foo_workspace.tlcdn.com/foo_template/foo%2Finput?aaa=42&aaa=21&auth_key=foo_key&exp=1714525200000&foo=bar&sig=sha256%3A9a8df3bb28eea621b46ec808a250b7903b2546be7e66c048956d4f30b8da7519"

if url != expected {
t.Errorf("Expected URL:\n%s\nGot:\n%s", expected, url)
Expand Down

0 comments on commit 1715f5e

Please sign in to comment.