diff --git a/README.md b/README.md index 335a4c1..91a8d45 100644 --- a/README.md +++ b/README.md @@ -154,6 +154,20 @@ you want to use a different caching implementation, it's probably easiest to just make a copy of `cmd/imageproxy/main.go` and customize it to fit your needs... it's a very simple command. +### Default Base URL ### + +Typically, remote images to be proxied are specified as absolute URLs. +However, if you commonly proxy images from a single source, you can provide a +base URL and then specify remote images relative to that base. Try it out by running: + + imageproxy -baseURL https://octodex.github.com/ + +Then load the codercat image, specified as a URL relative to that base: +. Note that this is not an +effective method to mask the true source of the images being proxied; it is +trivial to discover the base URL being used. Even when a base URL is +specified, you can always provide the absolute URL of the image to be proxied. + ## Deploying ## diff --git a/cmd/imageproxy/main.go b/cmd/imageproxy/main.go index 8ee260a..20840b6 100644 --- a/cmd/imageproxy/main.go +++ b/cmd/imageproxy/main.go @@ -20,6 +20,7 @@ import ( "fmt" "log" "net/http" + "net/url" "strings" "github.com/gregjones/httpcache" @@ -39,6 +40,7 @@ var ( var addr = flag.String("addr", "localhost:8080", "TCP address to listen on") var whitelist = flag.String("whitelist", "", "comma separated list of allowed remote hosts") +var baseURL = flag.String("baseURL", "", "default base URL for relative remote URLs") var cacheDir = flag.String("cacheDir", "", "directory to use for file cache") var cacheSize = flag.Uint64("cacheSize", 100, "maximum size of file cache (in MB)") var version = flag.Bool("version", false, "print version information") @@ -66,6 +68,13 @@ func main() { if *whitelist != "" { p.Whitelist = strings.Split(*whitelist, ",") } + if *baseURL != "" { + var err error + p.DefaultBaseURL, err = url.Parse(*baseURL) + if err != nil { + log.Fatalf("error parsing baseURL: %v", err) + } + } server := &http.Server{ Addr: *addr, diff --git a/data.go b/data.go index c1f9af0..6505d2e 100644 --- a/data.go +++ b/data.go @@ -199,7 +199,7 @@ type Request struct { // http://localhost/100x200,r90/http://example.com/image.jpg?foo=bar // http://localhost//http://example.com/image.jpg // http://localhost/http://example.com/image.jpg -func NewRequest(r *http.Request) (*Request, error) { +func NewRequest(r *http.Request, baseURL *url.URL) (*Request, error) { var err error req := new(Request) @@ -220,6 +220,10 @@ func NewRequest(r *http.Request) (*Request, error) { req.Options = ParseOptions(parts[0]) } + if baseURL != nil { + req.URL = baseURL.ResolveReference(req.URL) + } + if !req.URL.IsAbs() { return nil, URLError{"must provide absolute remote URL", r.URL} } diff --git a/data_test.go b/data_test.go index 2f86ad2..4e4f616 100644 --- a/data_test.go +++ b/data_test.go @@ -150,7 +150,7 @@ func TestNewRequest(t *testing.T) { continue } - r, err := NewRequest(req) + r, err := NewRequest(req, nil) if tt.ExpectError { if err == nil { t.Errorf("NewRequest(%v) did not return expected error", req) diff --git a/imageproxy.go b/imageproxy.go index a718af0..9993098 100644 --- a/imageproxy.go +++ b/imageproxy.go @@ -43,6 +43,11 @@ type Proxy struct { // Whitelist specifies a list of remote hosts that images can be // proxied from. An empty list means all hosts are allowed. Whitelist []string + + // DefaultBaseURL is the URL that relative remote URLs are resolved in + // reference to. If nil, all remote URLs specified in requests must be + // absolute. + DefaultBaseURL *url.URL } // NewProxy constructs a new proxy. The provided http RoundTripper will be @@ -75,7 +80,7 @@ func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { return // ignore favicon requests } - req, err := NewRequest(r) + req, err := NewRequest(r, p.DefaultBaseURL) if err != nil { msg := fmt.Sprintf("invalid request URL: %v", err) glog.Error(msg)