handle 'cleaned' remote URLs

If imageproxy runs behind an http.ServeMux or certain web servers, the
double slash in the remote URL will get collapsed down to a single
slash.  (e.g. http://example.com/ becomes http:/example.com/).  This
is now handled by imageproxy directly.

Ref #65
This commit is contained in:
Will Norris 2016-05-26 13:22:17 -07:00
parent a71584a63c
commit a1af9aa8e2
3 changed files with 10 additions and 4 deletions

View file

@ -19,6 +19,7 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"net/url" "net/url"
"regexp"
"strconv" "strconv"
"strings" "strings"
) )
@ -221,6 +222,10 @@ func (r Request) String() string {
return u.String() return u.String()
} }
// reCleanedURL matches an absolute HTTP URL that has been munged by path.Clean
// or a webserver that collapses multiple slashes.
var reCleanedURL = regexp.MustCompile(`^(https?):/([^/])`)
// NewRequest parses an http.Request into an imageproxy Request. Options and // NewRequest parses an http.Request into an imageproxy Request. Options and
// the remote image URL are specified in the request path, formatted as: // the remote image URL are specified in the request path, formatted as:
// /{options}/{remote_url}. Options may be omitted, so a request path may // /{options}/{remote_url}. Options may be omitted, so a request path may
@ -239,6 +244,7 @@ func NewRequest(r *http.Request, baseURL *url.URL) (*Request, error) {
req := &Request{Original: r} req := &Request{Original: r}
path := r.URL.Path[1:] // strip leading slash path := r.URL.Path[1:] // strip leading slash
path = reCleanedURL.ReplaceAllString(path, "$1://$2")
req.URL, err = url.Parse(path) req.URL, err = url.Parse(path)
if err != nil || !req.URL.IsAbs() { if err != nil || !req.URL.IsAbs() {
// first segment should be options // first segment should be options

View file

@ -143,6 +143,10 @@ func TestNewRequest(t *testing.T) {
"http://localhost//http://example.com/foo?bar", "http://localhost//http://example.com/foo?bar",
"http://example.com/foo?bar", emptyOptions, false, "http://example.com/foo?bar", emptyOptions, false,
}, },
{
"http://localhost/http:/example.com/foo",
"http://example.com/foo", emptyOptions, false,
},
} }
for _, tt := range tests { for _, tt := range tests {

View file

@ -35,10 +35,6 @@ import (
) )
// Proxy serves image requests. // Proxy serves image requests.
//
// Note that a Proxy should not be run behind a http.ServeMux, since the
// ServeMux aggressively cleans URLs and removes the double slash in the
// embedded request URL.
type Proxy struct { type Proxy struct {
Client *http.Client // client used to fetch remote URLs Client *http.Client // client used to fetch remote URLs
Cache Cache // cache used to cache responses Cache Cache // cache used to cache responses