func TestGzip(t *testing.T) { req, _ := http.NewRequest(echo.GET, "/", nil) rec := httptest.NewRecorder() c := echo.NewContext(req, echo.NewResponse(rec), echo.New()) h := func(c *echo.Context) error { return c.String(http.StatusOK, "test") } // Skip if no Accept-Encoding header Gzip()(h)(c) assert.Equal(t, http.StatusOK, rec.Code) assert.Equal(t, "test", rec.Body.String()) // Gzip req, _ = http.NewRequest(echo.GET, "/", nil) req.Header.Set(echo.AcceptEncoding, "gzip") rec = httptest.NewRecorder() c = echo.NewContext(req, echo.NewResponse(rec), echo.New()) Gzip()(h)(c) assert.Equal(t, http.StatusOK, rec.Code) assert.Equal(t, "gzip", rec.Header().Get(echo.ContentEncoding)) r, err := gzip.NewReader(rec.Body) defer r.Close() if assert.NoError(t, err) { buf := new(bytes.Buffer) buf.ReadFrom(r) assert.Equal(t, "test", buf.String()) } }
func TestStripTrailingSlash(t *testing.T) { req, _ := http.NewRequest(echo.GET, "/users/", nil) rec := httptest.NewRecorder() c := echo.NewContext(req, echo.NewResponse(rec), echo.New()) StripTrailingSlash()(c) assert.Equal(t, "/users", c.Request().URL.Path) }
func TestRedirectToSlash(t *testing.T) { req, _ := http.NewRequest(echo.GET, "/users", nil) rec := httptest.NewRecorder() c := echo.NewContext(req, echo.NewResponse(rec), echo.New()) RedirectToSlash(RedirectToSlashOptions{Code: http.StatusTemporaryRedirect})(c) assert.Equal(t, http.StatusTemporaryRedirect, rec.Code) assert.Equal(t, "/users/", c.Response().Header().Get("Location")) }
func main() { e := echo.New() e.Use(mw.Logger()) e.WebSocket("/ws", func(c *echo.Context) error { io.Copy(c.Socket(), c.Socket()) return nil }) e.Run(":1323") }
func TestJWTAuth(t *testing.T) { req, _ := http.NewRequest(echo.GET, "/", nil) rec := httptest.NewRecorder() c := echo.NewContext(req, echo.NewResponse(rec), echo.New()) key := []byte("key") fn := func(kid string, method jwt.SigningMethod) ([]byte, error) { return key, nil } ja := JWTAuth(fn) token := jwt.New(jwt.SigningMethodHS256) token.Claims["foo"] = "bar" token.Claims["exp"] = time.Now().Add(time.Hour * 72).Unix() ts, err := token.SignedString(key) assert.NoError(t, err) // Valid credentials auth := Bearer + " " + ts req.Header.Set(echo.Authorization, auth) assert.NoError(t, ja(c)) //--------------------- // Invalid credentials //--------------------- // Expired token token.Claims["exp"] = time.Now().Add(-time.Second).Unix() ts, err = token.SignedString(key) assert.NoError(t, err) auth = Bearer + " " + ts req.Header.Set(echo.Authorization, auth) he := ja(c).(*echo.HTTPError) assert.Equal(t, http.StatusUnauthorized, he.Code()) // Empty Authorization header req.Header.Set(echo.Authorization, "") he = ja(c).(*echo.HTTPError) assert.Equal(t, http.StatusBadRequest, he.Code()) // Invalid Authorization header auth = "token" req.Header.Set(echo.Authorization, auth) he = ja(c).(*echo.HTTPError) assert.Equal(t, http.StatusBadRequest, he.Code()) // Invalid scheme auth = "Bear token" req.Header.Set(echo.Authorization, auth) he = ja(c).(*echo.HTTPError) assert.Equal(t, http.StatusBadRequest, he.Code()) // WebSocket c.Request().Header.Set(echo.Upgrade, echo.WebSocket) assert.NoError(t, ja(c)) }
func TestCORS(t *testing.T) { mw := cors() req := testRequest(nil, "GET", "/", nil) res := httptest.NewRecorder() c := echo.NewContext(req.Request, echo.NewResponse(res), echo.New()) called := false next := func(c *echo.Context) error { called = true return nil } // It calls the next middleware when no origin is set h := mw(next) h(c) assert.True(t, called) assert.Empty(t, res.Header().Get("Access-Control-Allow-Origin")) // It sets CORS headers and calls the next middleware when the origin is set req.Header.Set("Origin", "china") called = false h(c) assert.True(t, called) assert.NotEmpty(t, res.Header().Get("Access-Control-Allow-Origin")) // It sets CORS headers, ends the middleware chain and // returns 200 when receiving a preflight request req.Method = "OPTIONS" res = httptest.NewRecorder() c = echo.NewContext(req.Request, echo.NewResponse(res), echo.New()) res.Code = 0 called = false h(c) assert.False(t, called) assert.Equal(t, 200, res.Code) assert.NotEmpty(t, res.Header().Get("Access-Control-Allow-Origin")) assert.NotEmpty(t, res.Header().Get("Access-Control-Allow-Methods")) assert.NotEmpty(t, res.Header().Get("Access-Control-Allow-Headers")) }
func TestRecover(t *testing.T) { e := echo.New() e.SetDebug(true) req, _ := http.NewRequest(echo.GET, "/", nil) rec := httptest.NewRecorder() c := echo.NewContext(req, echo.NewResponse(rec), e) h := func(c *echo.Context) error { panic("test") } Recover()(h)(c) assert.Equal(t, http.StatusInternalServerError, rec.Code) assert.Contains(t, rec.Body.String(), "panic recover") }
func createRouter() *echo.Echo { r := echo.New() r.SetHTTPErrorHandler(errorHandler) r.Use(mw.Logger()) r.Use(mw.Recover()) r.Use(cors()) r.Use(mw.StripTrailingSlash()) r.Use(auth()) account := r.Group("/account") account.Post("/login", login) account.Get("/ping", ping) account.Get("/settings", getSettings) account.Post("/settings", setSettings) account.Delete("/settings/:id", removeSetting) //account.Get("/takeout") casts := r.Group("/library/casts") casts.Get("", getCasts) casts.Post("", addCast) casts.Put("/:id", renameCast) casts.Delete("/:id", removeCast) episodes := r.Group("/library") episodes.Get("/newepisodes", getNewEpisodes) episodes.Get("/episodes/:castid", getEpisodes) episodes.Get("/episode/:id", getEpisode) episodes.Get("/episodes/label/:label", getEpisodesByLabel) events := r.Group("/library/events") events.Get("", getEvents) events.Post("", addEvents) labels := r.Group("/library/labels") labels.Get("", getLabels) labels.Post("", addLabel) labels.Put("/:id", updateLabel) labels.Delete("/:id", removeLabel) /*opml := r.Group("/library") opml.Get("/casts.opml") opml.Post("/casts.opml")*/ // Perhaps: // /newepisodes -> /episodes?since=0 // /episodes/label/:label -> /episodes?label=label return r }
func main() { // Echo instance e := echo.New() // Middleware e.Use(mw.Logger()) e.Use(mw.Recover()) // Routes e.Get("/", hello) // Start server e.Run(":1323") }
func TestBasicAuth(t *testing.T) { req, _ := http.NewRequest(echo.GET, "/", nil) rec := httptest.NewRecorder() c := echo.NewContext(req, echo.NewResponse(rec), echo.New()) fn := func(u, p string) bool { if u == "joe" && p == "secret" { return true } return false } ba := BasicAuth(fn) // Valid credentials auth := Basic + " " + base64.StdEncoding.EncodeToString([]byte("joe:secret")) req.Header.Set(echo.Authorization, auth) assert.NoError(t, ba(c)) //--------------------- // Invalid credentials //--------------------- // Incorrect password auth = Basic + " " + base64.StdEncoding.EncodeToString([]byte("joe:password")) req.Header.Set(echo.Authorization, auth) he := ba(c).(*echo.HTTPError) assert.Equal(t, http.StatusUnauthorized, he.Code()) // Empty Authorization header req.Header.Set(echo.Authorization, "") he = ba(c).(*echo.HTTPError) assert.Equal(t, http.StatusBadRequest, he.Code()) // Invalid Authorization header auth = base64.StdEncoding.EncodeToString([]byte(" :secret")) req.Header.Set(echo.Authorization, auth) he = ba(c).(*echo.HTTPError) assert.Equal(t, http.StatusBadRequest, he.Code()) // Invalid scheme auth = "Base " + base64.StdEncoding.EncodeToString([]byte(" :secret")) req.Header.Set(echo.Authorization, auth) he = ba(c).(*echo.HTTPError) assert.Equal(t, http.StatusBadRequest, he.Code()) // WebSocket c.Request().Header.Set(echo.Upgrade, echo.WebSocket) assert.NoError(t, ba(c)) }
func main() { e := echo.New() // Middleware e.Use(mw.Logger()) e.Use(mw.Recover()) // Routes e.Post("/users", createUser) e.Get("/users/:id", getUser) e.Patch("/users/:id", updateUser) e.Delete("/users/:id", deleteUser) // Start server e.Run(":1323") }
func main() { e := echo.New() e.Get("/stream", func(c *echo.Context) error { c.Response().Header().Set(echo.ContentType, echo.ApplicationJSON) c.Response().WriteHeader(http.StatusOK) for _, l := range locations { if err := json.NewEncoder(c.Response()).Encode(l); err != nil { return err } c.Response().Flush() time.Sleep(1 * time.Second) } return nil }) e.Run(":1323") }
func main() { // Echo instance e := echo.New() // Debug mode e.SetDebug(true) //------------ // Middleware //------------ // Logger e.Use(mw.Logger()) // Recover e.Use(mw.Recover()) // Basic auth e.Use(mw.BasicAuth(func(usr, pwd string) bool { if usr == "joe" && pwd == "secret" { return true } return false })) //------- // Slash //------- e.Use(mw.StripTrailingSlash()) // or // e.Use(mw.RedirectToSlash()) // Gzip e.Use(mw.Gzip()) // Routes e.Get("/", hello) // Start server e.Run(":1323") }
func TestLogger(t *testing.T) { e := echo.New() req, _ := http.NewRequest(echo.GET, "/", nil) rec := httptest.NewRecorder() c := echo.NewContext(req, echo.NewResponse(rec), e) // Status 2xx h := func(c *echo.Context) error { return c.String(http.StatusOK, "test") } Logger()(h)(c) // Status 3xx rec = httptest.NewRecorder() c = echo.NewContext(req, echo.NewResponse(rec), e) h = func(c *echo.Context) error { return c.String(http.StatusTemporaryRedirect, "test") } Logger()(h)(c) // Status 4xx rec = httptest.NewRecorder() c = echo.NewContext(req, echo.NewResponse(rec), e) h = func(c *echo.Context) error { return c.String(http.StatusNotFound, "test") } Logger()(h)(c) // Status 5xx with empty path req, _ = http.NewRequest(echo.GET, "", nil) rec = httptest.NewRecorder() c = echo.NewContext(req, echo.NewResponse(rec), e) h = func(c *echo.Context) error { return errors.New("error") } Logger()(h)(c) }
func main() { e := echo.New() // Middleware e.Use(mw.Logger()) e.Use(mw.Recover()) e.Use(mw.Gzip()) //------------------------ // Third-party middleware //------------------------ // https://github.com/rs/cors e.Use(cors.Default().Handler) // https://github.com/thoas/stats s := stats.New() e.Use(s.Handler) // Route e.Get("/stats", func(c *echo.Context) error { return c.JSON(http.StatusOK, s.Data()) }) // Serve index file e.Index("public/index.html") // Serve favicon e.Favicon("public/favicon.ico") // Serve static files e.Static("/scripts", "public/scripts") //-------- // Routes //-------- e.Post("/users", createUser) e.Get("/users", getUsers) e.Get("/users/:id", getUser) //----------- // Templates //----------- t := &Template{ // Cached templates templates: template.Must(template.ParseFiles("public/views/welcome.html")), } e.SetRenderer(t) e.Get("/welcome", welcome) //------- // Group //------- // Group with parent middleware a := e.Group("/admin") a.Use(func(c *echo.Context) error { // Security middleware return nil }) a.Get("", func(c *echo.Context) error { return c.String(http.StatusOK, "Welcome admin!") }) // Group with no parent middleware g := e.Group("/files", func(c *echo.Context) error { // Security middleware return nil }) g.Get("", func(c *echo.Context) error { return c.String(http.StatusOK, "Your files!") }) // Start server e.Run(":1323") }