0
Fork 0
mirror of https://github.com/willnorris/imageproxy.git synced 2024-12-16 21:56:43 -05:00

update allowed func to return error instead of bool

this allows returning a more accurate error message, particularly in the
case of an invalid referer header
This commit is contained in:
Will Norris 2015-12-13 16:59:56 -08:00
parent 710a2ab1c9
commit 27d53782b4
2 changed files with 17 additions and 24 deletions

View file

@ -108,10 +108,9 @@ func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// assign static settings from proxy to req.Options // assign static settings from proxy to req.Options
req.Options.ScaleUp = p.ScaleUp req.Options.ScaleUp = p.ScaleUp
if !p.allowed(req) { if err := p.allowed(req); err != nil {
msg := fmt.Sprintf("request does not contain an allowed host or valid signature") glog.Error(err)
glog.Error(msg) http.Error(w, err.Error(), http.StatusForbidden)
http.Error(w, msg, http.StatusForbidden)
return return
} }
@ -150,33 +149,27 @@ func copyHeader(w http.ResponseWriter, r *http.Response, header string) {
} }
} }
// allowed returns whether the specified request is allowed because it matches // allowed determines whether the specified request contains an allowed
// a host in the proxy whitelist or it has a valid signature. // referrer, host, and signature. It returns an error if the request is not
func (p *Proxy) allowed(r *Request) bool { // allowed.
func (p *Proxy) allowed(r *Request) error {
if len(p.Referrers) > 0 && !validReferrer(p.Referrers, r.Original) { if len(p.Referrers) > 0 && !validReferrer(p.Referrers, r.Original) {
glog.Infof("request not coming from allowed referrer: %v", r) return fmt.Errorf("request does not contain an allowed referrer: %v", r)
return false
} }
if len(p.Whitelist) == 0 && len(p.SignatureKey) == 0 { if len(p.Whitelist) == 0 && len(p.SignatureKey) == 0 {
return true // no whitelist or signature key, all requests accepted return nil // no whitelist or signature key, all requests accepted
} }
if len(p.Whitelist) > 0 { if len(p.Whitelist) > 0 && validHost(p.Whitelist, r.URL) {
if validHost(p.Whitelist, r.URL) { return nil
return true
}
glog.Infof("request is not for an allowed host: %v", r)
} }
if len(p.SignatureKey) > 0 { if len(p.SignatureKey) > 0 && validSignature(p.SignatureKey, r) {
if validSignature(p.SignatureKey, r) { return nil
return true
}
glog.Infof("request contains invalid signature: %v", r)
} }
return false return fmt.Errorf("request does not contain an allowed host or valid signature: %v", r)
} }
// validHost returns whether the host in u matches one of hosts. // validHost returns whether the host in u matches one of hosts.
@ -195,12 +188,12 @@ func validHost(hosts []string, u *url.URL) bool {
// returns whether the referrer from the request is in the host list. // returns whether the referrer from the request is in the host list.
func validReferrer(hosts []string, r *http.Request) bool { func validReferrer(hosts []string, r *http.Request) bool {
parsed, err := url.Parse(r.Header.Get("Referer")) u, err := url.Parse(r.Header.Get("Referer"))
if err != nil { // malformed or blank header, just deny if err != nil { // malformed or blank header, just deny
return false return false
} }
return validHost(hosts, parsed) return validHost(hosts, u)
} }
// validSignature returns whether the request signature is valid. // validSignature returns whether the request signature is valid.

View file

@ -70,7 +70,7 @@ func TestAllowed(t *testing.T) {
t.Errorf("error parsing url %q: %v", tt.url, err) t.Errorf("error parsing url %q: %v", tt.url, err)
} }
req := &Request{u, tt.options, tt.request} req := &Request{u, tt.options, tt.request}
if got, want := p.allowed(req), tt.allowed; got != want { if got, want := p.allowed(req), tt.allowed; (got == nil) != want {
t.Errorf("allowed(%q) returned %v, want %v.\nTest struct: %#v", req, got, want, tt) t.Errorf("allowed(%q) returned %v, want %v.\nTest struct: %#v", req, got, want, tt)
} }
} }