2015-04-24 15:13:06 -07:00
|
|
|
# Guide
|
|
|
|
|
2015-04-28 18:53:57 -07:00
|
|
|
<!---
|
2015-04-25 12:46:27 -07:00
|
|
|
Some info about guide
|
|
|
|
-->
|
|
|
|
|
2015-04-24 15:13:06 -07:00
|
|
|
---
|
|
|
|
|
|
|
|
## Installation
|
|
|
|
|
2015-04-25 12:46:27 -07:00
|
|
|
Echo has been developed and tested using Go `1.4.x`
|
|
|
|
|
2015-04-25 22:32:20 -07:00
|
|
|
Install the latest version of Echo via `go get`
|
2015-04-25 12:46:27 -07:00
|
|
|
|
|
|
|
```sh
|
|
|
|
$ go get github.com/labstack/echo
|
|
|
|
```
|
|
|
|
|
|
|
|
To upgrade
|
2015-04-24 15:13:06 -07:00
|
|
|
|
2015-04-25 12:46:27 -07:00
|
|
|
```sh
|
|
|
|
$ go get -u github.com/labstack/echo
|
|
|
|
```
|
2015-04-24 15:13:06 -07:00
|
|
|
|
2015-05-06 18:49:40 -07:00
|
|
|
Echo follows [semantic versioning](http://semver.org) managed through GitHub releases.
|
2015-04-25 12:46:27 -07:00
|
|
|
Specific version of Echo can be installed using any [package manager](https://github.com/avelino/awesome-go#package-management).
|
2015-04-24 15:13:06 -07:00
|
|
|
|
2015-04-28 18:53:57 -07:00
|
|
|
## Customization
|
2015-04-25 12:46:27 -07:00
|
|
|
|
2015-04-28 18:53:57 -07:00
|
|
|
### Max path parameters
|
2015-04-25 16:10:28 -07:00
|
|
|
|
2015-04-28 18:53:57 -07:00
|
|
|
`echo.MaxParam(n uint8)`
|
2015-04-25 16:10:28 -07:00
|
|
|
|
2015-04-28 18:53:57 -07:00
|
|
|
Sets the maximum number of path parameters allowed for the application.
|
|
|
|
Default value is **5**, [good enough](https://github.com/interagent/http-api-design#minimize-path-nesting)
|
|
|
|
for many use cases. Restricting path parameters allows us to use memory efficiently.
|
|
|
|
|
|
|
|
### Not found handler
|
|
|
|
|
|
|
|
`echo.NotFoundHandler(h Handler)`
|
|
|
|
|
2015-04-28 23:09:30 -07:00
|
|
|
Registers a custom NotFound handler. This handler is called in case router doesn't
|
2015-05-06 15:51:52 -07:00
|
|
|
find a matching route for the HTTP request.
|
2015-04-28 18:53:57 -07:00
|
|
|
|
|
|
|
Default handler sends 404 "Not Found" response.
|
|
|
|
|
|
|
|
### HTTP error handler
|
|
|
|
|
|
|
|
`echo.HTTPErrorHandler(h HTTPErrorHandler)`
|
|
|
|
|
2015-05-06 15:51:52 -07:00
|
|
|
Registers a custom centralized HTTP error handler `func(*HTTPError, *Context)`.
|
|
|
|
|
|
|
|
Default handler sends `HTTPError.Message` HTTP response with `HTTPError.Code` status
|
|
|
|
code.
|
|
|
|
|
|
|
|
- If HTTPError.Code is not specified it uses 500 "Internal Server Error".
|
|
|
|
- If HTTPError.Message is not specified it uses HTTPError.Error.Error() or the status
|
|
|
|
code text.
|
2015-04-24 15:13:06 -07:00
|
|
|
|
|
|
|
## Routing
|
|
|
|
|
2015-04-28 18:53:57 -07:00
|
|
|
Echo's router is [fast, optimized](https://github.com/labstack/echo#benchmark) and
|
|
|
|
flexible. It's based on [redix tree](http://en.wikipedia.org/wiki/Radix_tree)
|
|
|
|
data structure which makes routing lookup really fast. It leverages
|
|
|
|
[sync pool](https://golang.org/pkg/sync/#Pool) to reuse memory and achieve
|
2015-04-29 11:22:07 -07:00
|
|
|
zero dynamic memory allocation with no GC overhead.
|
2015-04-28 18:53:57 -07:00
|
|
|
|
2015-05-10 19:24:35 -07:00
|
|
|
Routes can be registered by specifying HTTP method, path and a handler. For example,
|
|
|
|
code below registers a route for method `GET`, path `/hello` and a handler which sends
|
2015-05-06 15:51:52 -07:00
|
|
|
`Hello!` HTTP response.
|
2015-04-28 18:53:57 -07:00
|
|
|
|
|
|
|
```go
|
2015-05-05 22:06:02 -07:00
|
|
|
echo.Get("/hello", func(*echo.Context) *HTTPError {
|
|
|
|
return c.String(http.StatusOK, "Hello!")
|
2015-04-28 18:53:57 -07:00
|
|
|
})
|
|
|
|
```
|
|
|
|
|
2015-05-05 21:55:49 -07:00
|
|
|
Echo's default handler is `func(*echo.Context) *echo.HTTPError` where `echo.Context`
|
2015-05-06 15:51:52 -07:00
|
|
|
primarily holds HTTP request and response objects. Echo also has a support for other
|
2015-05-05 21:55:49 -07:00
|
|
|
types of handlers.
|
2015-04-28 23:09:30 -07:00
|
|
|
|
|
|
|
<!-- TODO mention about not able to take advantage -->
|
|
|
|
|
2015-05-06 15:51:52 -07:00
|
|
|
### Group
|
|
|
|
|
2015-05-06 18:47:26 -07:00
|
|
|
*WIP*
|
2015-04-28 18:53:57 -07:00
|
|
|
|
2015-05-06 15:51:52 -07:00
|
|
|
### Path parameter
|
2015-04-28 18:53:57 -07:00
|
|
|
|
2015-05-13 23:07:03 -07:00
|
|
|
Request path parameters can be extracted either by name `echo.Context.Param(name string) string`
|
2015-05-10 19:24:35 -07:00
|
|
|
or by index `echo.Context.P(i uint8) string`. Getting parameter by index gives a
|
|
|
|
slightly better performance.
|
2015-04-28 18:53:57 -07:00
|
|
|
|
|
|
|
```go
|
2015-05-05 22:06:02 -07:00
|
|
|
echo.Get("/users/:id", func(c *echo.Context) *HTTPError {
|
2015-04-28 18:53:57 -07:00
|
|
|
// By name
|
|
|
|
id := c.Param("id")
|
|
|
|
|
|
|
|
// By index
|
|
|
|
id := c.P(0)
|
|
|
|
|
2015-05-05 22:06:02 -07:00
|
|
|
return c.String(http.StatusOK, id)
|
2015-04-28 18:53:57 -07:00
|
|
|
})
|
|
|
|
```
|
|
|
|
|
2015-04-28 23:09:30 -07:00
|
|
|
### Match-any
|
2015-04-28 18:53:57 -07:00
|
|
|
|
|
|
|
Matches zero or more characters in the path. For example, pattern `/users/*` will
|
|
|
|
match
|
|
|
|
|
|
|
|
- `/users/`
|
|
|
|
- `/users/1`
|
|
|
|
- `/users/1/files/1`
|
|
|
|
- `/users/anything...`
|
|
|
|
|
|
|
|
### Path matching order
|
2015-04-25 12:46:27 -07:00
|
|
|
|
2015-04-28 18:53:57 -07:00
|
|
|
- Static
|
|
|
|
- Param
|
|
|
|
- Match any
|
|
|
|
|
2015-04-28 23:09:30 -07:00
|
|
|
#### Example
|
|
|
|
|
|
|
|
```go
|
2015-05-05 22:06:02 -07:00
|
|
|
e.Get("/users/:id", func(c *echo.Context) *HTTPError {
|
|
|
|
return c.String(http.StatusOK, "/users/:id")
|
2015-04-28 23:09:30 -07:00
|
|
|
})
|
|
|
|
|
2015-05-05 22:06:02 -07:00
|
|
|
e.Get("/users/new", func(c *echo.Context) *HTTPError {
|
|
|
|
return c.String(http.StatusOK, "/users/new")
|
2015-04-28 23:09:30 -07:00
|
|
|
})
|
|
|
|
|
2015-05-05 22:06:02 -07:00
|
|
|
e.Get("/users/1/files/*", func(c *echo.Context) *HTTPError {
|
|
|
|
return c.String(http.StatusOK, "/users/1/files/*")
|
2015-04-28 23:09:30 -07:00
|
|
|
})
|
|
|
|
```
|
|
|
|
|
|
|
|
Above routes would resolve in order
|
|
|
|
|
|
|
|
- `/users/new`
|
|
|
|
- `/users/:id`
|
|
|
|
- `/users/1/files/*`
|
|
|
|
|
|
|
|
Routes can be written in any order.
|
|
|
|
|
2015-04-28 18:53:57 -07:00
|
|
|
<!-- Different use cases -->
|
|
|
|
|
|
|
|
### URI building
|
|
|
|
|
|
|
|
`echo.URI` can be used generate URI for any handler with specified path parameters.
|
|
|
|
It's helpful to centralize all your URI patterns which ease in refactoring your
|
|
|
|
application.
|
|
|
|
|
|
|
|
`echo.URI(h, 1)` will generate `/users/1` for the route registered below
|
|
|
|
|
|
|
|
```go
|
|
|
|
// Handler
|
2015-05-05 22:06:02 -07:00
|
|
|
h := func(*echo.Context) *HTTPError {
|
|
|
|
return c.String(http.StatusOK, "OK")
|
2015-04-28 18:53:57 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Route
|
|
|
|
e.Get("/users/:id", h)
|
|
|
|
```
|
|
|
|
|
2015-05-14 16:29:26 -07:00
|
|
|
## (Middleware)[https://github.com/labstack/echo/tree/master/examples/middleware]
|
|
|
|
|
|
|
|
*WIP*
|
2015-04-28 18:53:57 -07:00
|
|
|
|
2015-04-28 23:09:30 -07:00
|
|
|
## Response
|
|
|
|
|
|
|
|
### JSON
|
2015-04-25 12:46:27 -07:00
|
|
|
|
2015-05-04 14:00:07 -07:00
|
|
|
```go
|
2015-05-05 22:06:02 -07:00
|
|
|
context.JSON(code int, v interface{}) *HTTPError
|
2015-05-04 14:00:07 -07:00
|
|
|
```
|
|
|
|
|
2015-05-06 15:51:52 -07:00
|
|
|
Sends a JSON HTTP response with status code.
|
2015-04-28 23:09:30 -07:00
|
|
|
|
|
|
|
### String
|
|
|
|
|
2015-05-04 14:00:07 -07:00
|
|
|
```go
|
2015-05-05 22:06:02 -07:00
|
|
|
context.String(code int, s string) *HTTPError
|
2015-05-04 14:00:07 -07:00
|
|
|
```
|
|
|
|
|
2015-05-06 15:51:52 -07:00
|
|
|
Sends a text/plain HTTP response with status code.
|
2015-04-28 23:09:30 -07:00
|
|
|
|
|
|
|
### HTML
|
|
|
|
|
2015-05-04 14:00:07 -07:00
|
|
|
```go
|
2015-05-05 22:06:02 -07:00
|
|
|
func (c *Context) HTML(code int, html string) *HTTPError
|
2015-05-04 14:00:07 -07:00
|
|
|
```
|
|
|
|
|
2015-05-06 15:51:52 -07:00
|
|
|
Sends an HTML HTTP response with status code.
|
2015-04-25 12:46:27 -07:00
|
|
|
|
2015-04-28 18:53:57 -07:00
|
|
|
### Static files
|
|
|
|
|
2015-05-13 15:49:09 -07:00
|
|
|
`echo.Static(path, root string)` serves static files. For example, code below serves
|
2015-05-13 23:07:03 -07:00
|
|
|
files from directory `public/scripts` for any request path starting with `/scripts/`.
|
2015-04-28 18:53:57 -07:00
|
|
|
|
|
|
|
```go
|
2015-05-13 15:49:09 -07:00
|
|
|
e.Static("/scripts/", "public/scripts")
|
2015-04-28 18:53:57 -07:00
|
|
|
```
|
|
|
|
|
|
|
|
### Serving a file
|
|
|
|
|
2015-05-04 14:00:07 -07:00
|
|
|
`echo.ServeFile(path, file string)` serves a file. For example, code below serves
|
2015-05-13 23:07:03 -07:00
|
|
|
file `welcome.html` for request path `/welcome`.
|
2015-04-28 18:53:57 -07:00
|
|
|
|
|
|
|
```go
|
|
|
|
e.ServeFile("/welcome", "welcome.html")
|
|
|
|
```
|
|
|
|
|
|
|
|
### Serving an index file
|
|
|
|
|
2015-05-13 23:07:03 -07:00
|
|
|
`echo.Index(file string)` serves root index page - `GET /`. For example, code below
|
|
|
|
serves root index page from file `public/index.html`.
|
2015-04-28 18:53:57 -07:00
|
|
|
|
|
|
|
```go
|
2015-05-13 23:07:03 -07:00
|
|
|
e.Index("public/index.html")
|
2015-04-28 18:53:57 -07:00
|
|
|
```
|
|
|
|
|
2015-05-13 15:49:09 -07:00
|
|
|
### Serving favicon
|
|
|
|
|
|
|
|
`echo.Favicon(file string)` serves default favicon - `GET /favicon.ico`. For example,
|
2015-05-13 23:07:03 -07:00
|
|
|
code below serves favicon from file `public/favicon.ico`.
|
2015-05-13 15:49:09 -07:00
|
|
|
|
|
|
|
```go
|
|
|
|
e.Index("public/favicon.ico")
|
|
|
|
```
|
|
|
|
|
2015-05-06 15:51:52 -07:00
|
|
|
## Error Handling
|
|
|
|
|
|
|
|
Echo advocates centralized HTTP error handling by returning `*echo.HTTPError` from
|
|
|
|
middleware and handlers.
|
|
|
|
|
2015-05-06 18:47:26 -07:00
|
|
|
It allows you to
|
2015-05-06 18:42:45 -07:00
|
|
|
|
|
|
|
- Debug by writing stack trace to the HTTP response.
|
|
|
|
- Customize HTTP responses.
|
2015-05-06 15:51:52 -07:00
|
|
|
- Recover from panics inside middleware or handlers.
|
|
|
|
|
|
|
|
For example, when a basic auth middleware finds invalid credentials it returns 401
|
|
|
|
"Unauthorized" error, aborting the current HTTP request.
|
|
|
|
|
|
|
|
```go
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net/http"
|
|
|
|
|
|
|
|
"github.com/labstack/echo"
|
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
e := echo.New()
|
|
|
|
e.Use(func(c *echo.Context) *echo.HTTPError {
|
|
|
|
// Extract the credentials from HTTP request header and perform a security
|
|
|
|
// check
|
|
|
|
|
|
|
|
// For invalid credentials
|
|
|
|
return &echo.HTTPError{Code: http.StatusUnauthorized}
|
|
|
|
})
|
|
|
|
e.Get("/welcome", welcome)
|
2015-05-10 08:22:49 -07:00
|
|
|
e.Run(":1323")
|
2015-05-06 15:51:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func welcome(c *echo.Context) *echo.HTTPError {
|
|
|
|
return c.String(http.StatusOK, "Welcome!")
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2015-05-06 16:11:21 -07:00
|
|
|
See how [HTTPErrorHandler](#customization) handles it.
|
2015-04-28 23:09:30 -07:00
|
|
|
|
2015-05-06 15:51:52 -07:00
|
|
|
## Deployment
|
2015-05-06 10:27:01 -07:00
|
|
|
|
2015-05-06 18:47:26 -07:00
|
|
|
*WIP*
|