diff options
author | Christopher Speller <crspeller@gmail.com> | 2016-05-12 23:56:07 -0400 |
---|---|---|
committer | Christopher Speller <crspeller@gmail.com> | 2016-05-12 23:56:07 -0400 |
commit | 38ee83e45b4de7edf89bf9f0ef629eb4c6ad0fa8 (patch) | |
tree | a4fde09672192b97d453ad605b030bd5a10c5a45 /vendor/github.com/gorilla/handlers | |
parent | 84d2482ddbff9564c9ad75b2d30af66e3ddfd44d (diff) | |
download | chat-38ee83e45b4de7edf89bf9f0ef629eb4c6ad0fa8.tar.gz chat-38ee83e45b4de7edf89bf9f0ef629eb4c6ad0fa8.tar.bz2 chat-38ee83e45b4de7edf89bf9f0ef629eb4c6ad0fa8.zip |
Moving to glide
Diffstat (limited to 'vendor/github.com/gorilla/handlers')
-rw-r--r-- | vendor/github.com/gorilla/handlers/canonical_test.go | 127 | ||||
-rw-r--r-- | vendor/github.com/gorilla/handlers/compress_test.go | 154 | ||||
-rw-r--r-- | vendor/github.com/gorilla/handlers/cors_test.go | 336 | ||||
-rw-r--r-- | vendor/github.com/gorilla/handlers/handlers_test.go | 354 | ||||
-rw-r--r-- | vendor/github.com/gorilla/handlers/proxy_headers_test.go | 100 | ||||
-rw-r--r-- | vendor/github.com/gorilla/handlers/recovery_test.go | 44 |
6 files changed, 1115 insertions, 0 deletions
diff --git a/vendor/github.com/gorilla/handlers/canonical_test.go b/vendor/github.com/gorilla/handlers/canonical_test.go new file mode 100644 index 000000000..615e4b056 --- /dev/null +++ b/vendor/github.com/gorilla/handlers/canonical_test.go @@ -0,0 +1,127 @@ +package handlers + +import ( + "bufio" + "bytes" + "log" + "net/http" + "net/http/httptest" + "net/url" + "strings" + "testing" +) + +func TestCleanHost(t *testing.T) { + tests := []struct { + in, want string + }{ + {"www.google.com", "www.google.com"}, + {"www.google.com foo", "www.google.com"}, + {"www.google.com/foo", "www.google.com"}, + {" first character is a space", ""}, + } + for _, tt := range tests { + got := cleanHost(tt.in) + if tt.want != got { + t.Errorf("cleanHost(%q) = %q, want %q", tt.in, got, tt.want) + } + } +} + +func TestCanonicalHost(t *testing.T) { + gorilla := "http://www.gorillatoolkit.org" + + rr := httptest.NewRecorder() + r := newRequest("GET", "http://www.example.com/") + + testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) + + // Test a re-direct: should return a 302 Found. + CanonicalHost(gorilla, http.StatusFound)(testHandler).ServeHTTP(rr, r) + + if rr.Code != http.StatusFound { + t.Fatalf("bad status: got %v want %v", rr.Code, http.StatusFound) + } + + if rr.Header().Get("Location") != gorilla+r.URL.Path { + t.Fatalf("bad re-direct: got %q want %q", rr.Header().Get("Location"), gorilla+r.URL.Path) + } + +} + +func TestKeepsQueryString(t *testing.T) { + google := "https://www.google.com" + + rr := httptest.NewRecorder() + querystring := url.Values{"q": {"golang"}, "format": {"json"}}.Encode() + r := newRequest("GET", "http://www.example.com/search?"+querystring) + + testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) + CanonicalHost(google, http.StatusFound)(testHandler).ServeHTTP(rr, r) + + want := google + r.URL.Path + "?" + querystring + if rr.Header().Get("Location") != want { + t.Fatalf("bad re-direct: got %q want %q", rr.Header().Get("Location"), want) + } +} + +func TestBadDomain(t *testing.T) { + rr := httptest.NewRecorder() + r := newRequest("GET", "http://www.example.com/") + + testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) + + // Test a bad domain - should return 200 OK. + CanonicalHost("%", http.StatusFound)(testHandler).ServeHTTP(rr, r) + + if rr.Code != http.StatusOK { + t.Fatalf("bad status: got %v want %v", rr.Code, http.StatusOK) + } +} + +func TestEmptyHost(t *testing.T) { + rr := httptest.NewRecorder() + r := newRequest("GET", "http://www.example.com/") + + testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) + + // Test a domain that returns an empty url.Host from url.Parse. + CanonicalHost("hello.com", http.StatusFound)(testHandler).ServeHTTP(rr, r) + + if rr.Code != http.StatusOK { + t.Fatalf("bad status: got %v want %v", rr.Code, http.StatusOK) + } +} + +func TestHeaderWrites(t *testing.T) { + gorilla := "http://www.gorillatoolkit.org" + + testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(200) + }) + + // Catch the log output to ensure we don't write multiple headers. + var b bytes.Buffer + buf := bufio.NewWriter(&b) + tl := log.New(buf, "test: ", log.Lshortfile) + + srv := httptest.NewServer( + CanonicalHost(gorilla, http.StatusFound)(testHandler)) + defer srv.Close() + srv.Config.ErrorLog = tl + + _, err := http.Get(srv.URL) + if err != nil { + t.Fatal(err) + } + + err = buf.Flush() + if err != nil { + t.Fatal(err) + } + + // We rely on the error not changing: net/http does not export it. + if strings.Contains(b.String(), "multiple response.WriteHeader calls") { + t.Fatalf("re-direct did not return early: multiple header writes") + } +} diff --git a/vendor/github.com/gorilla/handlers/compress_test.go b/vendor/github.com/gorilla/handlers/compress_test.go new file mode 100644 index 000000000..6f07f440d --- /dev/null +++ b/vendor/github.com/gorilla/handlers/compress_test.go @@ -0,0 +1,154 @@ +// Copyright 2013 The Gorilla Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package handlers + +import ( + "bufio" + "io" + "net" + "net/http" + "net/http/httptest" + "strconv" + "testing" +) + +var contentType = "text/plain; charset=utf-8" + +func compressedRequest(w *httptest.ResponseRecorder, compression string) { + CompressHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Length", strconv.Itoa(9*1024)) + w.Header().Set("Content-Type", contentType) + for i := 0; i < 1024; i++ { + io.WriteString(w, "Gorilla!\n") + } + })).ServeHTTP(w, &http.Request{ + Method: "GET", + Header: http.Header{ + "Accept-Encoding": []string{compression}, + }, + }) + +} + +func TestCompressHandlerNoCompression(t *testing.T) { + w := httptest.NewRecorder() + compressedRequest(w, "") + if enc := w.HeaderMap.Get("Content-Encoding"); enc != "" { + t.Errorf("wrong content encoding, got %q want %q", enc, "") + } + if ct := w.HeaderMap.Get("Content-Type"); ct != contentType { + t.Errorf("wrong content type, got %q want %q", ct, contentType) + } + if w.Body.Len() != 1024*9 { + t.Errorf("wrong len, got %d want %d", w.Body.Len(), 1024*9) + } + if l := w.HeaderMap.Get("Content-Length"); l != "9216" { + t.Errorf("wrong content-length. got %q expected %d", l, 1024*9) + } +} + +func TestCompressHandlerGzip(t *testing.T) { + w := httptest.NewRecorder() + compressedRequest(w, "gzip") + if w.HeaderMap.Get("Content-Encoding") != "gzip" { + t.Errorf("wrong content encoding, got %q want %q", w.HeaderMap.Get("Content-Encoding"), "gzip") + } + if w.HeaderMap.Get("Content-Type") != "text/plain; charset=utf-8" { + t.Errorf("wrong content type, got %s want %s", w.HeaderMap.Get("Content-Type"), "text/plain; charset=utf-8") + } + if w.Body.Len() != 72 { + t.Errorf("wrong len, got %d want %d", w.Body.Len(), 72) + } + if l := w.HeaderMap.Get("Content-Length"); l != "" { + t.Errorf("wrong content-length. got %q expected %q", l, "") + } +} + +func TestCompressHandlerDeflate(t *testing.T) { + w := httptest.NewRecorder() + compressedRequest(w, "deflate") + if w.HeaderMap.Get("Content-Encoding") != "deflate" { + t.Fatalf("wrong content encoding, got %q want %q", w.HeaderMap.Get("Content-Encoding"), "deflate") + } + if w.HeaderMap.Get("Content-Type") != "text/plain; charset=utf-8" { + t.Fatalf("wrong content type, got %s want %s", w.HeaderMap.Get("Content-Type"), "text/plain; charset=utf-8") + } + if w.Body.Len() != 54 { + t.Fatalf("wrong len, got %d want %d", w.Body.Len(), 54) + } +} + +func TestCompressHandlerGzipDeflate(t *testing.T) { + w := httptest.NewRecorder() + compressedRequest(w, "gzip, deflate ") + if w.HeaderMap.Get("Content-Encoding") != "gzip" { + t.Fatalf("wrong content encoding, got %q want %q", w.HeaderMap.Get("Content-Encoding"), "gzip") + } + if w.HeaderMap.Get("Content-Type") != "text/plain; charset=utf-8" { + t.Fatalf("wrong content type, got %s want %s", w.HeaderMap.Get("Content-Type"), "text/plain; charset=utf-8") + } +} + +type fullyFeaturedResponseWriter struct{} + +// Header/Write/WriteHeader implement the http.ResponseWriter interface. +func (fullyFeaturedResponseWriter) Header() http.Header { + return http.Header{} +} +func (fullyFeaturedResponseWriter) Write([]byte) (int, error) { + return 0, nil +} +func (fullyFeaturedResponseWriter) WriteHeader(int) {} + +// Flush implements the http.Flusher interface. +func (fullyFeaturedResponseWriter) Flush() {} + +// Hijack implements the http.Hijacker interface. +func (fullyFeaturedResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { + return nil, nil, nil +} + +// CloseNotify implements the http.CloseNotifier interface. +func (fullyFeaturedResponseWriter) CloseNotify() <-chan bool { + return nil +} + +func TestCompressHandlerPreserveInterfaces(t *testing.T) { + // Compile time validation fullyFeaturedResponseWriter implements all the + // interfaces we're asserting in the test case below. + var ( + _ http.Flusher = fullyFeaturedResponseWriter{} + _ http.CloseNotifier = fullyFeaturedResponseWriter{} + _ http.Hijacker = fullyFeaturedResponseWriter{} + ) + var h http.Handler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + comp := r.Header.Get("Accept-Encoding") + if _, ok := rw.(*compressResponseWriter); !ok { + t.Fatalf("ResponseWriter wasn't wrapped by compressResponseWriter, got %T type", rw) + } + if _, ok := rw.(http.Flusher); !ok { + t.Errorf("ResponseWriter lost http.Flusher interface for %q", comp) + } + if _, ok := rw.(http.CloseNotifier); !ok { + t.Errorf("ResponseWriter lost http.CloseNotifier interface for %q", comp) + } + if _, ok := rw.(http.Hijacker); !ok { + t.Errorf("ResponseWriter lost http.Hijacker interface for %q", comp) + } + }) + h = CompressHandler(h) + var ( + rw fullyFeaturedResponseWriter + ) + r, err := http.NewRequest("GET", "/", nil) + if err != nil { + t.Fatalf("Failed to create test request: %v", err) + } + r.Header.Set("Accept-Encoding", "gzip") + h.ServeHTTP(rw, r) + + r.Header.Set("Accept-Encoding", "deflate") + h.ServeHTTP(rw, r) +} diff --git a/vendor/github.com/gorilla/handlers/cors_test.go b/vendor/github.com/gorilla/handlers/cors_test.go new file mode 100644 index 000000000..c63913eee --- /dev/null +++ b/vendor/github.com/gorilla/handlers/cors_test.go @@ -0,0 +1,336 @@ +package handlers + +import ( + "net/http" + "net/http/httptest" + "strings" + "testing" +) + +func TestDefaultCORSHandlerReturnsOk(t *testing.T) { + r := newRequest("GET", "http://www.example.com/") + rr := httptest.NewRecorder() + + testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) + + CORS()(testHandler).ServeHTTP(rr, r) + + if status := rr.Code; status != http.StatusOK { + t.Fatalf("bad status: got %v want %v", status, http.StatusFound) + } +} + +func TestDefaultCORSHandlerReturnsOkWithOrigin(t *testing.T) { + r := newRequest("GET", "http://www.example.com/") + r.Header.Set("Origin", r.URL.String()) + + rr := httptest.NewRecorder() + + testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) + + CORS()(testHandler).ServeHTTP(rr, r) + + if status := rr.Code; status != http.StatusOK { + t.Fatalf("bad status: got %v want %v", status, http.StatusFound) + } +} + +func TestCORSHandlerIgnoreOptionsFallsThrough(t *testing.T) { + r := newRequest("OPTIONS", "http://www.example.com/") + r.Header.Set("Origin", r.URL.String()) + + rr := httptest.NewRecorder() + + testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusTeapot) + }) + + CORS(IgnoreOptions())(testHandler).ServeHTTP(rr, r) + + if status := rr.Code; status != http.StatusTeapot { + t.Fatalf("bad status: got %v want %v", status, http.StatusTeapot) + } +} + +func TestCORSHandlerSetsExposedHeaders(t *testing.T) { + // Test default configuration. + r := newRequest("GET", "http://www.example.com/") + r.Header.Set("Origin", r.URL.String()) + + rr := httptest.NewRecorder() + + testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) + + CORS(ExposedHeaders([]string{"X-CORS-TEST"}))(testHandler).ServeHTTP(rr, r) + + if status := rr.Code; status != http.StatusOK { + t.Fatalf("bad status: got %v want %v", status, http.StatusOK) + } + + header := rr.HeaderMap.Get(corsExposeHeadersHeader) + if header != "X-Cors-Test" { + t.Fatal("bad header: expected X-Cors-Test header, got empty header for method.") + } +} + +func TestCORSHandlerUnsetRequestMethodForPreflightBadRequest(t *testing.T) { + r := newRequest("OPTIONS", "http://www.example.com/") + r.Header.Set("Origin", r.URL.String()) + + rr := httptest.NewRecorder() + + testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) + + CORS(AllowedMethods([]string{"DELETE"}))(testHandler).ServeHTTP(rr, r) + + if status := rr.Code; status != http.StatusBadRequest { + t.Fatalf("bad status: got %v want %v", status, http.StatusBadRequest) + } +} + +func TestCORSHandlerInvalidRequestMethodForPreflightMethodNotAllowed(t *testing.T) { + r := newRequest("OPTIONS", "http://www.example.com/") + r.Header.Set("Origin", r.URL.String()) + r.Header.Set(corsRequestMethodHeader, "DELETE") + + rr := httptest.NewRecorder() + + testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) + + CORS()(testHandler).ServeHTTP(rr, r) + + if status := rr.Code; status != http.StatusMethodNotAllowed { + t.Fatalf("bad status: got %v want %v", status, http.StatusMethodNotAllowed) + } +} + +func TestCORSHandlerOptionsRequestMustNotBePassedToNextHandler(t *testing.T) { + r := newRequest("OPTIONS", "http://www.example.com/") + r.Header.Set("Origin", r.URL.String()) + r.Header.Set(corsRequestMethodHeader, "GET") + + rr := httptest.NewRecorder() + + testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + t.Fatal("Options request must not be passed to next handler") + }) + + CORS()(testHandler).ServeHTTP(rr, r) + + if status := rr.Code; status != http.StatusOK { + t.Fatalf("bad status: got %v want %v", status, http.StatusOK) + } +} + +func TestCORSHandlerAllowedMethodForPreflight(t *testing.T) { + r := newRequest("OPTIONS", "http://www.example.com/") + r.Header.Set("Origin", r.URL.String()) + r.Header.Set(corsRequestMethodHeader, "DELETE") + + rr := httptest.NewRecorder() + + testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) + + CORS(AllowedMethods([]string{"DELETE"}))(testHandler).ServeHTTP(rr, r) + + if status := rr.Code; status != http.StatusOK { + t.Fatalf("bad status: got %v want %v", status, http.StatusOK) + } + + header := rr.HeaderMap.Get(corsAllowMethodsHeader) + if header != "DELETE" { + t.Fatalf("bad header: expected DELETE method header, got empty header.") + } +} + +func TestCORSHandlerAllowMethodsNotSetForSimpleRequestPreflight(t *testing.T) { + for _, method := range defaultCorsMethods { + r := newRequest("OPTIONS", "http://www.example.com/") + r.Header.Set("Origin", r.URL.String()) + r.Header.Set(corsRequestMethodHeader, method) + + rr := httptest.NewRecorder() + + testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) + + CORS()(testHandler).ServeHTTP(rr, r) + + if status := rr.Code; status != http.StatusOK { + t.Fatalf("bad status: got %v want %v", status, http.StatusOK) + } + + header := rr.HeaderMap.Get(corsAllowMethodsHeader) + if header != "" { + t.Fatalf("bad header: expected empty method header, got %s.", header) + } + } +} + +func TestCORSHandlerAllowedHeaderNotSetForSimpleRequestPreflight(t *testing.T) { + for _, simpleHeader := range defaultCorsHeaders { + r := newRequest("OPTIONS", "http://www.example.com/") + r.Header.Set("Origin", r.URL.String()) + r.Header.Set(corsRequestMethodHeader, "GET") + r.Header.Set(corsRequestHeadersHeader, simpleHeader) + + rr := httptest.NewRecorder() + + testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) + + CORS()(testHandler).ServeHTTP(rr, r) + + if status := rr.Code; status != http.StatusOK { + t.Fatalf("bad status: got %v want %v", status, http.StatusOK) + } + + header := rr.HeaderMap.Get(corsAllowHeadersHeader) + if header != "" { + t.Fatalf("bad header: expected empty header, got %s.", header) + } + } +} + +func TestCORSHandlerAllowedHeaderForPreflight(t *testing.T) { + r := newRequest("OPTIONS", "http://www.example.com/") + r.Header.Set("Origin", r.URL.String()) + r.Header.Set(corsRequestMethodHeader, "POST") + r.Header.Set(corsRequestHeadersHeader, "Content-Type") + + rr := httptest.NewRecorder() + + testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) + + CORS(AllowedHeaders([]string{"Content-Type"}))(testHandler).ServeHTTP(rr, r) + + if status := rr.Code; status != http.StatusOK { + t.Fatalf("bad status: got %v want %v", status, http.StatusOK) + } + + header := rr.HeaderMap.Get(corsAllowHeadersHeader) + if header != "Content-Type" { + t.Fatalf("bad header: expected Content-Type header, got empty header.") + } +} + +func TestCORSHandlerInvalidHeaderForPreflightForbidden(t *testing.T) { + r := newRequest("OPTIONS", "http://www.example.com/") + r.Header.Set("Origin", r.URL.String()) + r.Header.Set(corsRequestMethodHeader, "POST") + r.Header.Set(corsRequestHeadersHeader, "Content-Type") + + rr := httptest.NewRecorder() + + testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) + + CORS()(testHandler).ServeHTTP(rr, r) + + if status := rr.Code; status != http.StatusForbidden { + t.Fatalf("bad status: got %v want %v", status, http.StatusForbidden) + } +} + +func TestCORSHandlerMaxAgeForPreflight(t *testing.T) { + r := newRequest("OPTIONS", "http://www.example.com/") + r.Header.Set("Origin", r.URL.String()) + r.Header.Set(corsRequestMethodHeader, "POST") + + rr := httptest.NewRecorder() + + testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) + + CORS(MaxAge(3500))(testHandler).ServeHTTP(rr, r) + + if status := rr.Code; status != http.StatusOK { + t.Fatalf("bad status: got %v want %v", status, http.StatusOK) + } + + header := rr.HeaderMap.Get(corsMaxAgeHeader) + if header != "600" { + t.Fatalf("bad header: expected %s to be %s, got %s.", corsMaxAgeHeader, "600", header) + } +} + +func TestCORSHandlerAllowedCredentials(t *testing.T) { + r := newRequest("GET", "http://www.example.com/") + r.Header.Set("Origin", r.URL.String()) + + rr := httptest.NewRecorder() + + testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) + + CORS(AllowCredentials())(testHandler).ServeHTTP(rr, r) + + if status := rr.Code; status != http.StatusOK { + t.Fatalf("bad status: got %v want %v", status, http.StatusOK) + } + + header := rr.HeaderMap.Get(corsAllowCredentialsHeader) + if header != "true" { + t.Fatalf("bad header: expected %s to be %s, got %s.", corsAllowCredentialsHeader, "true", header) + } +} + +func TestCORSHandlerMultipleAllowOriginsSetsVaryHeader(t *testing.T) { + r := newRequest("GET", "http://www.example.com/") + r.Header.Set("Origin", r.URL.String()) + + rr := httptest.NewRecorder() + + testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) + + CORS(AllowedOrigins([]string{r.URL.String(), "http://google.com"}))(testHandler).ServeHTTP(rr, r) + + if status := rr.Code; status != http.StatusOK { + t.Fatalf("bad status: got %v want %v", status, http.StatusOK) + } + + header := rr.HeaderMap.Get(corsVaryHeader) + if header != corsOriginHeader { + t.Fatalf("bad header: expected %s to be %s, got %s.", corsVaryHeader, corsOriginHeader, header) + } +} + +func TestCORSWithMultipleHandlers(t *testing.T) { + var lastHandledBy string + corsMiddleware := CORS() + + testHandler1 := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + lastHandledBy = "testHandler1" + }) + testHandler2 := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + lastHandledBy = "testHandler2" + }) + + r1 := newRequest("GET", "http://www.example.com/") + rr1 := httptest.NewRecorder() + handler1 := corsMiddleware(testHandler1) + + corsMiddleware(testHandler2) + + handler1.ServeHTTP(rr1, r1) + if lastHandledBy != "testHandler1" { + t.Fatalf("bad CORS() registration: Handler served should be Handler registered") + } +} + +func TestCORSHandlerWithCustomValidator(t *testing.T) { + r := newRequest("GET", "http://a.example.com") + r.Header.Set("Origin", r.URL.String()) + rr := httptest.NewRecorder() + + testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) + + originValidator := func(origin string) bool { + if strings.HasSuffix(origin, ".example.com") { + return true + } + return false + } + + CORS(AllowedOriginValidator(originValidator))(testHandler).ServeHTTP(rr, r) + header := rr.HeaderMap.Get(corsAllowOriginHeader) + if header != r.URL.String() { + t.Fatalf("bad header: expected %s to be %s, got %s.", corsAllowOriginHeader, r.URL.String(), header) + } + +} diff --git a/vendor/github.com/gorilla/handlers/handlers_test.go b/vendor/github.com/gorilla/handlers/handlers_test.go new file mode 100644 index 000000000..6ea7c7fa6 --- /dev/null +++ b/vendor/github.com/gorilla/handlers/handlers_test.go @@ -0,0 +1,354 @@ +// Copyright 2013 The Gorilla Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package handlers + +import ( + "bytes" + "net" + "net/http" + "net/http/httptest" + "net/url" + "strings" + "testing" + "time" +) + +const ( + ok = "ok\n" + notAllowed = "Method not allowed\n" +) + +var okHandler = http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + w.Write([]byte(ok)) +}) + +func newRequest(method, url string) *http.Request { + req, err := http.NewRequest(method, url, nil) + if err != nil { + panic(err) + } + return req +} + +func TestMethodHandler(t *testing.T) { + tests := []struct { + req *http.Request + handler http.Handler + code int + allow string // Contents of the Allow header + body string + }{ + // No handlers + {newRequest("GET", "/foo"), MethodHandler{}, http.StatusMethodNotAllowed, "", notAllowed}, + {newRequest("OPTIONS", "/foo"), MethodHandler{}, http.StatusOK, "", ""}, + + // A single handler + {newRequest("GET", "/foo"), MethodHandler{"GET": okHandler}, http.StatusOK, "", ok}, + {newRequest("POST", "/foo"), MethodHandler{"GET": okHandler}, http.StatusMethodNotAllowed, "GET", notAllowed}, + + // Multiple handlers + {newRequest("GET", "/foo"), MethodHandler{"GET": okHandler, "POST": okHandler}, http.StatusOK, "", ok}, + {newRequest("POST", "/foo"), MethodHandler{"GET": okHandler, "POST": okHandler}, http.StatusOK, "", ok}, + {newRequest("DELETE", "/foo"), MethodHandler{"GET": okHandler, "POST": okHandler}, http.StatusMethodNotAllowed, "GET, POST", notAllowed}, + {newRequest("OPTIONS", "/foo"), MethodHandler{"GET": okHandler, "POST": okHandler}, http.StatusOK, "GET, POST", ""}, + + // Override OPTIONS + {newRequest("OPTIONS", "/foo"), MethodHandler{"OPTIONS": okHandler}, http.StatusOK, "", ok}, + } + + for i, test := range tests { + rec := httptest.NewRecorder() + test.handler.ServeHTTP(rec, test.req) + if rec.Code != test.code { + t.Fatalf("%d: wrong code, got %d want %d", i, rec.Code, test.code) + } + if allow := rec.HeaderMap.Get("Allow"); allow != test.allow { + t.Fatalf("%d: wrong Allow, got %s want %s", i, allow, test.allow) + } + if body := rec.Body.String(); body != test.body { + t.Fatalf("%d: wrong body, got %q want %q", i, body, test.body) + } + } +} + +func TestWriteLog(t *testing.T) { + loc, err := time.LoadLocation("Europe/Warsaw") + if err != nil { + panic(err) + } + ts := time.Date(1983, 05, 26, 3, 30, 45, 0, loc) + + // A typical request with an OK response + req := newRequest("GET", "http://example.com") + req.RemoteAddr = "192.168.100.5" + + buf := new(bytes.Buffer) + writeLog(buf, req, *req.URL, ts, http.StatusOK, 100) + log := buf.String() + + expected := "192.168.100.5 - - [26/May/1983:03:30:45 +0200] \"GET / HTTP/1.1\" 200 100\n" + if log != expected { + t.Fatalf("wrong log, got %q want %q", log, expected) + } + + // CONNECT request over http/2.0 + req = &http.Request{ + Method: "CONNECT", + Proto: "HTTP/2.0", + ProtoMajor: 2, + ProtoMinor: 0, + URL: &url.URL{Host: "www.example.com:443"}, + Host: "www.example.com:443", + RemoteAddr: "192.168.100.5", + } + + buf = new(bytes.Buffer) + writeLog(buf, req, *req.URL, ts, http.StatusOK, 100) + log = buf.String() + + expected = "192.168.100.5 - - [26/May/1983:03:30:45 +0200] \"CONNECT www.example.com:443 HTTP/2.0\" 200 100\n" + if log != expected { + t.Fatalf("wrong log, got %q want %q", log, expected) + } + + // Request with an unauthorized user + req = newRequest("GET", "http://example.com") + req.RemoteAddr = "192.168.100.5" + req.URL.User = url.User("kamil") + + buf.Reset() + writeLog(buf, req, *req.URL, ts, http.StatusUnauthorized, 500) + log = buf.String() + + expected = "192.168.100.5 - kamil [26/May/1983:03:30:45 +0200] \"GET / HTTP/1.1\" 401 500\n" + if log != expected { + t.Fatalf("wrong log, got %q want %q", log, expected) + } + + // Request with url encoded parameters + req = newRequest("GET", "http://example.com/test?abc=hello%20world&a=b%3F") + req.RemoteAddr = "192.168.100.5" + + buf.Reset() + writeLog(buf, req, *req.URL, ts, http.StatusOK, 100) + log = buf.String() + + expected = "192.168.100.5 - - [26/May/1983:03:30:45 +0200] \"GET /test?abc=hello%20world&a=b%3F HTTP/1.1\" 200 100\n" + if log != expected { + t.Fatalf("wrong log, got %q want %q", log, expected) + } +} + +func TestWriteCombinedLog(t *testing.T) { + loc, err := time.LoadLocation("Europe/Warsaw") + if err != nil { + panic(err) + } + ts := time.Date(1983, 05, 26, 3, 30, 45, 0, loc) + + // A typical request with an OK response + req := newRequest("GET", "http://example.com") + req.RemoteAddr = "192.168.100.5" + req.Header.Set("Referer", "http://example.com") + req.Header.Set( + "User-Agent", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.33 "+ + "(KHTML, like Gecko) Chrome/27.0.1430.0 Safari/537.33", + ) + + buf := new(bytes.Buffer) + writeCombinedLog(buf, req, *req.URL, ts, http.StatusOK, 100) + log := buf.String() + + expected := "192.168.100.5 - - [26/May/1983:03:30:45 +0200] \"GET / HTTP/1.1\" 200 100 \"http://example.com\" " + + "\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) " + + "AppleWebKit/537.33 (KHTML, like Gecko) Chrome/27.0.1430.0 Safari/537.33\"\n" + if log != expected { + t.Fatalf("wrong log, got %q want %q", log, expected) + } + + // CONNECT request over http/2.0 + req1 := &http.Request{ + Method: "CONNECT", + Host: "www.example.com:443", + Proto: "HTTP/2.0", + ProtoMajor: 2, + ProtoMinor: 0, + RemoteAddr: "192.168.100.5", + Header: http.Header{}, + URL: &url.URL{Host: "www.example.com:443"}, + } + req1.Header.Set("Referer", "http://example.com") + req1.Header.Set( + "User-Agent", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.33 "+ + "(KHTML, like Gecko) Chrome/27.0.1430.0 Safari/537.33", + ) + + buf = new(bytes.Buffer) + writeCombinedLog(buf, req1, *req1.URL, ts, http.StatusOK, 100) + log = buf.String() + + expected = "192.168.100.5 - - [26/May/1983:03:30:45 +0200] \"CONNECT www.example.com:443 HTTP/2.0\" 200 100 \"http://example.com\" " + + "\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) " + + "AppleWebKit/537.33 (KHTML, like Gecko) Chrome/27.0.1430.0 Safari/537.33\"\n" + if log != expected { + t.Fatalf("wrong log, got %q want %q", log, expected) + } + + // Request with an unauthorized user + req.URL.User = url.User("kamil") + + buf.Reset() + writeCombinedLog(buf, req, *req.URL, ts, http.StatusUnauthorized, 500) + log = buf.String() + + expected = "192.168.100.5 - kamil [26/May/1983:03:30:45 +0200] \"GET / HTTP/1.1\" 401 500 \"http://example.com\" " + + "\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) " + + "AppleWebKit/537.33 (KHTML, like Gecko) Chrome/27.0.1430.0 Safari/537.33\"\n" + if log != expected { + t.Fatalf("wrong log, got %q want %q", log, expected) + } + + // Test with remote ipv6 address + req.RemoteAddr = "::1" + + buf.Reset() + writeCombinedLog(buf, req, *req.URL, ts, http.StatusOK, 100) + log = buf.String() + + expected = "::1 - kamil [26/May/1983:03:30:45 +0200] \"GET / HTTP/1.1\" 200 100 \"http://example.com\" " + + "\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) " + + "AppleWebKit/537.33 (KHTML, like Gecko) Chrome/27.0.1430.0 Safari/537.33\"\n" + if log != expected { + t.Fatalf("wrong log, got %q want %q", log, expected) + } + + // Test remote ipv6 addr, with port + req.RemoteAddr = net.JoinHostPort("::1", "65000") + + buf.Reset() + writeCombinedLog(buf, req, *req.URL, ts, http.StatusOK, 100) + log = buf.String() + + expected = "::1 - kamil [26/May/1983:03:30:45 +0200] \"GET / HTTP/1.1\" 200 100 \"http://example.com\" " + + "\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) " + + "AppleWebKit/537.33 (KHTML, like Gecko) Chrome/27.0.1430.0 Safari/537.33\"\n" + if log != expected { + t.Fatalf("wrong log, got %q want %q", log, expected) + } +} + +func TestLogPathRewrites(t *testing.T) { + var buf bytes.Buffer + + handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + req.URL.Path = "/" // simulate http.StripPrefix and friends + w.WriteHeader(200) + }) + logger := LoggingHandler(&buf, handler) + + logger.ServeHTTP(httptest.NewRecorder(), newRequest("GET", "/subdir/asdf")) + + if !strings.Contains(buf.String(), "GET /subdir/asdf HTTP") { + t.Fatalf("Got log %#v, wanted substring %#v", buf.String(), "GET /subdir/asdf HTTP") + } +} + +func BenchmarkWriteLog(b *testing.B) { + loc, err := time.LoadLocation("Europe/Warsaw") + if err != nil { + b.Fatalf(err.Error()) + } + ts := time.Date(1983, 05, 26, 3, 30, 45, 0, loc) + + req := newRequest("GET", "http://example.com") + req.RemoteAddr = "192.168.100.5" + + b.ResetTimer() + + buf := &bytes.Buffer{} + for i := 0; i < b.N; i++ { + buf.Reset() + writeLog(buf, req, *req.URL, ts, http.StatusUnauthorized, 500) + } +} + +func TestContentTypeHandler(t *testing.T) { + tests := []struct { + Method string + AllowContentTypes []string + ContentType string + Code int + }{ + {"POST", []string{"application/json"}, "application/json", http.StatusOK}, + {"POST", []string{"application/json", "application/xml"}, "application/json", http.StatusOK}, + {"POST", []string{"application/json"}, "application/json; charset=utf-8", http.StatusOK}, + {"POST", []string{"application/json"}, "application/json+xxx", http.StatusUnsupportedMediaType}, + {"POST", []string{"application/json"}, "text/plain", http.StatusUnsupportedMediaType}, + {"GET", []string{"application/json"}, "", http.StatusOK}, + {"GET", []string{}, "", http.StatusOK}, + } + for _, test := range tests { + r, err := http.NewRequest(test.Method, "/", nil) + if err != nil { + t.Error(err) + continue + } + + h := ContentTypeHandler(okHandler, test.AllowContentTypes...) + r.Header.Set("Content-Type", test.ContentType) + w := httptest.NewRecorder() + h.ServeHTTP(w, r) + if w.Code != test.Code { + t.Errorf("expected %d, got %d", test.Code, w.Code) + } + } +} + +func TestHTTPMethodOverride(t *testing.T) { + var tests = []struct { + Method string + OverrideMethod string + ExpectedMethod string + }{ + {"POST", "PUT", "PUT"}, + {"POST", "PATCH", "PATCH"}, + {"POST", "DELETE", "DELETE"}, + {"PUT", "DELETE", "PUT"}, + {"GET", "GET", "GET"}, + {"HEAD", "HEAD", "HEAD"}, + {"GET", "PUT", "GET"}, + {"HEAD", "DELETE", "HEAD"}, + } + + for _, test := range tests { + h := HTTPMethodOverrideHandler(okHandler) + reqs := make([]*http.Request, 0, 2) + + rHeader, err := http.NewRequest(test.Method, "/", nil) + if err != nil { + t.Error(err) + } + rHeader.Header.Set(HTTPMethodOverrideHeader, test.OverrideMethod) + reqs = append(reqs, rHeader) + + f := url.Values{HTTPMethodOverrideFormKey: []string{test.OverrideMethod}} + rForm, err := http.NewRequest(test.Method, "/", strings.NewReader(f.Encode())) + if err != nil { + t.Error(err) + } + rForm.Header.Set("Content-Type", "application/x-www-form-urlencoded") + reqs = append(reqs, rForm) + + for _, r := range reqs { + w := httptest.NewRecorder() + h.ServeHTTP(w, r) + if r.Method != test.ExpectedMethod { + t.Errorf("Expected %s, got %s", test.ExpectedMethod, r.Method) + } + } + } +} diff --git a/vendor/github.com/gorilla/handlers/proxy_headers_test.go b/vendor/github.com/gorilla/handlers/proxy_headers_test.go new file mode 100644 index 000000000..85282ef7d --- /dev/null +++ b/vendor/github.com/gorilla/handlers/proxy_headers_test.go @@ -0,0 +1,100 @@ +package handlers + +import ( + "net/http" + "net/http/httptest" + "testing" +) + +type headerTable struct { + key string // header key + val string // header val + expected string // expected result +} + +func TestGetIP(t *testing.T) { + headers := []headerTable{ + {xForwardedFor, "8.8.8.8", "8.8.8.8"}, // Single address + {xForwardedFor, "8.8.8.8, 8.8.4.4", "8.8.8.8"}, // Multiple + {xForwardedFor, "[2001:db8:cafe::17]:4711", "[2001:db8:cafe::17]:4711"}, // IPv6 address + {xForwardedFor, "", ""}, // None + {xRealIP, "8.8.8.8", "8.8.8.8"}, // Single address + {xRealIP, "8.8.8.8, 8.8.4.4", "8.8.8.8, 8.8.4.4"}, // Multiple + {xRealIP, "[2001:db8:cafe::17]:4711", "[2001:db8:cafe::17]:4711"}, // IPv6 address + {xRealIP, "", ""}, // None + {forwarded, `for="_gazonk"`, "_gazonk"}, // Hostname + {forwarded, `For="[2001:db8:cafe::17]:4711`, `[2001:db8:cafe::17]:4711`}, // IPv6 address + {forwarded, `for=192.0.2.60;proto=http;by=203.0.113.43`, `192.0.2.60`}, // Multiple params + {forwarded, `for=192.0.2.43, for=198.51.100.17`, "192.0.2.43"}, // Multiple params + {forwarded, `for="workstation.local",for=198.51.100.17`, "workstation.local"}, // Hostname + } + + for _, v := range headers { + req := &http.Request{ + Header: http.Header{ + v.key: []string{v.val}, + }} + res := getIP(req) + if res != v.expected { + t.Fatalf("wrong header for %s: got %s want %s", v.key, res, + v.expected) + } + } +} + +func TestGetScheme(t *testing.T) { + headers := []headerTable{ + {xForwardedProto, "https", "https"}, + {xForwardedProto, "http", "http"}, + {xForwardedProto, "HTTP", "http"}, + {forwarded, `For="[2001:db8:cafe::17]:4711`, ""}, // No proto + {forwarded, `for=192.0.2.43, for=198.51.100.17;proto=https`, "https"}, // Multiple params before proto + {forwarded, `for=172.32.10.15; proto=https;by=127.0.0.1`, "https"}, // Space before proto + {forwarded, `for=192.0.2.60;proto=http;by=203.0.113.43`, "http"}, // Multiple params + } + + for _, v := range headers { + req := &http.Request{ + Header: http.Header{ + v.key: []string{v.val}, + }, + } + res := getScheme(req) + if res != v.expected { + t.Fatalf("wrong header for %s: got %s want %s", v.key, res, + v.expected) + } + } +} + +// Test the middleware end-to-end +func TestProxyHeaders(t *testing.T) { + rr := httptest.NewRecorder() + r := newRequest("GET", "/") + + r.Header.Set(xForwardedFor, "8.8.8.8") + r.Header.Set(xForwardedProto, "https") + + var addr string + var proto string + ProxyHeaders(http.HandlerFunc( + func(w http.ResponseWriter, r *http.Request) { + addr = r.RemoteAddr + proto = r.URL.Scheme + })).ServeHTTP(rr, r) + + if rr.Code != http.StatusOK { + t.Fatalf("bad status: got %d want %d", rr.Code, http.StatusOK) + } + + if addr != r.Header.Get(xForwardedFor) { + t.Fatalf("wrong address: got %s want %s", addr, + r.Header.Get(xForwardedFor)) + } + + if proto != r.Header.Get(xForwardedProto) { + t.Fatalf("wrong address: got %s want %s", proto, + r.Header.Get(xForwardedProto)) + } + +} diff --git a/vendor/github.com/gorilla/handlers/recovery_test.go b/vendor/github.com/gorilla/handlers/recovery_test.go new file mode 100644 index 000000000..1ae0e5805 --- /dev/null +++ b/vendor/github.com/gorilla/handlers/recovery_test.go @@ -0,0 +1,44 @@ +package handlers + +import ( + "bytes" + "log" + "net/http" + "net/http/httptest" + "strings" + "testing" +) + +func TestRecoveryLoggerWithDefaultOptions(t *testing.T) { + var buf bytes.Buffer + log.SetOutput(&buf) + + handler := RecoveryHandler() + handlerFunc := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + panic("Unexpected error!") + }) + + recovery := handler(handlerFunc) + recovery.ServeHTTP(httptest.NewRecorder(), newRequest("GET", "/subdir/asdf")) + + if !strings.Contains(buf.String(), "Unexpected error!") { + t.Fatalf("Got log %#v, wanted substring %#v", buf.String(), "Unexpected error!") + } +} + +func TestRecoveryLoggerWithCustomLogger(t *testing.T) { + var buf bytes.Buffer + var logger = log.New(&buf, "", log.LstdFlags) + + handler := RecoveryHandler(RecoveryLogger(logger), PrintRecoveryStack(false)) + handlerFunc := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + panic("Unexpected error!") + }) + + recovery := handler(handlerFunc) + recovery.ServeHTTP(httptest.NewRecorder(), newRequest("GET", "/subdir/asdf")) + + if !strings.Contains(buf.String(), "Unexpected error!") { + t.Fatalf("Got log %#v, wanted substring %#v", buf.String(), "Unexpected error!") + } +} |