mirror of
https://github.com/labstack/echo.git
synced 2026-05-16 09:48:24 +02:00
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
## Performance
|
## Performance
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
|
|||||||
+22
-18
@@ -13,8 +13,6 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"golang.org/x/net/websocket"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@@ -175,16 +173,15 @@ type (
|
|||||||
}
|
}
|
||||||
|
|
||||||
context struct {
|
context struct {
|
||||||
request *http.Request
|
request *http.Request
|
||||||
response *Response
|
response *Response
|
||||||
webSocket *websocket.Conn
|
path string
|
||||||
path string
|
pnames []string
|
||||||
pnames []string
|
pvalues []string
|
||||||
pvalues []string
|
query url.Values
|
||||||
query url.Values
|
handler HandlerFunc
|
||||||
handler HandlerFunc
|
store Map
|
||||||
store Map
|
echo *Echo
|
||||||
echo *Echo
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -238,15 +235,22 @@ func (c *context) SetPath(p string) {
|
|||||||
c.path = p
|
c.path = p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) Param(name string) (value string) {
|
func (c *context) Param(name string) string {
|
||||||
l := len(c.pnames)
|
|
||||||
for i, n := range c.pnames {
|
for i, n := range c.pnames {
|
||||||
if n == name && i < l {
|
if i < len(c.pnames) {
|
||||||
value = c.pvalues[i]
|
if strings.HasPrefix(n, name) {
|
||||||
break
|
return c.pvalues[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Param name with aliases
|
||||||
|
for _, p := range strings.Split(n, ",") {
|
||||||
|
if p == name {
|
||||||
|
return c.pvalues[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) ParamNames() []string {
|
func (c *context) ParamNames() []string {
|
||||||
|
|||||||
@@ -250,6 +250,18 @@ func TestContextPathParam(t *testing.T) {
|
|||||||
assert.Equal(t, "501", c.Param("fid"))
|
assert.Equal(t, "501", c.Param("fid"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestContextPathParamNamesAlais(t *testing.T) {
|
||||||
|
e := New()
|
||||||
|
req, _ := http.NewRequest(GET, "/", nil)
|
||||||
|
c := e.NewContext(req, nil)
|
||||||
|
|
||||||
|
c.SetParamNames("id,name")
|
||||||
|
c.SetParamValues("joe")
|
||||||
|
|
||||||
|
assert.Equal(t, "joe", c.Param("id"))
|
||||||
|
assert.Equal(t, "joe", c.Param("name"))
|
||||||
|
}
|
||||||
|
|
||||||
func TestContextFormValue(t *testing.T) {
|
func TestContextFormValue(t *testing.T) {
|
||||||
f := make(url.Values)
|
f := make(url.Values)
|
||||||
f.Set("name", "Jon Snow")
|
f.Set("name", "Jon Snow")
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package echo
|
package echo
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
type (
|
type (
|
||||||
// Router is the registry of all registered routes for an `Echo` instance for
|
// Router is the registry of all registered routes for an `Echo` instance for
|
||||||
// request matching and URL path parameter parsing.
|
// request matching and URL path parameter parsing.
|
||||||
@@ -170,7 +172,12 @@ func (r *Router) insert(method, path string, h HandlerFunc, t kind, ppath string
|
|||||||
if h != nil {
|
if h != nil {
|
||||||
cn.addHandler(method, h)
|
cn.addHandler(method, h)
|
||||||
cn.ppath = ppath
|
cn.ppath = ppath
|
||||||
cn.pnames = pnames
|
for i, n := range cn.pnames {
|
||||||
|
// Param name aliases
|
||||||
|
if !strings.Contains(n, pnames[i]) {
|
||||||
|
cn.pnames[i] += "," + pnames[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|||||||
+6
-3
@@ -3,6 +3,7 @@ package echo
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -823,9 +824,11 @@ func TestRouterAPI(t *testing.T) {
|
|||||||
c := e.NewContext(nil, nil).(*context)
|
c := e.NewContext(nil, nil).(*context)
|
||||||
for _, route := range gitHubAPI {
|
for _, route := range gitHubAPI {
|
||||||
r.Find(route.Method, route.Path, c)
|
r.Find(route.Method, route.Path, c)
|
||||||
for i, n := range c.pnames {
|
for _, n := range c.pnames {
|
||||||
if assert.NotEmpty(t, n) {
|
for _, p := range strings.Split(n, ",") {
|
||||||
assert.Equal(t, n, c.pnames[i])
|
if assert.NotEmpty(t, p) {
|
||||||
|
assert.Equal(t, c.Param(p), ":"+p)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,2 +1,2 @@
|
|||||||
build:
|
build:
|
||||||
rm -rf public && hugo
|
rm -rf public/v3 && hugo
|
||||||
|
|||||||
+2
-1
@@ -1,9 +1,10 @@
|
|||||||
{
|
{
|
||||||
"baseurl": "https://echo.labstack.com",
|
"baseurl": "https://echo.labstack.com/",
|
||||||
"languageCode": "en-us",
|
"languageCode": "en-us",
|
||||||
"title": "Echo - Fast and unfancy HTTP server framework for Go (Golang)",
|
"title": "Echo - Fast and unfancy HTTP server framework for Go (Golang)",
|
||||||
"canonifyurls": true,
|
"canonifyurls": true,
|
||||||
"googleAnalytics": "UA-85059636-2",
|
"googleAnalytics": "UA-85059636-2",
|
||||||
|
"publishdir": "public/v3",
|
||||||
"permalinks": {
|
"permalinks": {
|
||||||
"guide": "/guide/:filename",
|
"guide": "/guide/:filename",
|
||||||
"middleware": "/middleware/:filename",
|
"middleware": "/middleware/:filename",
|
||||||
|
|||||||
@@ -11,8 +11,6 @@ description = "Customizing Echo"
|
|||||||
|
|
||||||
### HTTP Error Handler
|
### HTTP Error Handler
|
||||||
|
|
||||||
`Echo#SetHTTPErrorHandler(h HTTPErrorHandler)` registers a custom `Echo#HTTPErrorHandler`.
|
|
||||||
|
|
||||||
Default HTTP error handler rules:
|
Default HTTP error handler rules:
|
||||||
|
|
||||||
- If error is of type `Echo#HTTPError` it sends HTTP response with status code `HTTPError.Code`
|
- If error is of type `Echo#HTTPError` it sends HTTP response with status code `HTTPError.Code`
|
||||||
@@ -20,79 +18,32 @@ and message `HTTPError.Message`.
|
|||||||
- Else it sends `500 - Internal Server Error`.
|
- Else it sends `500 - Internal Server Error`.
|
||||||
- If debug mode is enabled, it uses `error.Error()` as status message.
|
- If debug mode is enabled, it uses `error.Error()` as status message.
|
||||||
|
|
||||||
### Debug
|
You can also set a custom HTTP error handler using `Echo#HTTPErrorHandler`.
|
||||||
|
|
||||||
`Echo#SetDebug(on bool)` enable/disable debug mode.
|
### Debugging
|
||||||
|
|
||||||
|
`Echo#Debug` enables/disables debug mode.
|
||||||
|
|
||||||
### Logging
|
### Logging
|
||||||
|
|
||||||
#### Custom Logger
|
|
||||||
|
|
||||||
`Echo#SetLogger(l log.Logger)`
|
|
||||||
|
|
||||||
SetLogger defines a custom logger.
|
|
||||||
|
|
||||||
#### Log Output
|
#### Log Output
|
||||||
|
|
||||||
`Echo#SetLogOutput(w io.Writer)` sets the output destination for the logger. Default
|
`Echo#Logger.SetOutput(io.Writer)` sets the output destination for the logger.
|
||||||
value `os.Stdout`
|
Default value `os.Stdout`
|
||||||
|
|
||||||
To completely disable logs use `Echo#SetLogOutput(io.Discard)`
|
To completely disable logs use `Echo#Logger.SetOutput(io.Discard)` or `Echo#Logger.SetLevel(log.OFF)`
|
||||||
|
|
||||||
#### Log Level
|
#### Log Level
|
||||||
|
|
||||||
`Echo#SetLogLevel(l log.Level)`
|
`Echo#Logger.SetLevel(log.Lvl)`
|
||||||
|
|
||||||
SetLogLevel sets the log level for the logger. Default value `5` (OFF).
|
SetLogLevel sets the log level for the logger. Default value `OFF`.
|
||||||
Possible values:
|
Possible values:
|
||||||
|
|
||||||
- `0` (DEBUG)
|
- `DEBUG`
|
||||||
- `1` (INFO)
|
- `INFO`
|
||||||
- `2` (WARN)
|
- `WARN`
|
||||||
- `3` (ERROR)
|
- `ERROR`
|
||||||
- `4` (FATAL)
|
- `OFF`
|
||||||
- `5` (OFF)
|
|
||||||
|
|
||||||
### HTTP Engine
|
You can also set a custom logger using `Echo#Logger`.
|
||||||
|
|
||||||
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(<engine>.WithTLS(":1323", "<certFile>", "<keyFile>"))`
|
|
||||||
|
|
||||||
#### Running a server with engine configuration
|
|
||||||
|
|
||||||
`e.Run(<engine>.WithConfig(<config>))`
|
|
||||||
|
|
||||||
##### 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)
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -9,82 +9,47 @@ description = "Frequently asked questions in Echo"
|
|||||||
|
|
||||||
## FAQ
|
## FAQ
|
||||||
|
|
||||||
Q: **How to retrieve `*http.Request` and `http.ResponseWriter` from `echo.Context`?**
|
Q: How to retrieve `*http.Request` and `http.ResponseWriter` from `echo.Context`?
|
||||||
|
|
||||||
- `http.Request` > `c.Request().(*standard.Request).Request`
|
- `http.Request` > `c.Request()`
|
||||||
- `http.ResponseWriter` > `c.Response()`
|
- `http.ResponseWriter` > `c.Response()`
|
||||||
|
|
||||||
> Standard engine only
|
Q: How to use standard handler `func(http.ResponseWriter, *http.Request)` with Echo?
|
||||||
|
|
||||||
Q: **How to use standard handler `func(http.ResponseWriter, *http.Request)` with Echo?**
|
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func handler(w http.ResponseWriter, r *http.Request) {
|
func handler(w http.ResponseWriter, r *http.Request) {
|
||||||
io.WriteString(w, "Handler!")
|
io.WriteString(w, "Echo!")
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
e := echo.New()
|
e := echo.New()
|
||||||
e.GET("/", standard.WrapHandler(http.HandlerFunc(handler)))
|
e.GET("/", echo.WrapHandler(http.HandlerFunc(handler)))
|
||||||
e.Run(standard.New(":1323"))
|
e.Start(":1323")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Q: **How to use fasthttp handler `func(fasthttp.RequestCtx)` with Echo?**
|
Q: How to use standard middleware `func(http.Handler) http.Handler` 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
|
```go
|
||||||
func middleware(h http.Handler) http.Handler {
|
func middleware(h http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
println("Middleware!")
|
println("middleware")
|
||||||
h.ServeHTTP(w, r)
|
h.ServeHTTP(w, r)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
e := echo.New()
|
e := echo.New()
|
||||||
e.Use(standard.WrapMiddleware(middleware))
|
e.Use(echo.WrapMiddleware(middleware))
|
||||||
e.GET("/", func(c echo.Context) error {
|
e.GET("/", func(c echo.Context) error {
|
||||||
return c.String(http.StatusOK, "OK")
|
return c.String(http.StatusOK, "Echo!")
|
||||||
})
|
})
|
||||||
e.Run(standard.New(":1323"))
|
e.Start(":1323")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Q: **How to use fasthttp middleware `func(http.Handler) http.Handler` with Echo?**
|
Q: How to run Echo on a specific IP address?
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func middleware(h fh.RequestHandler) fh.RequestHandler {
|
e.Start("<ip>:<port>")
|
||||||
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"))
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
<!-- ### Q: How to run Echo on specific IP and port?
|
|
||||||
|
|
||||||
```go
|
|
||||||
``` -->
|
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ Echo is developed and tested using Go `1.6.x` and `1.7.x`
|
|||||||
$ go get -u github.com/labstack/echo
|
$ 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.
|
> 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)
|
### [Migrating Guide](/guide/migration)
|
||||||
|
|
||||||
Echo follows [semantic versioning](http://semver.org) managed through GitHub releases.
|
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).
|
Specific version of Echo can be installed using a [package manager](https://github.com/avelino/awesome-go#package-management).
|
||||||
|
|||||||
@@ -1,93 +0,0 @@
|
|||||||
+++
|
|
||||||
title = "Migrating"
|
|
||||||
description = "Migrating from Echo v1 to v2"
|
|
||||||
[menu.side]
|
|
||||||
name = "Migrating"
|
|
||||||
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.
|
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
+++
|
||||||
|
title = "Migration"
|
||||||
|
description = "Migration"
|
||||||
|
[menu.side]
|
||||||
|
name = "Migration"
|
||||||
|
parent = "guide"
|
||||||
|
weight = 2
|
||||||
|
+++
|
||||||
|
|
||||||
|
## V3
|
||||||
|
|
||||||
|
### Change Log
|
||||||
|
|
||||||
|
- Automatic TLS certificates via [Let's Encrypt](https://letsencrypt.org/)
|
||||||
|
- Built-in support for graceful shutdown
|
||||||
|
- Dropped static middleware in favor of `Echo#Static`
|
||||||
|
- Utility functions to wrap standard handler and middleware
|
||||||
|
- `Map` type as shorthand for `map[string]interface{}`
|
||||||
|
- Context now wraps standard net/http Request and Response
|
||||||
|
- New configuration
|
||||||
|
- `Echo#ShutdownTimeout`
|
||||||
|
- `Echo#DisableHTTP2`
|
||||||
|
- New API
|
||||||
|
- `Echo#Start()`
|
||||||
|
- `Echo#StartTLS()`
|
||||||
|
- `Echo#StartAutoTLS()`
|
||||||
|
- `Echo#StartServer()`
|
||||||
|
- `Echo#Shutdown()`
|
||||||
|
- `Echo#ShutdownTLS()`
|
||||||
|
- `Context#Scheme()`
|
||||||
|
- `Context#RealIP()`
|
||||||
|
- `Context#IsTLS()`
|
||||||
|
- Exposed the following properties instead of setter / getter functions on `Echo` instance:
|
||||||
|
- `Binder`
|
||||||
|
- `Renderer`
|
||||||
|
- `HTTPErrorHandler`
|
||||||
|
- `Debug`
|
||||||
|
- `Logger`
|
||||||
|
- Enhanced redirect and CORS middleware
|
||||||
|
- Dropped API
|
||||||
|
- `Echo#Run()`
|
||||||
|
- `Context#P()`
|
||||||
|
- Dropped standard `Context` support
|
||||||
|
- Dropped support for `fasthttp`
|
||||||
|
- Dropped deprecated API
|
||||||
|
- Moved `Logger` interface to root level
|
||||||
|
- Moved website and recipes to the main repo
|
||||||
|
- Updated docs and fixed numerous issues
|
||||||
|
|
||||||
|
### [Recipes](/recipes/hello-world)
|
||||||
@@ -8,7 +8,6 @@ title = "Index"
|
|||||||
|
|
||||||
- Optimized HTTP router which smartly prioritize routes
|
- Optimized HTTP router which smartly prioritize routes
|
||||||
- Build robust and scalable RESTful APIs
|
- Build robust and scalable RESTful APIs
|
||||||
- Run with standard HTTP server or FastHTTP server
|
|
||||||
- Group APIs
|
- Group APIs
|
||||||
- Extensible middleware framework
|
- Extensible middleware framework
|
||||||
- Define middleware at root, group or route level
|
- Define middleware at root, group or route level
|
||||||
@@ -18,11 +17,12 @@ title = "Index"
|
|||||||
- Template rendering with any template engine
|
- Template rendering with any template engine
|
||||||
- Define your format for the logger
|
- Define your format for the logger
|
||||||
- Highly customizable
|
- Highly customizable
|
||||||
|
- Automatic TLS via Let’s Encrypt
|
||||||
|
- Built-in graceful shutdown
|
||||||
|
|
||||||
## Performance
|
## Performance
|
||||||
|
|
||||||
<img style="width: 75%;" src="http://i.imgur.com/F2V7TfO.png" alt="Performance">
|
<img style="width: 75%;" src="https://i.imgur.com/F2V7TfO.png" alt="Performance">
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
|
|||||||
@@ -40,3 +40,4 @@
|
|||||||
<script async defer id="github-bjs" src="//buttons.github.io/buttons.js"></script>
|
<script async defer id="github-bjs" src="//buttons.github.io/buttons.js"></script>
|
||||||
<script src="https://cdn.labstack.com/scripts/prism.js"></script>
|
<script src="https://cdn.labstack.com/scripts/prism.js"></script>
|
||||||
<script src="https://cdn.labstack.com/scripts/doc.js"></script>
|
<script src="https://cdn.labstack.com/scripts/doc.js"></script>
|
||||||
|
<script src="{{ .Site.BaseURL }}scripts/main.js"></script>
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
<link rel="stylesheet" href="https://cdn.labstack.com/styles/prism.css">
|
<link rel="stylesheet" href="https://cdn.labstack.com/styles/prism.css">
|
||||||
<link rel="stylesheet" href="https://cdn.labstack.com/styles/base.css">
|
<link rel="stylesheet" href="https://cdn.labstack.com/styles/base.css">
|
||||||
<link rel="stylesheet" href="https://cdn.labstack.com/styles/doc.css">
|
<link rel="stylesheet" href="https://cdn.labstack.com/styles/doc.css">
|
||||||
<link rel="stylesheet" href="{{ .Site.BaseURL }}/styles/main.css">
|
<link rel="stylesheet" href="{{ .Site.BaseURL}}/styles/main.css">
|
||||||
<script>
|
<script>
|
||||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||||
|
|||||||
@@ -5,9 +5,15 @@
|
|||||||
<a class="support w3-btn w3-white w3-border w3-border-theme w3-round-xlarge" href="/support-echo">
|
<a class="support w3-btn w3-white w3-border w3-border-theme w3-round-xlarge" href="/support-echo">
|
||||||
<i class="fa fa-heart" aria-hidden="true"></i> Support Echo
|
<i class="fa fa-heart" aria-hidden="true"></i> Support Echo
|
||||||
</a>
|
</a>
|
||||||
|
<h4>
|
||||||
|
<select class="w3-select w3-border" onchange="version(this);">
|
||||||
|
<option value="/v2">v2</option>
|
||||||
|
<option value="/" selected>v3</option>
|
||||||
|
</select>
|
||||||
|
</h4>
|
||||||
{{ $currentNode := . }}
|
{{ $currentNode := . }}
|
||||||
{{ range .Site.Menus.side }}
|
{{ range .Site.Menus.side }}
|
||||||
<h4>{{ .Pre }} {{ .Name }}</h4>
|
<h3>{{ .Pre }} {{ .Name }}</h3>
|
||||||
{{ range .Children }}
|
{{ range .Children }}
|
||||||
<a{{ if $currentNode.IsMenuCurrent "side" . }} class="active"{{ end }} href="{{ .URL }}">
|
<a{{ if $currentNode.IsMenuCurrent "side" . }} class="active"{{ end }} href="{{ .URL }}">
|
||||||
{{ .Name }}
|
{{ .Name }}
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
function version(e) {
|
||||||
|
window.location = e.value;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user