Echo website
Features I liked about Echo
- Middleware
- Data binding
Tutorial
Routing
e.POST("/users", saveUser) e.GET("/users/:id", getUser) e.PUT("/users/:id", updateUser) e.DELETE("/users/:id", deleteUser)
Get :id by Param
// e.GET("/users/:id", getUser) func getUser(c echo.Context) error { // User ID from path `users/:id` id := c.Param("id") return c.String(http.StatusOK, id) }
Browse to http://localhost:1323/users/Joe and you should see ‘Joe’ on the page.
Query parameters
/show?team=x-men&member=wolverine
//e.GET("/show", show) func show(c echo.Context) error { // Get team and member from the query string team := c.QueryParam("team") member := c.QueryParam("member") return c.String(http.StatusOK, "team:" + team + ", member:" + member) }
Browse to http://localhost:1323/show?team=x-men&member=wolverine and you should see ’team:x-men, member:wolverine’ on the page.
Post
Form application/x-www-form-urlencoded
POST
/save
name | value |
name | Joe Smith |
email |
// e.POST("/save", save) func save(c echo.Context) error { // Get name and email name := c.FormValue("name") email := c.FormValue("email") return c.String(http.StatusOK, "name:" + name + ", email:" + email) }
Form multipart/form-data
POST
/save
name | value |
name | Joe Smith |
avatar | avatar |
Assume avator value is File
func save(c echo.Context) error { // Get name name := c.FormValue("name") // Get avatar avatar, err := c.FormFile("avatar") if err != nil { return err } // Source src, err := avatar.Open() if err != nil { return err } defer src.Close() // Destination dst, err := os.Create(avatar.Filename) if err != nil { return err } defer dst.Close() // Copy if _, err = io.Copy(dst, src); err != nil { return err } return c.HTML(http.StatusOK, "<b>Thank you! " + name + "</b>") }
Handling request
Handling all JSON, x-www-form-urlencoded, and form-data is annoying, but it can be handled at once by following the code.
- Bind
json
,xml
,form
orquery
payload into Go struct based onContent-Type
request header.
- Render response as
json
orxml
with status code.
type User struct { Name string `json:"name" xml:"name" form:"name" query:"name"` Email string `json:"email" xml:"email" form:"email" query:"email"` } e.POST("/users", func(c echo.Context) error { u := new(User) if err := c.Bind(u); err != nil { return err } return c.JSON(http.StatusCreated, u) // or // return c.XML(http.StatusCreated, u) })
Middleware
List of middlewares →
// Root level middleware e.Use(middleware.Logger()) e.Use(middleware.Recover())
Response
JSON response
In CRUD API, we usually use JSON response.
// User type User struct { Name string `json:"name" xml:"name"` Email string `json:"email" xml:"email"` } // Handler func(c echo.Context) error { u := &User{ Name: "Jon", Email: "jon@labstack.com", } return c.JSON(http.StatusOK, u) }
Stream JSON ?
Pretty
You can see JSON prettified by adding ?pretty at the end of url
Context#JSON()
internally uses json.Marshal
which may not be efficient to large JSON, in that case you can directly stream JSON.Jaeger
Prometheus
Timeout
Set timeout to 30 seconds.
e := echo.New() e.Use(middleware.TimeoutWithConfig(middleware.TimeoutConfig{ Skipper: Skipper, ErrorHandler: func(err error, e echo.Context) error { // you can handle your error here, the returning error will be // passed down the middleware chain return err }, Timeout: 30*time.Second, }))
Rate limiter
To add a rate limit to your application simply add the
RateLimiter
middlware. The example below will limit the application to 20 requests/sec using the default in-memory store:e.Use(middleware.RateLimiter(middleware.NewRateLimiterMemoryStore(20)))