// NewDispatcher creates a dispatcher for the given base pattern and config. func NewDispatcher(pattern string, c Config) Dispatcher { if !strings.HasSuffix(pattern, "/") { panic("The dispatcher pattern has to end with a '/'") } d := Dispatcher{ Pattern: pattern, Context: context.NewContext(), Config: c, Logger: NewStandardLogger(os.Stderr, "", 0), trie: NewTrie(), middleware: make(map[string]Middleware), } return d }
func TestErrorHandler(t *testing.T) { c := context.NewContext() mw := Error{} h := mw.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { panic("Test") }), c) r, _ := http.NewRequest("GET", "http://localhost:8080", nil) rec := httptest.NewRecorder() h.ServeHTTP(rec, r) if rec.Code != http.StatusInternalServerError { t.Fatalf("Expected response code to be %d, got %d\n", http.StatusInternalServerError, rec.Code) } if rec.Body.String() != "Internal Server Error" { t.Fatalf("Expected ISE message, got '%s'\n", rec.Body.String()) } mw = Error{ShowStack: true} h = mw.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { panic("Test") }), c) rec = httptest.NewRecorder() h.ServeHTTP(rec, r) if rec.Code != http.StatusInternalServerError { t.Fatalf("Expected response code to be %d, got %d\n", http.StatusInternalServerError, rec.Code) } if !strings.HasPrefix(rec.Body.String(), fmt.Sprintf("%s - %s", time.Now().Format(dateFormat), "Test")) { t.Fatalf("Expected ISE message, got '%s'\n", rec.Body.String()) } }
func TestGzipHandler(t *testing.T) { c := context.NewContext() mw := Gzip{} testContent := []byte("Test this string") buf := new(bytes.Buffer) gz := gzip.NewWriter(buf) if _, err := gz.Write(testContent); err != nil { t.Fatal(err) } gz.Close() gzippedContent := buf.Bytes() h := mw.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write(testContent) }), c) r, _ := http.NewRequest("GET", "http://localhost:8080", nil) rec := httptest.NewRecorder() h.ServeHTTP(rec, r) if !bytes.Equal(rec.Body.Bytes(), testContent) { t.Fatalf("Expected '%s', got '%s'\n", rec.Body.String(), string(testContent[:])) } r.Header.Set("Accept-Encoding", "gzip") rec = httptest.NewRecorder() h.ServeHTTP(rec, r) if !bytes.Equal(rec.Body.Bytes(), gzippedContent) { t.Fatalf("Expected '%s', got '%s'\n", rec.Body.String(), string(gzippedContent[:])) } }
func TestSessionHandler(t *testing.T) { c := context.NewContext() mw := Session{ Path: path.Join(os.TempDir(), "session"), Secret: secret, MaxAge: "1s", CleanupInterval: "1s", CleanupMaxAge: "1s", } h := mw.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { }), c) r, _ := http.NewRequest("GET", "http://localhost:8080/some/url", nil) rec := httptest.NewRecorder() c.Set(r, context.BaseCtxKey("r"), r) c.Set(r, context.BaseCtxKey("lang"), "en") h.ServeHTTP(rec, r) var cookie string if s, ok := c.Get(r, context.BaseCtxKey("session")); ok { sess := s.(context.Session) if sess.MaxAge() != time.Second { t.Fatalf("Expected Session.MaxAge to be '%s', got '%s'\n", time.Second, sess.MaxAge()) } if err := sess.Write(rec); err != nil { t.Fatal(err) } sess.Set("foo", "bar") cookie = rec.Header().Get("Set-Cookie") } else { t.Fatalf("Expected a new session") } if ft, ok := c.Get(r, context.BaseCtxKey("firstTimer")); ok { if !ft.(bool) { t.Fatalf("Expected a true first-timer flag") } } else { t.Fatalf("Expected a first-timer flag") } time.Sleep(2 * time.Second) r, _ = http.NewRequest("GET", "http://localhost:8080/some/url", nil) rec = httptest.NewRecorder() r.Header.Set("Cookie", cookie[:strings.Index(cookie, ";")]) h.ServeHTTP(rec, r) if ft, ok := c.Get(r, context.BaseCtxKey("firstTimer")); ok { if ft.(bool) { t.Fatalf("Expected a false first-timer flag") } } else { t.Fatalf("Expected a first-timer flag") } sess, _ := c.Get(r, context.BaseCtxKey("session")) if _, ok := sess.(context.Session).Get("foo"); ok { t.Fatalf("Expected the session to be empty") } }
func TestContextUtil(t *testing.T) { c := context.NewContext() r, _ := http.NewRequest("GET", "http://localhost:8080", nil) conf := GetConfig(c) if fmt.Sprintf("%v", conf) != fmt.Sprintf("%v", Config{}) { t.Fatalf("Expected a an empty Config, got %v\n", conf) } conf.Server.Address = "127.0.0.1" c.SetGlobal(context.BaseCtxKey("config"), conf) conf = GetConfig(c) if conf.Server.Address != "127.0.0.1" { t.Fatalf("Expected Server.Address to be '127.0.0.1', got '%s'\n", conf.Server.Address) } params := GetParams(c, r) if len(params) != 0 { t.Fatalf("Expected empty params, got %v\n", params) } params["foo"] = "bar" c.Set(r, context.BaseCtxKey("params"), params) params = GetParams(c, r) if len(params) != 1 { t.Fatalf("Expected params with 1 entry, got %v\n", params) } if v := params["foo"]; v != "bar" { t.Fatalf("Expected param value for 'foo' to be 'bar', got %s\n", v) } sess := GetSession(c, r) if sess.Name() == "" { t.Fatalf("Expected a non-empty session name\n") } if len(sess.GetAll()) != 0 { t.Fatalf("Expected an empty session, got %v\n", sess.GetAll()) } sess.Set("foo", "bar") uuid := sess.Name() c.Set(r, context.BaseCtxKey("session"), sess) sess = GetSession(c, r) if sess.Name() != uuid { t.Fatalf("Expected Session.Name '%s', got '%s'\n", uuid, sess.Name()) } if v, ok := sess.Get("foo"); ok { if v != "bar" { t.Fatalf("Expected the value for session key 'foo' to be 'bar', got '%v'\n", v) } } else { t.Fatalf("Expected the session to have a value for key 'foo'\n") } lang := GetLanguage(c, r) if lang != GetFallbackLanguage(c, r) { t.Fatalf("Expected lang to be '%s', got '%s'\n", GetFallbackLanguage(c, r), lang) } c.Set(r, context.BaseCtxKey("lang"), "ZZ") lang = GetLanguage(c, r) if lang != "ZZ" { t.Fatalf("Expected lang to be 'ZZ', got '%s'\n", lang) } ren := GetRenderer(c) if ren == nil { t.Fatalf("Expected a non-nil renderer\n") } log := GetLogger(c) if log == nil { t.Fatalf("Expected a non-nill logger\n") } r, _ = http.NewRequest("GET", "http://localhost:8080", nil) conf = GetConfig(c) if conf.Server.Address != "127.0.0.1" { t.Fatalf("Expected Server.Address to be '127.0.0.1', got '%s'\n", conf.Server.Address) } params = GetParams(c, r) if len(params) != 0 { t.Fatalf("Expected empty params, got %v\n", params) } }
func TestStaticHandler(t *testing.T) { c := context.NewContext() mw := Static{ Path: "testdata", } h := mw.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("test")) }), c) r, _ := http.NewRequest("GET", "http://localhost:8080/en.all.json", nil) r.RequestURI = "/en.all.json" rec := httptest.NewRecorder() h.ServeHTTP(rec, r) expected := []byte("test") if !bytes.Equal(rec.Body.Bytes(), expected) { t.Fatalf("Expected '%s', got '%s'\n", expected, rec.Body.Bytes()) } h = mw.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNotFound) }), c) r, _ = http.NewRequest("GET", "http://localhost:8080/en.all.json", nil) r.RequestURI = "/en.all.json" rec = httptest.NewRecorder() h.ServeHTTP(rec, r) expected, _ = ioutil.ReadFile(path.Join("testdata", "en.all.json")) if !bytes.Equal(rec.Body.Bytes(), expected) { t.Fatalf("Expected '%s', got '%s'\n", expected, rec.Body.Bytes()) } f, _ := os.Open(path.Join("testdata", "en.all.json")) defer f.Close() stat, _ := f.Stat() lm := rec.Header().Get("Last-Modified") if lm != stat.ModTime().UTC().Format(http.TimeFormat) { t.Fatalf("Expected the Last-Modified header to be set to the file modtime of '%s', got '%s'\n", stat.ModTime().UTC().Format(http.TimeFormat), lm) } etag := rec.Header().Get("ETag") hash := sha256.Sum256([]byte(fmt.Sprintf("%s-%d", path.Join("/", "en.all.json"), stat.ModTime().Unix()))) expectedStr := base64.URLEncoding.EncodeToString(hash[:]) if etag != expectedStr { t.Fatalf("Expected ETag to be '%s', got '%s'\n", expectedStr, etag) } cc := rec.Header().Get("Cache-Control") if cc != "" { t.Fatalf("Expected an empty Cache-Control header, got '%s'\n", cc) } exp := rec.Header().Get("Expires") if exp != "" { t.Fatalf("Expected an empty Expires header, got '%s'\n", exp) } r, _ = http.NewRequest("GET", "http://localhost:8080/dummy", nil) r.RequestURI = "/dummy" rec = httptest.NewRecorder() h.ServeHTTP(rec, r) if rec.Code != http.StatusFound { t.Fatalf("Expected code to be '%d', got '%d'\n", http.StatusFound, rec.Code) } r, _ = http.NewRequest("GET", "http://localhost:8080/dummy/", nil) r.RequestURI = "/dummy/" rec = httptest.NewRecorder() h.ServeHTTP(rec, r) if rec.Code != http.StatusNotFound { t.Fatalf("Expected code to be '%d', got '%d'\n", http.StatusNotFound, rec.Code) } mw = Static{ Path: "testdata", Index: "dummy", } h = mw.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNotFound) }), c) r, _ = http.NewRequest("GET", "http://localhost:8080/dummy/", nil) r.RequestURI = "/dummy/" rec = httptest.NewRecorder() h.ServeHTTP(rec, r) if rec.Code != http.StatusOK { t.Fatalf("Expected code to be '%d', got '%d'\n", http.StatusOK, rec.Code) } expected, _ = ioutil.ReadFile(path.Join("testdata", "dummy", "dummy")) if !bytes.Equal(rec.Body.Bytes(), expected) { t.Fatalf("Expected '%s', got '%s'\n", expected, rec.Body.Bytes()) } mw = Static{ Path: "testdata", Prefix: "/test", } h = mw.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNotFound) }), c) r, _ = http.NewRequest("GET", "http://localhost:8080/en.all.json", nil) r.RequestURI = "/en.all.json" rec = httptest.NewRecorder() h.ServeHTTP(rec, r) if rec.Code != http.StatusNotFound { t.Fatalf("Expected code to be '%d', got '%d'\n", http.StatusNotFound, rec.Code) } r, _ = http.NewRequest("GET", "http://localhost:8080/test/en.all.json", nil) r.RequestURI = "/test/en.all.json" rec = httptest.NewRecorder() h.ServeHTTP(rec, r) if rec.Code != http.StatusOK { t.Fatalf("Expected code to be '%d', got '%d'\n", http.StatusOK, rec.Code) } expected, _ = ioutil.ReadFile(path.Join("testdata", "en.all.json")) if !bytes.Equal(rec.Body.Bytes(), expected) { t.Fatalf("Expected '%s', got '%s'\n", expected, rec.Body.Bytes()) } mw = Static{ Path: "testdata", Expires: "1s", } h = mw.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNotFound) }), c) r, _ = http.NewRequest("GET", "http://localhost:8080/en.all.json", nil) r.RequestURI = "/en.all.json" rec = httptest.NewRecorder() h.ServeHTTP(rec, r) if rec.Code != http.StatusOK { t.Fatalf("Expected code to be '%d', got '%d'\n", http.StatusOK, rec.Code) } cc = rec.Header().Get("Cache-Control") if cc != "max-age=1" { t.Fatalf("Expected Cache-Control to be 'max-age=1' header, got '%s'\n", cc) } exp = rec.Header().Get("Expires") d, _ := time.ParseDuration("1s") expectedStr = time.Now().Add(d).Format(http.TimeFormat) if exp != expectedStr { t.Fatalf("Expected Expires to be '%s', got '%s'\n", expectedStr, exp) } mw = Static{ Path: "testdata", Index: "dummy", FileList: true, } h = mw.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNotFound) }), c) r, _ = http.NewRequest("GET", "http://localhost:8080/dummy/", nil) r.RequestURI = "/dummy/" rec = httptest.NewRecorder() h.ServeHTTP(rec, r) if rec.Code != http.StatusOK { t.Fatalf("Expected code to be '%d', got '%d'\n", http.StatusOK, rec.Code) } expected, _ = ioutil.ReadFile(path.Join("testdata", "dummy", "dummy")) if !bytes.Equal(rec.Body.Bytes(), expected) { t.Fatalf("Expected '%s', got '%s'\n", expected, rec.Body.Bytes()) } r, _ = http.NewRequest("GET", "http://localhost:8080/", nil) r.RequestURI = "/" rec = httptest.NewRecorder() h.ServeHTTP(rec, r) if rec.Code != http.StatusOK { t.Fatalf("Expected code to be '%d', got '%d'\n", http.StatusOK, rec.Code) } expectedStr = `<a href="../">../</a>` if !strings.Contains(rec.Body.String(), expectedStr) { t.Fatalf("Expected file list to contain '%s', got '%s'\n", expectedStr, rec.Body.String()) } expectedStr = `<a href="bg.all.json">bg.all.json</a>` if !strings.Contains(rec.Body.String(), expectedStr) { t.Fatalf("Expected file list to contain '%s', got '%s'\n", expectedStr, rec.Body.String()) } expectedStr = `<a href="en.all.json">en.all.json</a>` if !strings.Contains(rec.Body.String(), expectedStr) { t.Fatalf("Expected file list to contain '%s', got '%s'\n", expectedStr, rec.Body.String()) } expectedStr = `<a href="dummy/">dummy/</a>` if !strings.Contains(rec.Body.String(), expectedStr) { t.Fatalf("Expected file list to contain '%s', got '%s'\n", expectedStr, rec.Body.String()) } }
func TestI18NHandler(t *testing.T) { c := context.NewContext() ren := renderer.NewRenderer("testdata", "test.tmpl") c.SetGlobal(context.BaseCtxKey("renderer"), ren) mw := I18N{ Languages: []string{"en", "bg"}, Pattern: "/", Dir: "testdata", IgnoreURLPrefix: []string{"/css", "/js"}, } h := mw.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if err := ren.Render(w, nil, c.GetAll(r), "test_i18n.tmpl"); err != nil { t.Fatal(err) } }), c) r, _ := http.NewRequest("GET", "http://localhost:8080", nil) rec := httptest.NewRecorder() h.ServeHTTP(rec, r) if rec.Code != http.StatusFound { t.Fatalf("Expected code %d, got %d\n", http.StatusFound, rec.Code) } r, _ = http.NewRequest("GET", "http://localhost:8080/bg/", nil) r.RequestURI = "/bg/" rec = httptest.NewRecorder() h.ServeHTTP(rec, r) if rec.Code != http.StatusOK { t.Fatalf("Expected code %d, got %d\n", http.StatusOK, rec.Code) } expected := "test data bg" if !strings.Contains(rec.Body.String(), expected) { t.Fatalf("Expected body '%s' to contain '%s'\n", rec.Body.String(), expected) } r, _ = http.NewRequest("GET", "http://localhost:8080/en/", nil) r.RequestURI = "/en/" rec = httptest.NewRecorder() s := context.NewSession([]byte(""), nil, os.TempDir()) s.SetName("test1") c.Set(r, context.BaseCtxKey("session"), s) h.ServeHTTP(rec, r) if rec.Code != http.StatusOK { t.Fatalf("Expected code %d, got %d\n", http.StatusOK, rec.Code) } expected = "test data en" if !strings.Contains(rec.Body.String(), expected) { t.Fatalf("Expected body '%s' to contain '%s'\n", rec.Body.String(), expected) } if s, ok := s.Get("language"); ok { if s.(string) != "en" { t.Fatalf("Expected session.language to be '%s', got '%s'\n", "en", s.(string)) } } else { t.Fatalf("Expected the session to have a language key\n") } r, _ = http.NewRequest("GET", "http://localhost:8080/en", nil) r.RequestURI = "/en" rec = httptest.NewRecorder() h.ServeHTTP(rec, r) if rec.Code != http.StatusFound { t.Fatalf("Expected code %d, got %d\n", http.StatusFound, rec.Code) } expected = "/en/" if rec.Header().Get("Location") != expected { t.Fatalf("Expected a redirect to '%s', got '%s'\n", expected, rec.Header().Get("Location")) } r, _ = http.NewRequest("GET", "http://localhost:8080/foo/bar/baz", nil) r.RequestURI = "/foo/bar/baz" rec = httptest.NewRecorder() h.ServeHTTP(rec, r) if rec.Code != http.StatusFound { t.Fatalf("Expected code %d, got %d\n", http.StatusFound, rec.Code) } expected = "/en/foo/bar/baz" if rec.Header().Get("Location") != expected { t.Fatalf("Expected a redirect to '%s', got '%s'\n", expected, rec.Header().Get("Location")) } r, _ = http.NewRequest("GET", "http://localhost:8080/foo/bar/baz?alpha=beta&gamma=delta", nil) r.RequestURI = "/foo/bar/baz?alpha=beta&gamma=delta" rec = httptest.NewRecorder() h.ServeHTTP(rec, r) if rec.Code != http.StatusFound { t.Fatalf("Expected code %d, got %d\n", http.StatusFound, rec.Code) } expected = "/en/foo/bar/baz?alpha=beta&gamma=delta" if rec.Header().Get("Location") != expected { t.Fatalf("Expected a redirect to '%s', got '%s'\n", expected, rec.Header().Get("Location")) } r, _ = http.NewRequest("GET", "http://localhost:8080/foo/bar/baz?alpha=beta&gamma=delta#test", nil) r.RequestURI = "/foo/bar/baz?alpha=beta&gamma=delta#test" rec = httptest.NewRecorder() h.ServeHTTP(rec, r) if rec.Code != http.StatusFound { t.Fatalf("Expected code %d, got %d\n", http.StatusFound, rec.Code) } expected = "/en/foo/bar/baz?alpha=beta&gamma=delta#test" if rec.Header().Get("Location") != expected { t.Fatalf("Expected a redirect to '%s', got '%s'\n", expected, rec.Header().Get("Location")) } r, _ = http.NewRequest("GET", "http://localhost:8080/css/foo", nil) r.RequestURI = "/css/foo" rec = httptest.NewRecorder() h = mw.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { }), c) h.ServeHTTP(rec, r) if rec.Code != http.StatusOK { t.Fatalf("Expected code %d, got %d\n", http.StatusOK, rec.Code) } r, _ = http.NewRequest("GET", "http://localhost:8080/js/foo", nil) r.RequestURI = "/js/foo" rec = httptest.NewRecorder() h.ServeHTTP(rec, r) if rec.Code != http.StatusOK { t.Fatalf("Expected code %d, got %d\n", http.StatusOK, rec.Code) } }