Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 49 additions & 2 deletions data.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,9 +337,14 @@ func (r Request) String() string {
// http://localhost/http://example.com/image.jpg
func NewRequest(r *http.Request, baseURL *url.URL) (*Request, error) {
var err error
var additionalQuery string
req := &Request{Original: r}

path := r.URL.EscapedPath()[1:] // strip leading slash
path := r.URL.EscapedPath()[1:] // strip leading slash
decodedPath, err, additionalQuery := decodeURL(path) // Conditionally decode url path param if it is url encoded this enables us to process image urls with query params built in
if err == nil {
path = decodedPath
}
req.URL, err = parseURL(path)
if err != nil || !req.URL.IsAbs() {
// first segment should be options
Expand Down Expand Up @@ -370,7 +375,7 @@ func NewRequest(r *http.Request, baseURL *url.URL) (*Request, error) {
}

// query string is always part of the remote URL
req.URL.RawQuery = r.URL.RawQuery
req.URL.RawQuery = combineQueries(r.URL.RawQuery, additionalQuery)
return req, nil
}

Expand All @@ -382,3 +387,45 @@ func parseURL(s string) (*url.URL, error) {
s = reCleanedURL.ReplaceAllString(s, "$1://$2")
return url.Parse(s)
}

var reIsEncodedUrl = regexp.MustCompile(`^https?%`)

func decodeURL(s string) (string, error, string) {
var startsWithHttp = strings.HasPrefix(s, "http")
var prefix = ""
var u = s

if !startsWithHttp && strings.Contains(s, "http") {
var parts = strings.SplitN(s, "http", 2)
u = "http" + parts[1]
prefix = parts[0]
}

var isUrlEncoded = reIsEncodedUrl.MatchString(u)

if isUrlEncoded {
u, err := url.QueryUnescape(u)
if err != nil {
return u, err, ""
}

var parsed, err2 = url.Parse(u)
if err2 != nil {
return u, err2, ""
}

return prefix + u, err2, parsed.RawQuery
} else {
return s, nil, ""
}
}

func combineQueries(a string, b string) string {
if a == "" {
return b
} else if b == "" {
return a
} else {
return a + "&" + b
}
}
37 changes: 37 additions & 0 deletions data_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,43 @@ func TestNewRequest(t *testing.T) {
"http://localhost/http://example.com/%2C",
"http://example.com/%2C", emptyOptions, false,
},
// URI Encoded cases
{
"http://localhost/1x2/http%3A%2F%2Fexample.com%2Ffoo",
"http://example.com/foo", Options{Width: 1, Height: 2}, false,
},
{
"http://localhost/1x2/http%3A%2F%2Fexample.com%2Fhttp%2Fstuff",
"http://example.com/http/stuff", Options{Width: 1, Height: 2}, false,
},
{
"http://localhost/http%3A%2F%2Fexample.com%2Ffoo",
"http://example.com/foo", emptyOptions, false,
},
{
"http://localhost/http%3A%2F%2Fexample.com%2Ffoo",
"http://example.com/foo", emptyOptions, false,
},
{
"http://localhost/http%3A%2Fexample.com%2Ffoo",
"http://example.com/foo", emptyOptions, false,
},
{
"http://localhost/http%3A%2F%2F%2Fexample.com%2Ffoo",
"http://example.com/foo", emptyOptions, false,
},
{
"http://localhost//http%3A%2F%2Fexample.com%2Ffoo",
"http://example.com/foo", emptyOptions, false,
},
{
"http://localhost/http%3A%2F%2Fexample.com%2Ffoo%3Ftest%3D1%26test%3D2",
"http://example.com/foo?test=1&test=2", emptyOptions, false,
},
{
"http://localhost/1x2/http%3A%2F%2Fexample.com%2Ffoo%3Ftest%3D1%26test%3D2",
"http://example.com/foo?test=1&test=2", Options{Width: 1, Height: 2}, false,
},
}

for _, tt := range tests {
Expand Down