Example #1
0
// 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
}
Example #2
0
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())
	}
}
Example #3
0
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[:]))
	}

}
Example #4
0
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")
	}

}
Example #5
0
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)
	}
}
Example #6
0
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())
	}
}
Example #7
0
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)
	}
}