diff --git a/imageproxy.go b/imageproxy.go index bdde2bb..4767636 100644 --- a/imageproxy.go +++ b/imageproxy.go @@ -61,6 +61,9 @@ type Proxy struct { // absolute. DefaultBaseURL *url.URL + // The Logger used by the image proxy + Logger *log.Logger + // SignatureKey is the HMAC key used to verify signed requests. SignatureKey []byte @@ -105,7 +108,7 @@ func NewProxy(transport http.RoundTripper, cache Cache) *Proxy { CachingClient: client, log: func(format string, v ...interface{}) { if proxy.Verbose { - log.Printf(format, v...) + proxy.logf(format, v...) } }, }, @@ -141,13 +144,13 @@ func (p *Proxy) serveImage(w http.ResponseWriter, r *http.Request) { req, err := NewRequest(r, p.DefaultBaseURL) if err != nil { msg := fmt.Sprintf("invalid request URL: %v", err) - log.Print(msg) + p.log(msg) http.Error(w, msg, http.StatusBadRequest) return } if err := p.allowed(req); err != nil { - log.Printf("%s: %v", err, req) + p.logf("%s: %v", err, req) http.Error(w, msgNotAllowed, http.StatusForbidden) return } @@ -166,7 +169,7 @@ func (p *Proxy) serveImage(w http.ResponseWriter, r *http.Request) { if err != nil { msg := fmt.Sprintf("error fetching remote image: %v", err) - log.Print(msg) + p.log(msg) http.Error(w, msg, http.StatusInternalServerError) return } @@ -175,7 +178,7 @@ func (p *Proxy) serveImage(w http.ResponseWriter, r *http.Request) { cached := resp.Header.Get(httpcache.XFromCache) if p.Verbose { - log.Printf("request: %+v (served from cache: %t)", *actualReq, cached == "1") + p.logf("request: %+v (served from cache: %t)", *actualReq, cached == "1") } copyHeader(w.Header(), resp.Header, "Cache-Control", "Last-Modified", "Expires", "Etag", "Link") @@ -193,7 +196,7 @@ func (p *Proxy) serveImage(w http.ResponseWriter, r *http.Request) { contentType = peekContentType(b) } if resp.ContentLength != 0 && !contentTypeMatches(p.ContentTypes, contentType) { - log.Printf("content-type not allowed: %q", contentType) + p.logf("content-type not allowed: %q", contentType) http.Error(w, msgNotAllowed, http.StatusForbidden) return } @@ -368,6 +371,22 @@ func should304(req *http.Request, resp *http.Response) bool { return false } +func (p *Proxy) log(v ...interface{}) { + if p.Logger != nil { + p.Logger.Print(v...) + } else { + log.Print(v...) + } +} + +func (p *Proxy) logf(format string, v ...interface{}) { + if p.Logger != nil { + p.Logger.Printf(format, v...) + } else { + log.Printf(format, v...) + } +} + // TransformingTransport is an implementation of http.RoundTripper that // optionally transforms images using the options specified in the request URL // fragment. diff --git a/imageproxy_test.go b/imageproxy_test.go index 035ae38..de31ffb 100644 --- a/imageproxy_test.go +++ b/imageproxy_test.go @@ -21,9 +21,11 @@ import ( "fmt" "image" "image/png" + "log" "net/http" "net/http/httptest" "net/url" + "os" "reflect" "strings" "testing" @@ -412,6 +414,52 @@ func TestProxy_ServeHTTP_is304(t *testing.T) { } } +func TestProxy_log(t *testing.T) { + var b strings.Builder + + p := &Proxy{ + Logger: log.New(&b, "", 0), + } + p.log("Test") + + if got, want := b.String(), "Test\n"; got != want { + t.Errorf("log wrote %s, want %s", got, want) + } + + b.Reset() + p.logf("Test %v", 123) + + if got, want := b.String(), "Test 123\n"; got != want { + t.Errorf("logf wrote %s, want %s", got, want) + } +} + +func TestProxy_log_default(t *testing.T) { + var b strings.Builder + + defer func(flags int) { + log.SetOutput(os.Stderr) + log.SetFlags(flags) + }(log.Flags()) + + log.SetOutput(&b) + log.SetFlags(0) + + p := &Proxy{} + p.log("Test") + + if got, want := b.String(), "Test\n"; got != want { + t.Errorf("log wrote %s, want %s", got, want) + } + + b.Reset() + p.logf("Test %v", 123) + + if got, want := b.String(), "Test 123\n"; got != want { + t.Errorf("logf wrote %s, want %s", got, want) + } +} + func TestTransformingTransport(t *testing.T) { client := new(http.Client) tr := &TransformingTransport{