diff --git a/website/config.json b/website/config.json deleted file mode 100644 index f0c95b0f..00000000 --- a/website/config.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "baseurl": "https://echo.labstack.com", - "languageCode": "en-us", - "title": "Fast and unfancy HTTP server framework for Go (Golang) - LabStack Echo", - "canonifyurls": true, - "googleAnalytics": "UA-85059636-2", - "permalinks": { - "guide": "/guide/:title", - "middleware": "/middleware/:title", - "recipes": "/recipes/:title" - }, - "menu": { - "side": [{ - "name": "Guide", - "pre": "", - "weight": 1, - "identifier": "guide", - "url": "guide" - },{ - "name": "Middleware", - "pre": "", - "weight": 1, - "identifier": "middleware", - "url": "middleware" - }, { - "name": "Recipes", - "pre": "", - "weight": 2, - "identifier": "recipes", - "url": "recipes" - }, { - "name": "Godoc", - "pre": "", - "weight": 3, - "identifier": "godoc", - "url": "godoc" - }] - }, - "params": { - "description": "Golang micro web framework, High performance, Minimalistic and Fast." - } -} diff --git a/website/content/godoc/echo.md b/website/content/godoc/echo.md deleted file mode 100644 index 628384f8..00000000 --- a/website/content/godoc/echo.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: echo -menu: - side: - parent: godoc - weight: 1 - url: https://godoc.org/github.com/labstack/echo ---- diff --git a/website/content/godoc/engine.md b/website/content/godoc/engine.md deleted file mode 100644 index bc1011b8..00000000 --- a/website/content/godoc/engine.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: engine -menu: - side: - parent: godoc - weight: 3 - url: https://godoc.org/github.com/labstack/echo/engine ---- diff --git a/website/content/godoc/fasthttp.md b/website/content/godoc/fasthttp.md deleted file mode 100644 index b641be34..00000000 --- a/website/content/godoc/fasthttp.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: fasthttp -menu: - side: - parent: godoc - weight: 5 - url: https://godoc.org/github.com/labstack/echo/engine/fasthttp ---- diff --git a/website/content/godoc/middleware.md b/website/content/godoc/middleware.md deleted file mode 100644 index 881b476c..00000000 --- a/website/content/godoc/middleware.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: middleware -menu: - side: - identifier: "godoc-middleware" - parent: godoc - weight: 1 - url: https://godoc.org/github.com/labstack/echo/middleware ---- diff --git a/website/content/godoc/standard.md b/website/content/godoc/standard.md deleted file mode 100644 index c7e7e87e..00000000 --- a/website/content/godoc/standard.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: standard -menu: - side: - parent: godoc - weight: 4 - url: https://godoc.org/github.com/labstack/echo/engine/standard ---- diff --git a/website/content/guide/context.md b/website/content/guide/context.md deleted file mode 100644 index 4414e9b6..00000000 --- a/website/content/guide/context.md +++ /dev/null @@ -1,73 +0,0 @@ -+++ -title = "Context" -[menu.side] - identifier = "context" - parent = "guide" - weight = 5 -+++ - -## Context - -`echo.Context` represents the context of the current HTTP request. It holds request and -response reference, path, path parameters, data, registered handler and APIs to read -request and write response. Context is 100% compatible with standard `context.Context`. -As Context is an interface, it is easy to extend it with custom APIs. - -#### Extending Context - -**Define a custom context** - -```go -type CustomContext struct { - echo.Context -} - -func (c *CustomContext) Foo() { - println("foo") -} - -func (c *CustomContext) Bar() { - println("bar") -} -``` - -**Create a middleware to extend default context** - -```go -e.Use(func(h echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { - cc := &CustomContext{c} - return h(cc) - } -}) -``` - -> This middleware should be registered before any other middleware. - -**Use in handler** - -```go -e.Get("/", func(c echo.Context) error { - cc := c.(*CustomContext) - cc.Foo() - cc.Bar() - return cc.String(200, "OK") -}) -``` - -### Standard Context - -`echo.Context` embeds standard `context.Context` interface, so all it's functions -are available right from `echo.Context`. - -*Example* - -```go -e.GET("/users/:name", func(c echo.Context) error) { - c.SetContext(context.WithValue(nil, "key", "val")) - // Pass it down... - // Use it... - val := c.Value("key").(string) - return c.String(http.StatusOK, name) -}) -``` diff --git a/website/content/guide/cookies.md b/website/content/guide/cookies.md deleted file mode 100644 index f90a5081..00000000 --- a/website/content/guide/cookies.md +++ /dev/null @@ -1,77 +0,0 @@ -+++ -title = "Cookies" -[menu.side] - name = "Cookies" - parent = "guide" - weight = 6 -+++ - -## Cookies - -Cookie is a small piece of data sent from a website and stored in the user's web -browser while the user is browsing. Every time the user loads the website, the browser -sends the cookie back to the server to notify the user's previous activity. -Cookies were designed to be a reliable mechanism for websites to remember stateful -information (such as items added in the shopping cart in an online store) or to -record the user's browsing activity (including clicking particular buttons, logging -in, or recording which pages were visited in the past). Cookies can also store -passwords and form content a user has previously entered, such as a credit card -number or an address. - -### Cookie Attributes - -Attribute | Optional -:--- | :--- -`Name` | No -`Value` | No -`Path` | Yes -`Domain` | Yes -`Expires` | Yes -`Secure` | Yes -`HTTPOnly` | Yes - -### Create a Cookie - -```go -func writeCookie(c echo.Context) error { - cookie := new(echo.Cookie) - cookie.SetName("username") - cookie.SetValue("jon") - cookie.SetExpires(time.Now().Add(24 * time.Hour)) - c.SetCookie(cookie) - return c.String(http.StatusOK, "write a cookie") -} -``` - -- Cookie is created using `new(echo.Cookie)`. -- Attributes for the cookie are set using `Setter` functions. -- Finally `c.SetCookie(cookies)` adds a `Set-Cookie` header in HTTP response. - -### Read a Cookie - -```go -func readCookie(c echo.Context) error { - cookie, err := c.Cookie("username") - if err != nil { - return err - } - fmt.Println(cookie.Name()) - fmt.Println(cookie.Value()) - return c.String(http.StatusOK, "read a cookie") -} -``` - -- Cookie is read by name using `c.Cookie("username")` from the HTTP request. -- Cookie attributes are accessed using `Getter` function. - -### Read all Cookies - -```go -func readAllCookies(c echo.Context) error { - for _, cookie := range c.Cookies() { - fmt.Println(cookie.Name()) - fmt.Println(cookie.Value()) - } - return c.String(http.StatusOK, "read all cookie") -} -``` diff --git a/website/content/guide/customization.md b/website/content/guide/customization.md deleted file mode 100644 index 77cb2e7d..00000000 --- a/website/content/guide/customization.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: Customization -menu: - side: - parent: guide - weight: 3 ---- - -## Customization - -### HTTP Error Handler - -`Echo#SetHTTPErrorHandler(h HTTPErrorHandler)` registers a custom `Echo#HTTPErrorHandler`. - -Default HTTP error handler rules: - -- If error is of type `Echo#HTTPError` it sends HTTP response with status code `HTTPError.Code` -and message `HTTPError.Message`. -- Else it sends `500 - Internal Server Error`. -- If debug mode is enabled, it uses `error.Error()` as status message. - -### Debug - -`Echo#SetDebug(on bool)` enable/disable debug mode. - -### Logging - -#### Custom Logger - -`Echo#SetLogger(l log.Logger)` - -SetLogger defines a custom logger. - -#### Log Output - -`Echo#SetLogOutput(w io.Writer)` sets the output destination for the logger. Default -value `os.Stdout` - -To completely disable logs use `Echo#SetLogOutput(io.Discard)` - -#### Log Level - -`Echo#SetLogLevel(l log.Level)` - -SetLogLevel sets the log level for the logger. Default value `5` (OFF). -Possible values: - -- `0` (DEBUG) -- `1` (INFO) -- `2` (WARN) -- `3` (ERROR) -- `4` (FATAL) -- `5` (OFF) - -### HTTP Engine - -Echo currently supports standard and [fasthttp](https://github.com/valyala/fasthttp) -server engines. Echo utilizes interfaces to abstract the internal implementation -of these servers so you can seamlessly switch from one engine to another based on -your preference. - -#### Running a standard HTTP server - -`e.Run(standard.New(":1323"))` - -#### Running a fasthttp server - -`e.Run(fasthttp.New(":1323"))` - -#### Running a server with TLS configuration - -`e.Run(.WithTLS(":1323", "", ""))` - -#### Running a server with engine configuration - -`e.Run(.WithConfig())` - -##### Configuration - -```go -Config struct { - Address string // TCP address to listen on. - Listener net.Listener // Custom `net.Listener`. If set, server accepts connections on it. - TLSCertFile string // TLS certificate file path. - TLSKeyFile string // TLS key file path. - ReadTimeout time.Duration // Maximum duration before timing out read of the request. - WriteTimeout time.Duration // Maximum duration before timing out write of the response. -} -``` - -#### Access internal server instance and configure its properties - -```go -s := standard.New(":1323") -s.MaxHeaderBytes = 1 << 20 -e.Run(s) -``` diff --git a/website/content/guide/error-handling.md b/website/content/guide/error-handling.md deleted file mode 100644 index 5bbeddf1..00000000 --- a/website/content/guide/error-handling.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Error Handling -menu: - side: - parent: guide - weight: 8 ---- - -## Error Handling - -Echo advocates centralized HTTP error handling by returning error from middleware -or handlers. - -- Log errors from a unified location -- Send customized HTTP responses - -For example, when 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) error { - // Extract the credentials from HTTP request header and perform a security - // check - - // For invalid credentials - return echo.NewHTTPError(http.StatusUnauthorized) - }) - e.GET("/welcome", welcome) - e.Run(":1323") -} - -func welcome(c echo.Context) error { - return c.String(http.StatusOK, "Welcome!") -} -``` - -See how [HTTPErrorHandler](/guide/customization#http-error-handler) handles it. diff --git a/website/content/guide/faq.md b/website/content/guide/faq.md deleted file mode 100644 index a49e0c50..00000000 --- a/website/content/guide/faq.md +++ /dev/null @@ -1,89 +0,0 @@ ---- -title: FAQ -menu: - side: - parent: guide - weight: 20 ---- - -## FAQ - -Q: **How to retrieve `*http.Request` and `http.ResponseWriter` from `echo.Context`?** - -- `http.Request` > `c.Request().(*standard.Request).Request` -- `http.ResponseWriter` > `c.Response()` - -> Standard engine only - -Q: **How to use standard handler `func(http.ResponseWriter, *http.Request)` with Echo?** - -```go -func handler(w http.ResponseWriter, r *http.Request) { - io.WriteString(w, "Handler!") -} - -func main() { - e := echo.New() - e.GET("/", standard.WrapHandler(http.HandlerFunc(handler))) - e.Run(standard.New(":1323")) -} -``` - -Q: **How to use fasthttp handler `func(fasthttp.RequestCtx)` with Echo?** - -```go -func handler(c *fh.RequestCtx) { - io.WriteString(c, "Handler!") -} - -func main() { - e := echo.New() - e.GET("/", fasthttp.WrapHandler(handler)) - e.Run(fasthttp.New(":1323")) -} -``` - -Q: **How to use standard middleware `func(http.Handler) http.Handler` with Echo?** - -```go -func middleware(h http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - println("Middleware!") - h.ServeHTTP(w, r) - }) -} - -func main() { - e := echo.New() - e.Use(standard.WrapMiddleware(middleware)) - e.GET("/", func(c echo.Context) error { - return c.String(http.StatusOK, "OK") - }) - e.Run(standard.New(":1323")) -} -``` - -Q: **How to use fasthttp middleware `func(http.Handler) http.Handler` with Echo?** - -```go -func middleware(h fh.RequestHandler) fh.RequestHandler { - return func(ctx *fh.RequestCtx) { - println("Middleware!") - h(ctx) - } -} - -func main() { - e := echo.New() - e.Use(fasthttp.WrapMiddleware(middleware)) - e.GET("/", func(c echo.Context) error { - return c.String(http.StatusOK, "OK") - }) - e.Run(fasthttp.New(":1323")) -} -``` - - diff --git a/website/content/guide/installation.md b/website/content/guide/installation.md deleted file mode 100644 index 20a1f83c..00000000 --- a/website/content/guide/installation.md +++ /dev/null @@ -1,21 +0,0 @@ -+++ -title = "Installation" -[menu.side] - parent = "guide" - weight = 1 -+++ - -## Installation - -Echo is developed and tested using Go `1.6.x` and `1.7.x` - -```sh -$ go get -u github.com/labstack/echo -``` - -> Ideally, you should rely on a [package manager](https://github.com/avelino/awesome-go#package-management) like glide or govendor to use a specific [version](https://github.com/labstack/echo/releases) of Echo. - -### [Migrating from v1](/guide/migrating) - -Echo follows [semantic versioning](http://semver.org) managed through GitHub releases. -Specific version of Echo can be installed using a [package manager](https://github.com/avelino/awesome-go#package-management). diff --git a/website/content/guide/migrating.md b/website/content/guide/migrating.md deleted file mode 100644 index 121f89b2..00000000 --- a/website/content/guide/migrating.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -title: Migrating -menu: - side: - parent: guide - weight: 2 ---- - -## Migrating from v1 - -### Change Log - -- Good news, 85% of the API remains the same. -- `Engine` interface to abstract `HTTP` server implementation, allowing -us to use HTTP servers beyond Go standard library. It currently supports standard and [fasthttp](https://github.com/valyala/fasthttp) server. -- Context, Request and Response are converted to interfaces. [More...](https://github.com/labstack/echo/issues/146) -- Handler signature is changed to `func (c echo.Context) error`. -- Dropped auto wrapping of handler and middleware to enforce compile time check. -- APIs to run middleware before or after the router, which doesn't require `Echo#Hook` API now. -- Ability to define middleware at route level. -- `Echo#HTTPError` exposed it's fields `Code` and `Message`. -- Option to specify log format in logger middleware and default logger. - -#### API - -v1 | v2 ---- | --- -`Context#Query()` | `Context#QueryParam()` -`Context#Form()` | `Context#FormValue()` - -### FAQ - -Q. How to access original objects from interfaces? - -A. Only if you need to... - -```go -// `*http.Request` -c.Request().(*standard.Request).Request - -// `*http.URL` -c.Request().URL().(*standard.URL).URL - -// Request `http.Header` -c.Request().Header().(*standard.Header).Header - -// `http.ResponseWriter` -c.Response().(*standard.Response).ResponseWriter - -// Response `http.Header` -c.Response().Header().(*standard.Header).Header -``` - -Q. How to use standard handler and middleware? - -A. - -```go -package main - -import ( - "net/http" - - "github.com/labstack/echo" - "github.com/labstack/echo/engine/standard" -) - -// Standard middleware -func middleware(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - println("standard middleware") - next.ServeHTTP(w, r) - }) -} - -// Standard handler -func handler(w http.ResponseWriter, r *http.Request) { - println("standard handler") -} - -func main() { - e := echo.New() - e.Use(standard.WrapMiddleware(middleware)) - e.GET("/", standard.WrapHandler(http.HandlerFunc(handler))) - e.Run(standard.New(":1323")) -} -``` - -### Next? - -- Browse through [recipes](/recipes/hello-world) freshly converted to v2. -- Read documentation and dig into test cases. diff --git a/website/content/guide/request.md b/website/content/guide/request.md deleted file mode 100644 index 27ca6ac0..00000000 --- a/website/content/guide/request.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: Request -menu: - side: - parent: guide - weight: 6 ---- - -## Request - -### Bind Request Body - -To bind request body into a provided Go type use `Context#Bind(interface{})`. -The default binder supports decoding application/json, application/xml and -application/x-www-form-urlencoded payload based on Context-Type header. - -*Example* - -TODO - -> Custom binder can be registered via `Echo#SetBinder(Binder)` - -### Query Parameter - -Query parameter can be retrieved by name using `Context#QueryParam(name string)`. - -*Example* - -```go -e.GET("/users", func(c echo.Context) error { - name := c.QueryParam("name") - return c.String(http.StatusOK, name) -}) -``` - -```sh -$ curl -G -d "name=joe" http://localhost:1323/users -``` - -### Form Parameter - -Form parameter can be retrieved by name using `Context#FormValue(name string)`. - -*Example* - -```go -e.POST("/users", func(c echo.Context) error { - name := c.FormValue("name") - return c.String(http.StatusOK, name) -}) -``` - -```sh -$ curl -d "name=joe" http://localhost:1323/users -``` - -### Path Parameter - -Registered path parameter can be retrieved either by name `Context#Param(name string) string` -or by index `Context#P(i int) string`. Getting parameter by index gives a slightly -better performance. - -*Example* - -```go -e.GET("/users/:name", func(c echo.Context) error { - // By name - name := c.Param("name") - - // By index - name := c.P(0) - - return c.String(http.StatusOK, name) -}) -``` - -```sh -$ curl http://localhost:1323/users/joe -``` - - -### Handler Path - -`Context#Path()` returns the registered path for the handler, it can be used in the -middleware for logging purpose. - -*Example* - -```go -e.Use(func(c echo.Context) error { - println(c.Path()) // Prints `/users/:name` - return nil -}) -e.GET("/users/:name", func(c echo.Context) error) { - return c.String(http.StatusOK, name) -}) -``` diff --git a/website/content/guide/routing.md b/website/content/guide/routing.md deleted file mode 100644 index 793b4f43..00000000 --- a/website/content/guide/routing.md +++ /dev/null @@ -1,114 +0,0 @@ ---- -title: Routing -menu: - side: - parent: guide - weight: 4 ---- - -## Routing - -Echo's router is [fast, optimized]({{< ref "index.md#performance">}}) and -flexible. It's based on [radix tree](http://en.wikipedia.org/wiki/Radix_tree) data -structure which makes route lookup really fast. Router leverages [sync pool](https://golang.org/pkg/sync/#Pool) -to reuse memory and achieve zero dynamic memory allocation with no GC overhead. - -Routes can be registered by specifying HTTP method, path and a matching handler. -For example, code below registers a route for method `GET`, path `/hello` and a -handler which sends `Hello, World!` HTTP response. - -```go -// Handler -func hello(c echo.Context) error { - return c.String(http.StatusOK, "Hello, World!") -} - -// Route -e.GET("/hello", hello) -``` - -You can use `Echo.Any(path string, h Handler)` to register a handler for all HTTP methods. -If you want to register it for some methods use `Echo.Match(methods []string, path string, h Handler)`. - -Echo defines handler function as `func(echo.Context) error` where `echo.Context` primarily -holds HTTP request and response interfaces. - -### Match-any - -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 - -- Static -- Param -- Match any - -#### Example - -```go -e.GET("/users/:id", func(c echo.Context) error { - return c.String(http.StatusOK, "/users/:id") -}) - -e.GET("/users/new", func(c echo.Context) error { - return c.String(http.StatusOK, "/users/new") -}) - -e.GET("/users/1/files/*", func(c echo.Context) error { - return c.String(http.StatusOK, "/users/1/files/*") -}) -``` - -Above routes would resolve in the following order: - -- `/users/new` -- `/users/:id` -- `/users/1/files/*` - -> Routes can be written in any order. - -### Group - -`Echo#Group(prefix string, m ...Middleware) *Group` - -Routes with common prefix can be grouped to define a new sub-router with optional -middleware. In addition to specified middleware group also inherits parent middleware. -To add middleware later in the group you can use `Group.Use(m ...Middleware)`. -Groups can also be nested. - -In the code below, we create an admin group which requires basic HTTP authentication -for routes `/admin/*`. - -```go -g := e.Group("/admin") -g.Use(middleware.BasicAuth(func(username, password string) bool { - if username == "joe" && password == "secret" { - return true - } - return false -})) -``` - -### URI building - -`Echo.URI` can be used to generate URI for any handler with specified path parameters. -It's helpful to centralize all your URI patterns which ease in refactoring your -application. - -`e.URI(h, 1)` will generate `/users/1` for the route registered below - -```go -// Handler -h := func(c echo.Context) error { - return c.String(http.StatusOK, "OK") -} - -// Route -e.GET("/users/:id", h) -``` diff --git a/website/content/guide/static-files.md b/website/content/guide/static-files.md deleted file mode 100644 index bb43f063..00000000 --- a/website/content/guide/static-files.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: Static Files -menu: - side: - parent: guide - weight: 3 ---- - -Images, JavaScript, CSS, PDF, Fonts and so on... - -## Static Files - -### [Using Static Middleware]({{< ref "middleware/static.md">}}) - -### Using `Echo#Static()` - -`Echo#Static(prefix, root string)` registers a new route with path prefix to serve -static files from the provided root directory. - -*Usage 1* - -```go -e := echo.New() -e.Static("/static", "assets") -``` - -Example above will serve any file from the assets directory for path `/static/*`. For example, -a request to `/static/js/main.js` will fetch and serve `assets/js/main.js` file. - -*Usage 2* - -```go -e := echo.New() -e.Static("/", "assets") -``` - -Example above will serve any file from the assets directory for path `/*`. For example, -a request to `/js/main.js` will fetch and serve `assets/js/main.js` file. - -### Using `Echo#File()` - -`Echo#File(path, file string)` registers a new route with path to serve a static -file. - -*Usage 1* - -Serving an index page from `public/index.html` - -```go -e.File("/", "public/index.html") -``` - -*Usage 2* - -Serving a favicon from `images/favicon.ico` - -```go -e.File("/favicon.ico", "images/favicon.ico") -``` diff --git a/website/content/guide/templates.md b/website/content/guide/templates.md deleted file mode 100644 index 97e665f1..00000000 --- a/website/content/guide/templates.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: Templates -menu: - side: - parent: guide - weight: 3 ---- - -## Templates - -### Template Rendering - -`Context#Render(code int, name string, data interface{}) error` renders a template -with data and sends a text/html response with status code. Templates can be registered -using `Echo.SetRenderer()`, allowing us to use any template engine. - -Example below shows how to use Go `html/template`: - -1. Implement `echo.Renderer` interface - - ```go - type Template struct { - templates *template.Template - } - - func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error { - return t.templates.ExecuteTemplate(w, name, data) - } - ``` - -2. Pre-compile templates - - `public/views/hello.html` - - ```html - {{define "hello"}}Hello, {{.}}!{{end}} - ``` - - ```go - t := &Template{ - templates: template.Must(template.ParseGlob("public/views/*.html")), - } - ``` - -3. Register templates - - ```go - e := echo.New() - e.SetRenderer(t) - e.GET("/hello", Hello) - ``` - -4. Render a template inside your handler - - ```go - func Hello(c echo.Context) error { - return c.Render(http.StatusOK, "hello", "World") - } - ``` diff --git a/website/content/guide/testing.md b/website/content/guide/testing.md deleted file mode 100644 index b42b9aa6..00000000 --- a/website/content/guide/testing.md +++ /dev/null @@ -1,160 +0,0 @@ ---- -title: Testing -menu: - side: - parent: guide - weight: 9 ---- - -## Testing - -### Testing Handler - -`GET` `/users/:id` - -Handler below retrieves user by id from the database. If user is not found it returns -`404` error with a message. - -#### CreateUser - -`POST` `/users` - -- Accepts JSON payload -- On success `201 - Created` -- On error `500 - Internal Server Error` - -#### GetUser - -`GET` `/users/:email` - -- On success `200 - OK` -- On error `404 - Not Found` if user is not found otherwise `500 - Internal Server Error` - -`handler.go` - -```go -package handler - -import ( - "net/http" - - "github.com/labstack/echo" -) - -type ( - User struct { - Name string `json:"name" form:"name"` - Email string `json:"email" form:"email"` - } - handler struct { - db map[string]*User - } -) - -func (h *handler) createUser(c echo.Context) error { - u := new(User) - if err := c.Bind(u); err != nil { - return err - } - return c.JSON(http.StatusCreated, u) -} - -func (h *handler) getUser(c echo.Context) error { - email := c.Param("email") - user := h.db[email] - if user == nil { - return echo.NewHTTPError(http.StatusNotFound, "user not found") - } - return c.JSON(http.StatusOK, user) -} -``` - -`handler_test.go` - -```go -package handler - -import ( - "net/http" - "net/http/httptest" - "strings" - "testing" - - "github.com/labstack/echo" - "github.com/labstack/echo/engine/standard" - "github.com/stretchr/testify/assert" -) - -var ( - mockDB = map[string]*User{ - "jon@labstack.com": &User{"Jon Snow", "jon@labstack.com"}, - } - userJSON = `{"name":"Jon Snow","email":"jon@labstack.com"}` -) - -func TestCreateUser(t *testing.T) { - // Setup - e := echo.New() - req, err := http.NewRequest(echo.POST, "/users", strings.NewReader(userJSON)) - if assert.NoError(t, err) { - req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) - rec := httptest.NewRecorder() - c := e.NewContext(standard.NewRequest(req, e.Logger()), standard.NewResponse(rec, e.Logger())) - h := &handler{mockDB} - - // Assertions - if assert.NoError(t, h.createUser(c)) { - assert.Equal(t, http.StatusCreated, rec.Code) - assert.Equal(t, userJSON, rec.Body.String()) - } - } -} - -func TestGetUser(t *testing.T) { - // Setup - e := echo.New() - req := new(http.Request) - rec := httptest.NewRecorder() - c := e.NewContext(standard.NewRequest(req, e.Logger()), standard.NewResponse(rec, e.Logger())) - c.SetPath("/users/:email") - c.SetParamNames("email") - c.SetParamValues("jon@labstack.com") - h := &handler{mockDB} - - // Assertions - if assert.NoError(t, h.getUser(c)) { - assert.Equal(t, http.StatusOK, rec.Code) - assert.Equal(t, userJSON, rec.Body.String()) - } -} -``` - -#### Using Form Payload - -```go -f := make(url.Values) -f.Set("name", "Jon Snow") -f.Set("email", "jon@labstack.com") -req, err := http.NewRequest(echo.POST, "/", strings.NewReader(f.Encode())) -``` - -#### Setting Path Params - -```go -c.SetParamNames("id", "email") -c.SetParamValues("1", "jon@labstack.com") -``` - -#### Setting Query Params - -```go -q := make(url.Values) -q.Set("email", "jon@labstack.com") -req, err := http.NewRequest(echo.POST, "/?"+q.Encode(), nil) -``` - -### Testing Middleware - -*TBD* - -You can looking to built-in middleware [test cases](https://github.com/labstack/echo/tree/master/middleware). diff --git a/website/content/index.md b/website/content/index.md deleted file mode 100644 index acc25581..00000000 --- a/website/content/index.md +++ /dev/null @@ -1,291 +0,0 @@ ---- -title: Index ---- - -# Fast and unfancy HTTP server framework for Go (Golang). - -## Feature Overview - -- Optimized HTTP router which smartly prioritize routes -- Build robust and scalable RESTful APIs -- Run with standard HTTP server or FastHTTP server -- Group APIs -- Extensible middleware framework -- Define middleware at root, group or route level -- Data binding for JSON, XML and form payload -- Handy functions to send variety of HTTP responses -- Centralized HTTP error handling -- Template rendering with any template engine -- Define your format for the logger -- Highly customizable - - -## Performance - -- Environment: - - Go 1.6 - - wrk 4.0.0 - - 2 GB, 2 Core (DigitalOcean) -- Test Suite: https://github.com/vishr/web-framework-benchmark -- Date: 4/4/2016 - - - -## Quick Start - -### Installation - -```sh -$ go get -u github.com/labstack/echo -``` - -### Hello, World! - -Create `server.go` - -```go -package main - -import ( - "net/http" - "github.com/labstack/echo" - "github.com/labstack/echo/engine/standard" -) - -func main() { - e := echo.New() - e.GET("/", func(c echo.Context) error { - return c.String(http.StatusOK, "Hello, World!") - }) - e.Run(standard.New(":1323")) -} -``` - -Start server - -```sh -$ go run server.go -``` - -Browse to [http://localhost:1323](http://localhost:1323) and you should see -Hello, World! on the page. - -### Routing - -```go -e.POST("/users", saveUser) -e.GET("/users/:id", getUser) -e.PUT("/users/:id", updateUser) -e.DELETE("/users/:id", deleteUser) -``` - -### Path Parameters - -```go -func getUser(c echo.Context) error { - // User ID from path `users/:id` - id := c.Param("id") -} -``` - -### Query Parameters - -`/show?team=x-men&member=wolverine` - -```go -func show(c echo.Context) error { - // Get team and member from the query string - team := c.QueryParam("team") - member := c.QueryParam("member") -} -``` - -### Form `application/x-www-form-urlencoded` - -`POST` `/save` - -name | value -:--- | :--- -name | Joe Smith -email | joe@labstack.com - -```go -func save(c echo.Context) error { - // Get name and email - name := c.FormValue("name") - email := c.FormValue("email") -} -``` - -### Form `multipart/form-data` - -`POST` `/save` - -name | value -:--- | :--- -name | Joe Smith -email | joe@labstack.com -avatar | avatar - -```go -func save(c echo.Context) error { - // Get name and email - name := c.FormValue("name") - email := c.FormValue("email") - // 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, "Thank you!") -} -``` - -### Handling Request - -- Bind `JSON` or `XML` or `form` payload into Go struct based on `Content-Type` request header. -- Render response as `JSON` or `XML` with status code. - -```go -type User struct { - Name string `json:"name" xml:"name" form:"name"` - Email string `json:"email" xml:"email" form:"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) -}) -``` - -### Static Content - -Server any file from static directory for path `/static/*`. - -```go -e.Static("/static", "static") -``` - -##### [Learn More](https://echo.labstack.com/guide/static-files) - -### [Template Rendering](https://echo.labstack.com/guide/templates) - -### Middleware - -```go -// Root level middleware -e.Use(middleware.Logger()) -e.Use(middleware.Recover()) - -// Group level middleware -g := e.Group("/admin") -g.Use(middleware.BasicAuth(func(username, password string) bool { - if username == "joe" && password == "secret" { - return true - } - return false -})) - -// Route level middleware -track := func(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { - println("request to /users") - return next(c) - } -} -e.GET("/users", func(c echo.Context) error { - return c.String(http.StatusOK, "/users") -}, track) -``` - -#### Built-in Middleware - -Middleware | Description -:--- | :--- -[BodyLimit]({{< ref "middleware/body-limit.md">}}) | Limit request body -[Logger]({{< ref "middleware/logger.md">}}) | Log HTTP requests -[Recover]({{< ref "middleware/recover.md">}}) | Recover from panics -[Gzip]({{< ref "middleware/gzip.md">}}) | Send gzip HTTP response -[BasicAuth]({{< ref "middleware/basic-auth.md">}}) | HTTP basic authentication -[JWTAuth]({{< ref "middleware/jwt.md">}}) | JWT authentication -[Secure]({{< ref "middleware/secure.md">}}) | Protection against attacks -[CORS]({{< ref "middleware/cors.md">}}) | Cross-Origin Resource Sharing -[CSRF]({{< ref "middleware/csrf.md">}}) | Cross-Site Request Forgery -[Static]({{< ref "middleware/static.md">}}) | Serve static files -[HTTPSRedirect]({{< ref "middleware/redirect.md#httpsredirect-middleware">}}) | Redirect HTTP requests to HTTPS -[HTTPSWWWRedirect]({{< ref "middleware/redirect.md#httpswwwredirect-middleware">}}) | Redirect HTTP requests to WWW HTTPS -[WWWRedirect]({{< ref "middleware/redirect.md#wwwredirect-middleware">}}) | Redirect non WWW requests to WWW -[NonWWWRedirect]({{< ref "middleware/redirect.md#nonwwwredirect-middleware">}}) | Redirect WWW requests to non WWW -[AddTrailingSlash]({{< ref "middleware/trailing-slash.md#addtrailingslash-middleware">}}) | Add trailing slash to the request URI -[RemoveTrailingSlash]({{< ref "middleware/trailing-slash.md#removetrailingslash-middleware">}}) | Remove trailing slash from the request URI -[MethodOverride]({{< ref "middleware/method-override.md">}}) | Override request method - -#### Third-party Middleware - -Middleware | Description -:--- | :--- -[echoperm](https://github.com/xyproto/echoperm) | Keeping track of users, login states and permissions. -[echopprof](https://github.com/mtojek/echopprof) | Adapt net/http/pprof to labstack/echo. - -##### [Learn More](https://echo.labstack.com/middleware/overview) - -### Next - -- Head over to [guide](https://echo.labstack.com/guide/installation) -- Browse [recipes](https://echo.labstack.com/recipes/hello-world) - -### Need help? - -- [Hop on to chat](https://gitter.im/labstack/echo) -- [Open an issue](https://github.com/labstack/echo/issues/new) - -## Support Echo - -- ☆ the project -- [Donate](https://echo.labstack.com/support-echo) -- 🌐 spread the word -- [Contribute](#contribute:d680e8a854a7cbad6d490c445cba2eba) to the project - -## Contribute - -**Use issues for everything** - -- Report issues -- Discuss on chat before sending a pull request -- Suggest new features or enhancements -- Improve/fix documentation - -## Credits - -- [Vishal Rana](https://github.com/vishr) - Author -- [Nitin Rana](https://github.com/nr17) - Consultant -- [Contributors](https://github.com/labstack/echo/graphs/contributors) - -## License - -[MIT](https://github.com/labstack/echo/blob/master/LICENSE) diff --git a/website/content/middleware/basic-auth.md b/website/content/middleware/basic-auth.md deleted file mode 100644 index fb93a100..00000000 --- a/website/content/middleware/basic-auth.md +++ /dev/null @@ -1,58 +0,0 @@ -+++ -title = "Basic Auth" -[menu.side] - name = "BasicAuth" - parent = "middleware" - weight = 5 -+++ - -## BasicAuth Middleware - -BasicAuth middleware provides an HTTP basic authentication. - -- For valid credentials it calls the next handler. -- For invalid credentials, it sends "401 - Unauthorized" response. -- For empty or invalid `Authorization` header, it sends "400 - Bad Request" response. - -*Usage* - -```go -e := echo.New() -e.Use(middleware.BasicAuth(func(username, password string) bool { - if username == "joe" && password == "secret" { - return true - } - return false -})) -``` - -### Custom Configuration - -*Usage* - -```go -e := echo.New() -e.Use(middleware.BasicAuthWithConfig(middleware.BasicAuthConfig{}, -})) -``` - -### Configuration - -```go -BasicAuthConfig struct { - // Skipper defines a function to skip middleware. - Skipper Skipper - - // Validator is a function to validate BasicAuth credentials. - // Required. - Validator BasicAuthValidator -} -``` - -*Default Configuration* - -```go -DefaultBasicAuthConfig = BasicAuthConfig{ - Skipper: defaultSkipper, -} -``` diff --git a/website/content/middleware/body-limit.md b/website/content/middleware/body-limit.md deleted file mode 100644 index fb3d46cb..00000000 --- a/website/content/middleware/body-limit.md +++ /dev/null @@ -1,54 +0,0 @@ -+++ -title = "Body Limit" -[menu.side] - name = "BodyLimit" - parent = "middleware" - weight = 5 -+++ - -## BodyLimit Middleware - -BodyLimit middleware sets the maximum allowed size for a request body, if the -size exceeds the configured limit, it sends "413 - Request Entity Too Large" -response. The body limit is determined based on both `Content-Length` request -header and actual content read, which makes it super secure. - -Limit can be specified as `4x` or `4xB`, where x is one of the multiple from K, M, -G, T or P. - -*Usage* - -```go -e := echo.New() -e.Use(middleware.BodyLimit("2M")) -``` -### Custom Configuration - -*Usage* - -```go -e := echo.New() -e.Use(middleware.BodyLimitWithConfig(middleware.BodyLimitConfig{}, -})) -``` - -### Configuration - -```go -BodyLimitConfig struct { - // Skipper defines a function to skip middleware. - Skipper Skipper - - // Maximum allowed size for a request body, it can be specified - // as `4x` or `4xB`, where x is one of the multiple from K, M, G, T or P. - Limit string `json:"limit"` -} -``` - -*Default Configuration* - -```go -DefaultBodyLimitConfig = BodyLimitConfig{ - Skipper: defaultSkipper, -} -``` diff --git a/website/content/middleware/cors.md b/website/content/middleware/cors.md deleted file mode 100644 index 782d6631..00000000 --- a/website/content/middleware/cors.md +++ /dev/null @@ -1,79 +0,0 @@ -+++ -title = "CORS" -[menu.side] - name = "CORS" - parent = "middleware" - weight = 5 -+++ - -## CORS Middleware - -CORS middleware implements [CORS](http://www.w3.org/TR/cors) specification. -CORS gives web servers cross-domain access controls, which enable secure cross-domain -data transfers. - -*Usage* - -`e.Use(middleware.CORS())` - -### Custom Configuration - -*Usage* - -```go -e := echo.New() -e.Use(middleware.CORSWithConfig(middleware.CORSConfig{ - AllowOrigins: []string{"https://labstack.com", "https://labstack.net"}, - AllowHeaders: []string{echo.HeaderOrigin, echo.HeaderContentType, echo.HeaderAccept}, -})) -``` - -### Configuration - -```go -CORSConfig struct { - // Skipper defines a function to skip middleware. - Skipper Skipper - - // AllowOrigin defines a list of origins that may access the resource. - // Optional. Default value []string{"*"}. - AllowOrigins []string `json:"allow_origins"` - - // AllowMethods defines a list methods allowed when accessing the resource. - // This is used in response to a preflight request. - // Optional. Default value DefaultCORSConfig.AllowMethods. - AllowMethods []string `json:"allow_methods"` - - // AllowHeaders defines a list of request headers that can be used when - // making the actual request. This in response to a preflight request. - // Optional. Default value []string{}. - AllowHeaders []string `json:"allow_headers"` - - // AllowCredentials indicates whether or not the response to the request - // can be exposed when the credentials flag is true. When used as part of - // a response to a preflight request, this indicates whether or not the - // actual request can be made using credentials. - // Optional. Default value false. - AllowCredentials bool `json:"allow_credentials"` - - // ExposeHeaders defines a whitelist headers that clients are allowed to - // access. - // Optional. Default value []string{}. - ExposeHeaders []string `json:"expose_headers"` - - // MaxAge indicates how long (in seconds) the results of a preflight request - // can be cached. - // Optional. Default value 0. - MaxAge int `json:"max_age"` -} -``` - -*Default Configuration* - -```go -DefaultCORSConfig = CORSConfig{ - Skipper: defaultSkipper, - AllowOrigins: []string{"*"}, - AllowMethods: []string{echo.GET, echo.HEAD, echo.PUT, echo.PATCH, echo.POST, echo.DELETE}, -} -``` diff --git a/website/content/middleware/csrf.md b/website/content/middleware/csrf.md deleted file mode 100644 index 2c7e3c39..00000000 --- a/website/content/middleware/csrf.md +++ /dev/null @@ -1,106 +0,0 @@ -+++ -title = "CSRF" -[menu.side] - name = "CSRF" - parent = "middleware" - weight = 5 -+++ - -## CSRF Middleware - -Cross-site request forgery, also known as one-click attack or session riding and -abbreviated as CSRF (sometimes pronounced sea-surf) or XSRF, is a type of malicious -exploit of a website where unauthorized commands are transmitted from a user that -the website trusts. - -*Usage* - -`e.Use(middleware.CSRF())` - -### Custom Configuration - -*Usage* - -```go -e := echo.New() -e.Use(middleware.CSRFWithConfig(middleware.CSRFConfig{ - TokenLookup: "header:X-XSRF-TOKEN", -})) -``` - -Example above uses `X-XSRF-TOKEN` request header to extract CSRF token. - -### Accessing CSRF Token - -#### Server-side - -CSRF token can be accessed from `Echo#Context` using `ContextKey` and passed to -the client via template. - -#### Client-side - -CSRF token can be accessed from CSRF cookie. - -### Configuration - -```go -// CSRFConfig defines the config for CSRF middleware. -CSRFConfig struct { - // Skipper defines a function to skip middleware. - Skipper Skipper - - // TokenLength is the length of the generated token. - TokenLength uint8 `json:"token_length"` - // Optional. Default value 32. - - // TokenLookup is a string in the form of ":" that is used - // to extract token from the request. - // Optional. Default value "header:X-CSRF-Token". - // Possible values: - // - "header:" - // - "form:" - // - "query:" - TokenLookup string `json:"token_lookup"` - - // Context key to store generated CSRF token into context. - // Optional. Default value "csrf". - ContextKey string `json:"context_key"` - - // Name of the CSRF cookie. This cookie will store CSRF token. - // Optional. Default value "csrf". - CookieName string `json:"cookie_name"` - - // Domain of the CSRF cookie. - // Optional. Default value none. - CookieDomain string `json:"cookie_domain"` - - // Path of the CSRF cookie. - // Optional. Default value none. - CookiePath string `json:"cookie_path"` - - // Max age (in seconds) of the CSRF cookie. - // Optional. Default value 86400 (24hr). - CookieMaxAge int `json:"cookie_max_age"` - - // Indicates if CSRF cookie is secure. - // Optional. Default value false. - CookieSecure bool `json:"cookie_secure"` - - // Indicates if CSRF cookie is HTTP only. - // Optional. Default value false. - CookieHTTPOnly bool `json:"cookie_http_only"` -} -``` - -*Default Configuration* - -```go -DefaultCSRFConfig = CSRFConfig{ - Skipper: defaultSkipper, - TokenLength: 32, - TokenLookup: "header:" + echo.HeaderXCSRFToken, - ContextKey: "csrf", - CookieName: "_csrf", - CookieMaxAge: 86400, -} -``` diff --git a/website/content/middleware/gzip.md b/website/content/middleware/gzip.md deleted file mode 100644 index 260bcfbd..00000000 --- a/website/content/middleware/gzip.md +++ /dev/null @@ -1,48 +0,0 @@ -+++ -title = "Gzip" -[menu.side] - name = "Gzip" - parent = "middleware" - weight = 5 -+++ - -## Gzip Middleware - -Gzip middleware compresses HTTP response using gzip compression scheme. - -*Usage* - -`e.Use(middleware.Gzip())` - -### Custom Configuration - -*Usage* - -```go -e := echo.New() -e.Use(middleware.GzipWithConfig(middleware.GzipConfig{ - Level: 5, -})) -``` - -### Configuration - -```go -GzipConfig struct { - // Skipper defines a function to skip middleware. - Skipper Skipper - - // Gzip compression level. - // Optional. Default value -1. - Level int `json:"level"` -} -``` - -*Default Configuration* - -```go -DefaultGzipConfig = GzipConfig{ - Skipper: defaultSkipper, - Level: -1, -} -``` diff --git a/website/content/middleware/jwt.md b/website/content/middleware/jwt.md deleted file mode 100644 index 8b3ea5d1..00000000 --- a/website/content/middleware/jwt.md +++ /dev/null @@ -1,80 +0,0 @@ -+++ -title = "JWT" -[menu.side] - name = "JWT" - parent = "middleware" - weight = 5 -+++ - -## JWT Middleware - -JWT provides a JSON Web Token (JWT) authentication middleware. - -- For valid token, it sets the user in context and calls next handler. -- For invalid token, it sends "401 - Unauthorized" response. -- For empty or invalid `Authorization` header, it sends "400 - Bad Request". - -*Usage* - -`e.Use(middleware.JWT([]byte("secret"))` - -### Custom Configuration - -*Usage* - -```go -e := echo.New() -e.Use(middleware.JWTWithConfig(middleware.JWTConfig{ - SigningKey: []byte("secret"), - TokenLookup: "query:token", -})) -``` - -### Configuration - -```go -// JWTConfig defines the config for JWT middleware. -JWTConfig struct { - // Skipper defines a function to skip middleware. - Skipper Skipper - - // Signing key to validate token. - // Required. - SigningKey interface{} `json:"signing_key"` - - // Signing method, used to check token signing method. - // Optional. Default value HS256. - SigningMethod string `json:"signing_method"` - - // Context key to store user information from the token into context. - // Optional. Default value "user". - ContextKey string `json:"context_key"` - - // Claims are extendable claims data defining token content. - // Optional. Default value jwt.MapClaims - Claims jwt.Claims - - // TokenLookup is a string in the form of ":" that is used - // to extract token from the request. - // Optional. Default value "header:Authorization". - // Possible values: - // - "header:" - // - "query:" - // - "cookie:" - TokenLookup string `json:"token_lookup"` -} -``` - -*Default Configuration* - -```go -DefaultJWTConfig = JWTConfig{ - Skipper: defaultSkipper, - SigningMethod: AlgorithmHS256, - ContextKey: "user", - TokenLookup: "header:" + echo.HeaderAuthorization, - Claims: jwt.MapClaims{}, -} -``` - -### [Recipe]({{< ref "recipes/jwt.md">}}) diff --git a/website/content/middleware/logger.md b/website/content/middleware/logger.md deleted file mode 100644 index 8a124851..00000000 --- a/website/content/middleware/logger.md +++ /dev/null @@ -1,88 +0,0 @@ -+++ -title = "Logger" -[menu.side] - name = "Logger" - parent = "middleware" - weight = 5 -+++ - -## Logger Middleware - -Logger middleware logs the information about each HTTP request. - -*Usage* - -`e.Use(middleware.Logger())` - -*Sample Output* - -```js -{"time":"2016-05-10T07:02:25-07:00","remote_ip":"::1","method":"GET","uri":"/","status":200, "latency":55653,"latency_human":"55.653µs","rx_bytes":0,"tx_bytes":13} -``` - -### Custom Configuration - -*Usage* - -```go -e := echo.New() -e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{ - Format: "method=${method}, uri=${uri}, status=${status}\n", -})) -``` - -Example above uses a `Format` which logs request method and request URI. - -*Sample Output* - -```sh -method=GET, uri=/hello, status=200 -``` - -### Configuration - -```go -LoggerConfig struct { - // Skipper defines a function to skip middleware. - Skipper Skipper - - // Log format which can be constructed using the following tags: - // - // - time_rfc3339 - // - id (Request ID - Not implemented) - // - remote_ip - // - uri - // - host - // - method - // - path - // - referer - // - user_agent - // - status - // - latency (In microseconds) - // - latency_human (Human readable) - // - bytes_in (Bytes received) - // - bytes_out (Bytes sent) - // - // Example "${remote_ip} ${status}" - // - // Optional. Default value DefaultLoggerConfig.Format. - Format string `json:"format"` - - // Output is a writer where logs are written. - // Optional. Default value os.Stdout. - Output io.Writer -} -``` - -*Default Configuration* - -```go -DefaultLoggerConfig = LoggerConfig{ - Skipper: defaultSkipper, - Format: `{"time":"${time_rfc3339}","remote_ip":"${remote_ip}",` + - `"method":"${method}","uri":"${uri}","status":${status}, "latency":${latency},` + - `"latency_human":"${latency_human}","bytes_in":${bytes_in},` + - `"bytes_out":${bytes_out}}` + "\n", - Output: os.Stdout, -} -``` diff --git a/website/content/middleware/method-override.md b/website/content/middleware/method-override.md deleted file mode 100644 index bf6a6d71..00000000 --- a/website/content/middleware/method-override.md +++ /dev/null @@ -1,51 +0,0 @@ -+++ -title = "Method Override" -[menu.side] - name = "MethodOverride" - parent = "middleware" - weight = 5 -+++ - -## MethodOverride Middleware - -MethodOverride middleware checks for the overridden method from the request and -uses it instead of the original method. - -For security reasons, only `POST` method can be overridden. - -*Usage* - -`e.Pre(middleware.MethodOverride())` - -### Custom Configuration - -*Usage* - -```go -e := echo.New() -e.Pre(middleware.MethodOverrideWithConfig(middleware.MethodOverrideConfig{ - Getter: middleware.MethodFromForm("_method"), -})) -``` - -### Configuration - -```go -MethodOverrideConfig struct { - // Skipper defines a function to skip middleware. - Skipper Skipper - - // Getter is a function that gets overridden method from the request. - // Optional. Default values MethodFromHeader(echo.HeaderXHTTPMethodOverride). - Getter MethodOverrideGetter -} -``` - -*Default Configuration* - -```go -DefaultMethodOverrideConfig = MethodOverrideConfig{ - Skipper: defaultSkipper, - Getter: MethodFromHeader(echo.HeaderXHTTPMethodOverride), -} -``` diff --git a/website/content/middleware/overview.md b/website/content/middleware/overview.md deleted file mode 100644 index fb6a5cea..00000000 --- a/website/content/middleware/overview.md +++ /dev/null @@ -1,104 +0,0 @@ -+++ -title = "Overview" -[menu.side] - name = "Overview" - parent = "middleware" - weight = 1 -+++ - -## Middleware Overview - -Middleware is a function chained in the HTTP request-response cycle with access -to `Echo#Context` which it uses to perform a specific action, for example, logging -every request or limiting the number of requests. - -Handler is processed in the end after all middleware are finished executing. - -### Middleware Levels - -#### Root Level (Before router) - -`Echo#Pre()` can be used to register a middleware which is executed before router -processes the request. It is helpful to make any changes to the request properties, -for example, adding or removing a trailing slash from the path so it matches the -route. - -The following built-in middleware should be registered at this level: - -- HTTPSRedirect -- HTTPSWWWRedirect -- WWWRedirect -- NonWWWRedirect -- AddTrailingSlash -- RemoveTrailingSlash -- MethodOverride - -> As router has not processed the request, middleware at this level won't -have access to any path related API from `echo.Context`. - -#### Root Level (After router) - -Most of the time you will register a middleware at this level using `Echo#Use()`. -This middleware is executed after router processes the request and has full access -to `echo.Context` API. - -The following built-in middleware should be registered at this level: - -- BodyLimit -- Logger -- Gzip -- Recover -- BasicAuth -- JWTAuth -- Secure -- CORS -- Static - -#### Group Level - -When creating a new group, you can register middleware just for that group. For -example, you can have an admin group which is secured by registering a BasicAuth -middleware for it. - -*Usage* - -```go -e := echo.New() -admin := e.Group("/admin", middleware.BasicAuth()) -``` - -You can also add a middleware after creating a group via `admin.Use()`. - -#### Route Level - -When defining a new route, you can optionally register middleware just for it. - -*Usage* - -```go -e := echo.New() -e.GET("/", , ) -``` - -### Skipping Middleware - -There are cases when you would like to skip a middleware based on some condition, -for that each middleware has an option to define a function `Skipper func(c echo.Context) bool`. - -*Usage* - -```go -e := echo.New() -e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{ - Skipper: func(c echo.Context) bool { - if strings.HasPrefix(c.Request().Host(), "localhost") { - return true - } - return false - }, -})) -``` - -Example above skips Logger middleware when request host starts with localhost. - -### [Writing Custom Middleware]({{< ref "recipes/middleware.md">}}) diff --git a/website/content/middleware/recover.md b/website/content/middleware/recover.md deleted file mode 100644 index fef121ab..00000000 --- a/website/content/middleware/recover.md +++ /dev/null @@ -1,64 +0,0 @@ -+++ -title = "Recover" -[menu.side] - name = "Recover" - parent = "middleware" - weight = 5 -+++ - -## Recover Middleware - -Recover middleware recovers from panics anywhere in the chain, prints stack trace -and handles the control to the centralized -[HTTPErrorHandler]({{< ref "guide/customization.md#http-error-handler">}}). - -*Usage* - -`e.Use(middleware.Recover())` - -### Custom Configuration - -*Usage* - -```go -e := echo.New() -e.Use(middleware.RecoverWithConfig(middleware.RecoverConfig{ - StackSize: 1 << 10, // 1 KB -})) -``` - -Example above uses a `StackSize` of 1 KB and default values for `DisableStackAll` -and `DisablePrintStack`. - -### Configuration - -```go -RecoverConfig struct { - // Skipper defines a function to skip middleware. - Skipper Skipper - - // Size of the stack to be printed. - // Optional. Default value 4KB. - StackSize int `json:"stack_size"` - - // DisableStackAll disables formatting stack traces of all other goroutines - // into buffer after the trace for the current goroutine. - // Optional. Default value false. - DisableStackAll bool `json:"disable_stack_all"` - - // DisablePrintStack disables printing stack trace. - // Optional. Default value as false. - DisablePrintStack bool `json:"disable_print_stack"` -} -``` - -*Default Configuration* - -```go -DefaultRecoverConfig = RecoverConfig{ - Skipper: defaultSkipper, - StackSize: 4 << 10, // 4 KB - DisableStackAll: false, - DisablePrintStack: false, -} -``` diff --git a/website/content/middleware/redirect.md b/website/content/middleware/redirect.md deleted file mode 100644 index e500177d..00000000 --- a/website/content/middleware/redirect.md +++ /dev/null @@ -1,103 +0,0 @@ -+++ -title = "Redirect" -[menu.side] - name = "Redirect" - parent = "middleware" - weight = 5 -+++ - -## HTTPSRedirect Middleware - -HTTPSRedirect middleware redirects http requests to https. -For example, http://labstack.com will be redirected to https://labstack.com. - -*Usage* - -```go -e := echo.New() -e.Pre(middleware.HTTPSRedirect()) -``` - -## HTTPSWWWRedirect Middleware - -HTTPSWWWRedirect redirects http requests to www https. -For example, http://labstack.com will be redirected to https://www.labstack.com. - -*Usage* - -```go -e := echo.New() -e.Pre(middleware.HTTPSWWWRedirect()) -``` - -## HTTPSNonWWWRedirect Middleware - -HTTPSNonWWWRedirect redirects http requests to https non www. -For example, http://www.labstack.com will be redirect to https://labstack.com. - -*Usage* - -```go -e := echo.New() -e.Pre(HTTPSNonWWWRedirect()) -``` - -## WWWRedirect Middleware - -WWWRedirect redirects non www requests to www. - -For example, http://labstack.com will be redirected to http://www.labstack.com. - -*Usage* - -```go -e := echo.New() -e.Pre(middleware.WWWRedirect()) -``` - -## NonWWWRedirect Middleware - -NonWWWRedirect redirects www requests to non www. -For example, http://www.labstack.com will be redirected to http://labstack.com. - -*Usage* - -```go -e := echo.New() -e.Pre(middleware.NonWWWRedirect()) -``` - -### Custom Configuration - -*Usage* - -```go -e := echo.New() -e.Use(middleware.HTTPSRedirectWithConfig(middleware.RedirectConfig{ - Code: http.StatusTemporaryRedirect, -})) -``` - -Example above will redirect the request HTTP to HTTPS with status code `307 - StatusTemporaryRedirect`. - -### Configuration - -```go -RedirectConfig struct { - // Skipper defines a function to skip middleware. - Skipper Skipper - - // Status code to be used when redirecting the request. - // Optional. Default value http.StatusMovedPermanently. - Code int `json:"code"` -} -``` - -*Default Configuration* - -```go -DefaultRedirectConfig = RedirectConfig{ - Skipper: defaultSkipper, - Code: http.StatusMovedPermanently, -} -``` diff --git a/website/content/middleware/secure.md b/website/content/middleware/secure.md deleted file mode 100644 index f2f0bcbd..00000000 --- a/website/content/middleware/secure.md +++ /dev/null @@ -1,97 +0,0 @@ -+++ -title = "Secure" -[menu.side] - name = "Secure" - parent = "middleware" - weight = 5 -+++ - -## Secure Middleware - -Secure middleware provides protection against cross-site scripting (XSS) attack, -content type sniffing, clickjacking, insecure connection and other code injection -attacks. - -*Usage* - -`e.Use(middleware.Secure())` - -### Custom Configuration - -*Usage* - -```go -e := echo.New() -e.Use(middleware.SecureWithConfig(middleware.SecureConfig{ - XSSProtection: "", - ContentTypeNosniff: "", - XFrameOptions: "", - HSTSMaxAge: 3600, - ContentSecurityPolicy: "default-src 'self'", -})) -``` - -Passing empty `XSSProtection`, `ContentTypeNosniff`, `XFrameOptions` or `ContentSecurityPolicy` -disables that protection. - -### Configuration - -```go -SecureConfig struct { - // Skipper defines a function to skip middleware. - Skipper Skipper - - // XSSProtection provides protection against cross-site scripting attack (XSS) - // by setting the `X-XSS-Protection` header. - // Optional. Default value "1; mode=block". - XSSProtection string `json:"xss_protection"` - - // ContentTypeNosniff provides protection against overriding Content-Type - // header by setting the `X-Content-Type-Options` header. - // Optional. Default value "nosniff". - ContentTypeNosniff string `json:"content_type_nosniff"` - - // XFrameOptions can be used to indicate whether or not a browser should - // be allowed to render a page in a , or . - // Sites can use this to avoid clickjacking attacks, by ensuring that their - // content is not embedded into other sites.provides protection against - // clickjacking. - // Optional. Default value "SAMEORIGIN". - // Possible values: - // - "SAMEORIGIN" - The page can only be displayed in a frame on the same origin as the page itself. - // - "DENY" - The page cannot be displayed in a frame, regardless of the site attempting to do so. - // - "ALLOW-FROM uri" - The page can only be displayed in a frame on the specified origin. - XFrameOptions string `json:"x_frame_options"` - - // HSTSMaxAge sets the `Strict-Transport-Security` header to indicate how - // long (in seconds) browsers should remember that this site is only to - // be accessed using HTTPS. This reduces your exposure to some SSL-stripping - // man-in-the-middle (MITM) attacks. - // Optional. Default value 0. - HSTSMaxAge int `json:"hsts_max_age"` - - // HSTSExcludeSubdomains won't include subdomains tag in the `Strict Transport Security` - // header, excluding all subdomains from security policy. It has no effect - // unless HSTSMaxAge is set to a non-zero value. - // Optional. Default value false. - HSTSExcludeSubdomains bool `json:"hsts_exclude_subdomains"` - - // ContentSecurityPolicy sets the `Content-Security-Policy` header providing - // security against cross-site scripting (XSS), clickjacking and other code - // injection attacks resulting from execution of malicious content in the - // trusted web page context. - // Optional. Default value "". - ContentSecurityPolicy string `json:"content_security_policy"` -} -``` - -*Default Configuration* - -```go -DefaultSecureConfig = SecureConfig{ - Skipper: defaultSkipper, - XSSProtection: "1; mode=block", - ContentTypeNosniff: "nosniff", - XFrameOptions: "SAMEORIGIN", -} -``` diff --git a/website/content/middleware/static.md b/website/content/middleware/static.md deleted file mode 100644 index 48ec832c..00000000 --- a/website/content/middleware/static.md +++ /dev/null @@ -1,70 +0,0 @@ -+++ -title = "Static" -[menu.side] - name = "Static" - parent = "middleware" - weight = 5 -+++ - -## Static Middleware - -Static middleware can be used to serve static files from the provided root directory. - -*Usage* - -```go -e := echo.New() -e.Use(middleware.Static("/static")) -``` - -This serves static files from `static` directory. For example, a request to `/js/main.js` -will fetch and serve `static/js/main.js` file. - -### Custom Configuration - -*Usage* - -```go -e := echo.New() -e.Use(middleware.StaticWithConfig(middleware.StaticConfig{ - Root: "static", - Browse: true, -})) -``` - -This serves static files from `static` directory and enables directory browsing. - -### Configuration - -```go -StaticConfig struct { - // Skipper defines a function to skip middleware. - Skipper Skipper - - // Root directory from where the static content is served. - // Required. - Root string `json:"root"` - - // Index file for serving a directory. - // Optional. Default value "index.html". - Index string `json:"index"` - - // Enable HTML5 mode by forwarding all not-found requests to root so that - // SPA (single-page application) can handle the routing. - // Optional. Default value false. - HTML5 bool `json:"html5"` - - // Enable directory browsing. - // Optional. Default value false. - Browse bool `json:"browse"` -} -``` - -*Default Configuration* - -```go -DefaultStaticConfig = StaticConfig{ - Skipper: defaultSkipper, - Index: "index.html", -} -``` diff --git a/website/content/middleware/trailing-slash.md b/website/content/middleware/trailing-slash.md deleted file mode 100644 index 425a0edb..00000000 --- a/website/content/middleware/trailing-slash.md +++ /dev/null @@ -1,63 +0,0 @@ -+++ -title = "Trailing Slash" -[menu.side] - name = "TrailingSlash" - parent = "middleware" - weight = 5 -+++ - -## AddTrailingSlash Middleware - -AddTrailingSlash middleware adds a trailing slash to the request URI. - -*Usage* - -```go -e := echo.New() -e.Pre(middleware.AddTrailingSlash()) -``` - -## RemoveTrailingSlash Middleware - -RemoveTrailingSlash middleware removes a trailing slash from the request URI. - -*Usage* - -```go -e := echo.New() -e.Pre(middleware.RemoveTrailingSlash()) -``` - -### Custom Configuration - -*Usage* - -```go -e := echo.New() -e.Use(middleware.AddTrailingSlashWithConfig(middleware.TrailingSlashConfig{ - RedirectCode: http.StatusMovedPermanently, -})) -``` - -Example above will add a trailing slash to the request URI and redirect with `308 - StatusMovedPermanently`. - -### Configuration - -```go -TrailingSlashConfig struct { - // Skipper defines a function to skip middleware. - Skipper Skipper - - // Status code to be used when redirecting the request. - // Optional, but when provided the request is redirected using this code. - RedirectCode int `json:"redirect_code"` -} -``` - -*Default Configuration* - -```go -DefaultTrailingSlashConfig = TrailingSlashConfig{ - Skipper: defaultSkipper, -} -``` diff --git a/website/content/recipes/cors.md b/website/content/recipes/cors.md deleted file mode 100644 index 6325427d..00000000 --- a/website/content/recipes/cors.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: CORS -menu: - side: - identifier: cors-middleware - parent: recipes - weight: 3 ---- - -## CORS Recipe - -### Server - -`server.go` - -{{< embed "cors/server.go" >}} - -### Maintainers - -- [vishr](https://github.com/vishr) - -### [Source Code]({{< source "cors" >}}) diff --git a/website/content/recipes/crud.md b/website/content/recipes/crud.md deleted file mode 100644 index 1071d7be..00000000 --- a/website/content/recipes/crud.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -title: CRUD -menu: - side: - parent: recipes - weight: 2 ---- - -## CRUD Recipe - -### Server - -`server.go` - -{{< embed "crud/server.go" >}} - -### Client - -`curl` - -#### Create User - -```sh -curl -X POST \ - -H 'Content-Type: application/json' \ - -d '{"name":"Joe Smith"}' \ - localhost:1323/users -``` - -*Response* - -```js -{ - "id": 1, - "name": "Joe Smith" -} -``` - -#### Get User - -```sh -curl localhost:1323/users/1 -``` - -*Response* - -```js -{ - "id": 1, - "name": "Joe Smith" -} -``` - -#### Update User - -```sh -curl -X PUT \ - -H 'Content-Type: application/json' \ - -d '{"name":"Joe"}' \ - localhost:1323/users/1 -``` - -*Response* - -```js -{ - "id": 1, - "name": "Joe" -} -``` - -#### Delete User - -```sh -curl -X DELETE localhost:1323/users/1 -``` - -*Response* - -`NoContent - 204` - -### Maintainers - -- [vishr](https://github.com/vishr) - -### [Source Code]({{< source "crud" >}}) diff --git a/website/content/recipes/embed-resources.md b/website/content/recipes/embed-resources.md deleted file mode 100644 index 456aecb9..00000000 --- a/website/content/recipes/embed-resources.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: Embed Resources -menu: - side: - parent: recipes - weight: 14 ---- - -## Embed Resources Recipe - -### With go.rice - -`server.go` - -{{< embed "embed-resources/server.go" >}} - -### Maintainers - -- [caarlos0](https://github.com/caarlos0) -- [maddie](https://github.com/maddie) - -### [Source Code]({{< source "embed-resources" >}}) diff --git a/website/content/recipes/file-upload.md b/website/content/recipes/file-upload.md deleted file mode 100644 index 22e21dd2..00000000 --- a/website/content/recipes/file-upload.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: File Upload -menu: - side: - parent: recipes - weight: 7 ---- - -## File Upload Recipe - -### How to upload single file with fields? - -#### Server - -`server.go` - -{{< embed "file-upload/single/server.go" >}} - -#### Client - -`index.html` - -{{< embed "file-upload/single/public/index.html" >}} - -### How to upload multiple files with fields? - -#### Server - -`server.go` - -{{< embed "file-upload/multiple/server.go" >}} - -#### Client - -`index.html` - -{{< embed "file-upload/multiple/public/index.html" >}} - -### Maintainers - -- [vishr](https://github.com/vishr) - -### Source Code - -- [single]({{< source "file-upload/single" >}}) -- [multiple]({{< source "file-upload/multiple" >}}) diff --git a/website/content/recipes/google-app-engine.md b/website/content/recipes/google-app-engine.md deleted file mode 100644 index d9a54a9d..00000000 --- a/website/content/recipes/google-app-engine.md +++ /dev/null @@ -1,137 +0,0 @@ ---- -title: Google App Engine -menu: - side: - parent: recipes - weight: 12 ---- - -## Google App Engine Recipe - -Google App Engine (GAE) provides a range of hosting options from pure PaaS (App Engine Classic) -through Managed VMs to fully self-managed or container-driven Compute Engine instances. Echo -works great with all of these but requires a few changes to the usual examples to run on the -AppEngine Classic and Managed VM options. With a small amount of effort though it's possible -to produce a codebase that will run on these and also non-managed platforms automatically. - -We'll walk through the changes needed to support each option. - -### Standalone - -Wait? What? I thought this was about AppEngine! Bear with me - the easiest way to show the changes -required is to start with a setup for standalone and work from there plus there's no reason we -wouldn't want to retain the ability to run our app anywhere, right? - -We take advantage of the go [build constraints or tags](http://golang.org/pkg/go/build/) to change -how we create and run the Echo server for each platform while keeping the rest of the application -(e.g. handler wireup) the same across all of them. - -First, we have the normal setup based on the examples but we split it into two files - `app.go` will -be common to all variations and holds the Echo instance variable. We initialise it from a function -and because it is a `var` this will happen _before_ any `init()` functions run - a feature that we'll -use to connect our handlers later. - -`app.go` - -{{< embed "google-app-engine/app.go" >}} - -A separate source file contains the function to create the Echo instance and add the static -file handlers and middleware. Note the build tag on the first line which says to use this when _not_ -bulding with appengine or appenginevm tags (which thoese platforms automatically add for us). We also -have the `main()` function to start serving our app as normal. This should all be very familiar. - -`app-standalone.go` - -{{< embed "google-app-engine/app-standalone.go" >}} - -The handler-wireup that would normally also be a part of this Echo setup moves to separate files which -take advantage of the ability to have multiple `init()` functions which run _after_ the `e` Echo var is -initialised but _before_ the `main()` function is executed. These allow additional handlers to attach -themselves to the instance - I've found the `Group` feature naturally fits into this pattern with a file -per REST endpoint, often with a higher-level `api` group created that they attach to instead of the root -Echo instance directly (so things like CORS middleware can be added at this higher common-level). - -`users.go` - -{{< embed "google-app-engine/users.go" >}} - -If we run our app it should execute as it did before when everything was in one file although we have -at least gained the ability to organize our handlers a little more cleanly. - -### AppEngine Classic and Managed VMs - -So far we've seen how to split apart the Echo creation and setup but still have the same app that -still only runs standalone. Now we'll see hwo those changes allow us to add support for AppEngine -hosting. - -Refer to the [AppEngine site](https://cloud.google.com/appengine/docs/go/) for full configuration -and deployment information. - -#### app.yaml configuration file - -Both of these are Platform as as Service options running on either sandboxed micro-containers -or managed Compute Engine instances. Both require an `app.yaml` file to describe the app to -the service. While the app _could_ still serve all it's static files itself, one of the benefits -of the platform is having Google's infrastructure handle that for us so it can be offloaded and -the app only has to deal with dynamic requests. The platform also handles logging and http gzip -compression so these can be removed from the codebase as well. - -The yaml file also contains other options to control instance size and auto-scaling so for true -deployment freedom you would likely have separate `app-classic.yaml` and `app-vm.yaml` files and -this can help when making the transition from AppEngine Classic to Managed VMs. - -`app-engine.yaml` - -{{< embed "google-app-engine/app-engine.yaml" >}} - -#### Router configuration - -We'll now use the [build constraints](http://golang.org/pkg/go/build/) again like we did when creating -our `app-standalone.go` instance but this time with the opposite tags to use this file _if_ the build has -the appengine or appenginevm tags (added automatically when deploying to these platforms). - -This allows us to replace the `createMux()` function to create our Echo server _without_ any of the -static file handling and logging + gzip middleware which is no longer required. Also worth nothing is -that GAE classic provides a wrapper to handle serving the app so instead of a `main()` function where -we run the server, we instead wire up the router to the default `http.Handler` instead. - -`app-engine.go` - -{{< embed "google-app-engine/app-engine.go" >}} - -Managed VMs are slightly different. They are expected to respond to requests on port 8080 as well -as special health-check requests used by the service to detect if an instance is still running in -order to provide automated failover and instance replacement. The `google.golang.org/appengine` -package provides this for us so we have a slightly different version for Managed VMs: - -`app-managed.go` - -{{< embed "google-app-engine/app-managed.go" >}} - -So now we have three different configurations. We can build and run our app as normal so it can -be executed locally, on a full Compute Engine instance or any other traditional hosting provider -(including EC2, Docker etc...). This build will ignore the code in appengine and appenginevm tagged -files and the `app.yaml` file is meaningless to anything other than the AppEngine platform. - -We can also run locally using the [Google AppEngine SDK for Go](https://cloud.google.com/appengine/downloads) -either emulating [AppEngine Classic](https://cloud.google.com/appengine/docs/go/tools/devserver): - - goapp serve - -Or [Managed VMs](https://cloud.google.com/appengine/docs/managed-vms/sdk#run-local): - - gcloud config set project [your project id] - gcloud preview app run . - -And of course we can deploy our app to both of these platforms for easy and inexpensive auto-scaling joy. - -Depending on what your app actually does it's possible you may need to make other changes to allow -switching between AppEngine provided service such as Datastore and alternative storage implementations -such as MongoDB. A combination of go interfaces and build constraints can make this fairly straightforward -but is outside the scope of this recipe. - -### Maintainers - -- [CaptainCodeman](https://github.com/CaptainCodeman) - -### [Source Code]({{< source "google-app-engine" >}}) diff --git a/website/content/recipes/graceful-shutdown.md b/website/content/recipes/graceful-shutdown.md deleted file mode 100644 index c4b08aed..00000000 --- a/website/content/recipes/graceful-shutdown.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: Graceful Shutdown -menu: - side: - parent: recipes - weight: 13 ---- - -## Graceful Shutdown Recipe - -### Using [grace](https://github.com/facebookgo/grace) - -`server.go` - -{{< embed "graceful-shutdown/grace/server.go" >}} - -### Using [graceful](https://github.com/tylerb/graceful) - -`server.go` - -{{< embed "graceful-shutdown/graceful/server.go" >}} - -### Maintainers - -- [mertenvg](https://github.com/mertenvg) - -### Source Code - -- [graceful]({{< source "graceful-shutdown/graceful" >}}) -- [grace]({{< source "graceful-shutdown/grace" >}}) diff --git a/website/content/recipes/hello-world.md b/website/content/recipes/hello-world.md deleted file mode 100644 index 175a41f2..00000000 --- a/website/content/recipes/hello-world.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Hello World -menu: - side: - parent: recipes - weight: 1 ---- - -## Hello World Recipe - -### Server - -`server.go` - -{{< embed "hello-world/server.go" >}} - -### Maintainers - -- [vishr](https://github.com/vishr) - -### [Source Code]({{< source "hello-world" >}}) diff --git a/website/content/recipes/http2.md b/website/content/recipes/http2.md deleted file mode 100644 index 2ea4b3d3..00000000 --- a/website/content/recipes/http2.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: HTTP2 -menu: - side: - identifier: http2 - parent: recipes - weight: 3 ---- - -## What is HTTP2? - -HTTP/2 (originally named HTTP/2.0) is the second major version of the HTTP network -protocol used by the World Wide Web - -### Features - -- Binary, instead of textual. -- Fully multiplexed, instead of ordered and blocking, can therefore use just one TCP connection. -- Uses header compression to reduce overhead. -- Allows servers to "push" responses proactively into client caches. - -## How to run an HTTP/2 and HTTPS server? - -> Standard engine only - -### Generate a self-signed X.509 TLS certificate (HTTP/2 requires TLS to operate) - -```sh -go run $GOROOT/src/crypto/tls/generate_cert.go --host localhost -``` - -This will generate `cert.pem` and `key.pem` files. - -> For demo purpose, we are using a self-signed certificate. Ideally you should obtain -a certificate from [CA](https://en.wikipedia.org/wiki/Certificate_authority). - -### Configure a server with `engine.Config` - -`server.go` - -{{< embed "http2/server.go" >}} - -### Endpoints - -- https://localhost:1323/request (Displays the information about received HTTP request) -- https://localhost:1323/stream (Streams the current time every second) - -### Maintainers - -- [vishr](https://github.com/vishr) - -### [Source Code]({{< source "http2" >}}) diff --git a/website/content/recipes/jsonp.md b/website/content/recipes/jsonp.md deleted file mode 100644 index 74fd8134..00000000 --- a/website/content/recipes/jsonp.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: JSONP -menu: - side: - parent: recipes - weight: 6 ---- - -## JSONP Recipe - -JSONP is a method that allows cross-domain server calls. You can read more about it at the JSON versus JSONP Tutorial. - -### Server - -`server.go` - -{{< embed "jsonp/server.go" >}} - -### Client - -`index.html` - -{{< embed "jsonp/public/index.html" >}} - -### Maintainers - -- [willf](https://github.com/willf) - -### [Source Code]({{< source "jsonp" >}}) diff --git a/website/content/recipes/jwt.md b/website/content/recipes/jwt.md deleted file mode 100644 index 3ff25d0c..00000000 --- a/website/content/recipes/jwt.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: JWT -menu: - side: - identifier: jwt-recipe - parent: recipes - weight: 11 ---- - -## JWT Recipe - -- JWT authentication using HS256 algorithm. -- JWT is retrieved from `Authorization` request header. - -### Server using Map claims - -`server.go` - -{{< embed "jwt/map-claims/server.go" >}} - -### Server using custom claims - -`server.go` - -{{< embed "jwt/custom-claims/server.go" >}} - -### Client - -`curl` - -#### Login - -Login using username and password to retrieve a token. - -```sh -curl -X POST -d 'username=jon' -d 'password=shhh!' localhost:1323/login -``` - -*Response* - -```js -{ - "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0NjE5NTcxMzZ9.RB3arc4-OyzASAaUhC2W3ReWaXAt_z2Fd3BN4aWTgEY" -} -``` - -#### Request - -Request a restricted resource using the token in `Authorization` request header. - -```sh -curl localhost:1323/restricted -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0NjE5NTcxMzZ9.RB3arc4-OyzASAaUhC2W3ReWaXAt_z2Fd3BN4aWTgEY" -``` - -*Response* - -``` -Welcome Jon Snow! -``` - -### Maintainers - -- [vishr](https://github.com/vishr) -- [axdg](https://github.com/axdg) -- [matcornic](https://github.com/matcornic) - -### Source Code - -- [With default Map claims]({{< source "jwt/map-claims" >}}) -- [With custom claims]({{< source "jwt/custom-claims" >}}) diff --git a/website/content/recipes/middleware.md b/website/content/recipes/middleware.md deleted file mode 100644 index 588dd2c6..00000000 --- a/website/content/recipes/middleware.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: Middleware -menu: - side: - identifier: "recipes-middleware" - parent: recipes - weight: 3 ---- - -## Middleware Recipe - -### How to write a custom middleware? - -- Middleware to collect request count, statuses and uptime. -- Middleware to write custom `Server` header to the response. - -#### Server - -`server.go` - -{{< embed "middleware/server.go" >}} - -#### Response - -*Headers* -```sh -Content-Length:122 -Content-Type:application/json; charset=utf-8 -Date:Thu, 14 Apr 2016 20:31:46 GMT -Server:Echo/2.0 -``` - -*Body* - -```js -{ - "uptime": "2016-04-14T13:28:48.486548936-07:00", - "requestCount": 5, - "statuses": { - "200": 4, - "404": 1 - } -} -``` - -### Maintainers - -- [vishr](https://github.com/vishr) - -### [Source Code]({{< source "middleware" >}}) diff --git a/website/content/recipes/streaming-response.md b/website/content/recipes/streaming-response.md deleted file mode 100644 index 82b9b8d3..00000000 --- a/website/content/recipes/streaming-response.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: Streaming Response -menu: - side: - parent: recipes - weight: 9 ---- - -## Streaming Response Recipe - -- Send data as it is produced -- Streaming JSON response with chunked transfer encoding - -### Server - -`server.go` - -{{< embed "streaming-response/server.go" >}} - -### Client - -```sh -$ curl localhost:1323 -``` - -### Output - -```sh -{"Altitude":-97,"Latitude":37.819929,"Longitude":-122.478255} -{"Altitude":1899,"Latitude":39.096849,"Longitude":-120.032351} -{"Altitude":2619,"Latitude":37.865101,"Longitude":-119.538329} -{"Altitude":42,"Latitude":33.812092,"Longitude":-117.918974} -{"Altitude":15,"Latitude":37.77493,"Longitude":-122.419416} -``` - -### Maintainers - -- [vishr](https://github.com/vishr) - -### [Source Code]({{< source "streaming-response" >}}) diff --git a/website/content/recipes/subdomains.md b/website/content/recipes/subdomains.md deleted file mode 100644 index 57168de7..00000000 --- a/website/content/recipes/subdomains.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: Subdomains -menu: - side: - parent: recipes - weight: 10 ---- - -## Subdomains Recipe - -`server.go` - -{{< embed "subdomains/server.go" >}} - -### Maintainers - -- [axdg](https://github.com/axdg) -- [vishr](https://github.com/vishr) - -### [Source Code]({{< source "subdomains" >}}) diff --git a/website/content/recipes/website.md b/website/content/recipes/website.md deleted file mode 100644 index 635b4a33..00000000 --- a/website/content/recipes/website.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: Website -draft: true -menu: - side: - parent: recipes - weight: 4 ---- - -## Website Recipe - -### Server - -`server.go` - -{{< embed "website/server.go" >}} - -### Client - -`index.html` - -{{< embed "website/public/index.html" >}} - -### Maintainers - -- [vishr](https://github.com/vishr) - -### [Source Code]({{< source "website" >}}) diff --git a/website/content/recipes/websocket.md b/website/content/recipes/websocket.md deleted file mode 100644 index 7782c3da..00000000 --- a/website/content/recipes/websocket.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: WebSocket -menu: - side: - parent: recipes - weight: 5 ---- - -## WebSocket Recipe - -> Only supported in `standard` engine. - -### Using `net` WebSocket - -#### Server - -`server.go` - -{{< embed "websocket/net/server.go" >}} - -### Using `gorilla` WebSocket - -#### Server - -`server.go` - -{{< embed "websocket/gorilla/server.go" >}} - -### Client - -`index.html` - -{{< embed "websocket/public/index.html" >}} - -### Output - -`Client` - -```sh -Hello, Client! -Hello, Client! -Hello, Client! -Hello, Client! -Hello, Client! -``` - -`Server` - -```sh -Hello, Server! -Hello, Server! -Hello, Server! -Hello, Server! -Hello, Server! -``` - -### Maintainers - -- [vishr](https://github.com/vishr) - -### [Source Code]({{< source "websocket" >}}) diff --git a/website/content/support-echo.md b/website/content/support-echo.md deleted file mode 100644 index 8f8f3f62..00000000 --- a/website/content/support-echo.md +++ /dev/null @@ -1,23 +0,0 @@ -+++ -title = "Support" -+++ - -## Support Echo Development - - - - - Support Vue.js on Patreon (recurring pledge) - - - - - - - Donate via PayPal (one time) - - - -Echo is an MIT licensed open source project and completely free to use. If you are -using Echo in your products/projects, please consider sponsoring Echo to ensure -it is actively developed and maintained. diff --git a/website/layouts/_default/single.html b/website/layouts/_default/single.html deleted file mode 100644 index a251d929..00000000 --- a/website/layouts/_default/single.html +++ /dev/null @@ -1,37 +0,0 @@ -{{ partial "head.html" . }} - - {{ partial "navbar.html" . }} - {{ partial "sidenav.html" . }} - {{ partial "search.html" . }} - - {{ partial "ad.html" }} - - - {{ partial "notice.html" }} - - - {{ .Content }} - - - - - - - {{ partial "footer.html" . }} - -
- - - Support Vue.js on Patreon (recurring pledge) - -
- - - Donate via PayPal (one time) - -