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

refactor whitelist check in preparation for signature check

This commit is contained in:
Will Norris 2015-05-11 21:35:07 -07:00
parent 6553dd0603
commit 9d6f8fdf7d
2 changed files with 56 additions and 20 deletions

View file

@ -88,10 +88,10 @@ func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return
}
if !p.allowed(req.URL) {
msg := fmt.Sprintf("remote URL is not for an allowed host: %v", req.URL)
if !p.allowed(req) {
msg := fmt.Sprintf("request does not contain an allowed host")
glog.Error(msg)
http.Error(w, msg, http.StatusBadRequest)
http.Error(w, msg, http.StatusForbidden)
return
}
@ -135,13 +135,26 @@ func copyHeader(w http.ResponseWriter, r *http.Response, header string) {
}
}
// allowed returns whether the specified URL is on the whitelist of remote hosts.
func (p *Proxy) allowed(u *url.URL) bool {
// allowed returns whether the specified request is allowed because it matches
// a host in the proxy whitelist.
func (p *Proxy) allowed(r *Request) bool {
if len(p.Whitelist) == 0 {
return true
return true // no whitelist, all requests accepted
}
for _, host := range p.Whitelist {
if len(p.Whitelist) > 0 {
if validHost(p.Whitelist, r.URL) {
return true
}
glog.Infof("remote URL is not for an allowed host: %v", r.URL)
}
return false
}
// validHost returns whether the host in u matches one of hosts.
func validHost(hosts []string, u *url.URL) bool {
for _, host := range hosts {
if u.Host == host {
return true
}

View file

@ -15,7 +15,7 @@ import (
)
func TestAllowed(t *testing.T) {
whitelist := []string{"a.test", "*.b.test", "*c.test"}
whitelist := []string{"good.test"}
tests := []struct {
url string
@ -25,16 +25,8 @@ func TestAllowed(t *testing.T) {
{"http://foo/image", nil, true},
{"http://foo/image", []string{}, true},
{"http://a.test/image", whitelist, true},
{"http://x.a.test/image", whitelist, false},
{"http://b.test/image", whitelist, true},
{"http://x.b.test/image", whitelist, true},
{"http://x.y.b.test/image", whitelist, true},
{"http://c.test/image", whitelist, false},
{"http://xc.test/image", whitelist, false},
{"/image", whitelist, false},
{"http://good.test/image", whitelist, true},
{"http://bad.test/image", whitelist, false},
}
for _, tt := range tests {
@ -45,12 +37,43 @@ func TestAllowed(t *testing.T) {
if err != nil {
t.Errorf("error parsing url %q: %v", tt.url, err)
}
if got, want := p.allowed(u), tt.allowed; got != want {
req := &Request{u, emptyOptions}
if got, want := p.allowed(req), tt.allowed; got != want {
t.Errorf("allowed(%q) returned %v, want %v", u, got, want)
}
}
}
func TestValidHost(t *testing.T) {
whitelist := []string{"a.test", "*.b.test", "*c.test"}
tests := []struct {
url string
valid bool
}{
{"http://a.test/image", true},
{"http://x.a.test/image", false},
{"http://b.test/image", true},
{"http://x.b.test/image", true},
{"http://x.y.b.test/image", true},
{"http://c.test/image", false},
{"http://xc.test/image", false},
{"/image", false},
}
for _, tt := range tests {
u, err := url.Parse(tt.url)
if err != nil {
t.Errorf("error parsing url %q: %v", tt.url, err)
}
if got, want := validHost(whitelist, u), tt.valid; got != want {
t.Errorf("validHost(%v, %q) returned %v, want %v", whitelist, u, got, want)
}
}
}
func TestCheck304(t *testing.T) {
tests := []struct {
req, resp string
@ -168,7 +191,7 @@ func TestProxy_ServeHTTP(t *testing.T) {
}{
{"/favicon.ico", http.StatusOK},
{"//foo", http.StatusBadRequest}, // invalid request URL
{"/http://bad.test/", http.StatusBadRequest}, // Disallowed host
{"/http://bad.test/", http.StatusForbidden}, // Disallowed host
{"/http://good.test/error", http.StatusInternalServerError}, // HTTP protocol error
{"/http://good.test/nocontent", http.StatusNoContent}, // non-OK response