From c5a3575d4c4121ba7a01a9aa21637c712adec067 Mon Sep 17 00:00:00 2001 From: Vishal Rana Date: Sun, 13 Nov 2016 09:36:57 -0800 Subject: [PATCH] updated migration guide Signed-off-by: Vishal Rana --- README.md | 2 +- context.go | 40 ++++++----- context_test.go | 12 ++++ router.go | 9 ++- router_test.go | 9 ++- website/Makefile | 2 +- website/config.json | 3 +- website/content/guide/customization.md | 79 +++++----------------- website/content/guide/faq.md | 61 ++++------------- website/content/guide/installation.md | 4 +- website/content/guide/migrating.md | 93 -------------------------- website/content/guide/migration.md | 50 ++++++++++++++ website/content/index.md | 6 +- website/layouts/partials/footer.html | 1 + website/layouts/partials/head.html | 2 +- website/layouts/partials/sidenav.html | 8 ++- website/static/scripts/main.js | 3 + 17 files changed, 147 insertions(+), 237 deletions(-) delete mode 100644 website/content/guide/migrating.md create mode 100644 website/content/guide/migration.md create mode 100644 website/static/scripts/main.js diff --git a/README.md b/README.md index 038c4f540..ebc754c6e 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ ## Performance -![Performance](http://i.imgur.com/F2V7TfO.png) +![Performance](https://i.imgur.com/F2V7TfO.png) ## Quick Start diff --git a/context.go b/context.go index 868e37bbf..cc76a870d 100644 --- a/context.go +++ b/context.go @@ -13,8 +13,6 @@ import ( "os" "path/filepath" "strings" - - "golang.org/x/net/websocket" ) type ( @@ -175,16 +173,15 @@ type ( } context struct { - request *http.Request - response *Response - webSocket *websocket.Conn - path string - pnames []string - pvalues []string - query url.Values - handler HandlerFunc - store Map - echo *Echo + request *http.Request + response *Response + path string + pnames []string + pvalues []string + query url.Values + handler HandlerFunc + store Map + echo *Echo } ) @@ -238,15 +235,22 @@ func (c *context) SetPath(p string) { c.path = p } -func (c *context) Param(name string) (value string) { - l := len(c.pnames) +func (c *context) Param(name string) string { for i, n := range c.pnames { - if n == name && i < l { - value = c.pvalues[i] - break + if i < len(c.pnames) { + if strings.HasPrefix(n, name) { + 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 { diff --git a/context_test.go b/context_test.go index 6993d610f..4d4e62f47 100644 --- a/context_test.go +++ b/context_test.go @@ -250,6 +250,18 @@ func TestContextPathParam(t *testing.T) { 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) { f := make(url.Values) f.Set("name", "Jon Snow") diff --git a/router.go b/router.go index 78c29b9d5..83895a45f 100644 --- a/router.go +++ b/router.go @@ -1,5 +1,7 @@ package echo +import "strings" + type ( // Router is the registry of all registered routes for an `Echo` instance for // 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 { cn.addHandler(method, h) 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 diff --git a/router_test.go b/router_test.go index 338e21d7a..968c8dde4 100644 --- a/router_test.go +++ b/router_test.go @@ -3,6 +3,7 @@ package echo import ( "fmt" "net/http" + "strings" "testing" "github.com/stretchr/testify/assert" @@ -823,9 +824,11 @@ func TestRouterAPI(t *testing.T) { c := e.NewContext(nil, nil).(*context) for _, route := range gitHubAPI { r.Find(route.Method, route.Path, c) - for i, n := range c.pnames { - if assert.NotEmpty(t, n) { - assert.Equal(t, n, c.pnames[i]) + for _, n := range c.pnames { + for _, p := range strings.Split(n, ",") { + if assert.NotEmpty(t, p) { + assert.Equal(t, c.Param(p), ":"+p) + } } } } diff --git a/website/Makefile b/website/Makefile index c5e4c030a..8dc1c36b8 100644 --- a/website/Makefile +++ b/website/Makefile @@ -1,2 +1,2 @@ build: - rm -rf public && hugo + rm -rf public/v3 && hugo diff --git a/website/config.json b/website/config.json index 4f48e64ee..1a04be2d1 100644 --- a/website/config.json +++ b/website/config.json @@ -1,9 +1,10 @@ { - "baseurl": "https://echo.labstack.com", + "baseurl": "https://echo.labstack.com/", "languageCode": "en-us", "title": "Echo - Fast and unfancy HTTP server framework for Go (Golang)", "canonifyurls": true, "googleAnalytics": "UA-85059636-2", + "publishdir": "public/v3", "permalinks": { "guide": "/guide/:filename", "middleware": "/middleware/:filename", diff --git a/website/content/guide/customization.md b/website/content/guide/customization.md index a555cb960..3e3ef1196 100644 --- a/website/content/guide/customization.md +++ b/website/content/guide/customization.md @@ -11,8 +11,6 @@ description = "Customizing Echo" ### 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` @@ -20,79 +18,32 @@ 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. +You can also set a custom HTTP error handler using `Echo#HTTPErrorHandler`. -### Logging +### Debugging -#### Custom Logger +`Echo#Debug` enables/disables debug mode. -`Echo#SetLogger(l log.Logger)` - -SetLogger defines a custom logger. +### Logging #### Log Output -`Echo#SetLogOutput(w io.Writer)` sets the output destination for the logger. Default -value `os.Stdout` +`Echo#Logger.SetOutput(io.Writer)` sets the output destination for the logger. +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 -`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: -- `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 +- `DEBUG` +- `INFO` +- `WARN` +- `ERROR` +- `OFF` -```go -s := standard.New(":1323") -s.MaxHeaderBytes = 1 << 20 -e.Run(s) -``` +You can also set a custom logger using `Echo#Logger`. diff --git a/website/content/guide/faq.md b/website/content/guide/faq.md index 394dbb8ca..121c456d0 100644 --- a/website/content/guide/faq.md +++ b/website/content/guide/faq.md @@ -9,82 +9,47 @@ description = "Frequently asked questions in Echo" ## 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()` -> 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 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!") + io.WriteString(w, "Echo!") } func main() { e := echo.New() - e.GET("/", fasthttp.WrapHandler(handler)) - e.Run(fasthttp.New(":1323")) + e.GET("/", echo.WrapHandler(http.HandlerFunc(handler))) + e.Start(":1323") } ``` -Q: **How to use standard middleware `func(http.Handler) http.Handler` with Echo?** +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!") + println("middleware") h.ServeHTTP(w, r) }) } func main() { e := echo.New() - e.Use(standard.WrapMiddleware(middleware)) + e.Use(echo.WrapMiddleware(middleware)) 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 -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")) -} +e.Start(":") ``` - - diff --git a/website/content/guide/installation.md b/website/content/guide/installation.md index 78449b9b6..a05afc7ac 100644 --- a/website/content/guide/installation.md +++ b/website/content/guide/installation.md @@ -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 ``` -> 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. 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 0baea8c18..000000000 --- a/website/content/guide/migrating.md +++ /dev/null @@ -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. diff --git a/website/content/guide/migration.md b/website/content/guide/migration.md new file mode 100644 index 000000000..861d12f3c --- /dev/null +++ b/website/content/guide/migration.md @@ -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) diff --git a/website/content/index.md b/website/content/index.md index 16b29f3d4..8faa967f4 100644 --- a/website/content/index.md +++ b/website/content/index.md @@ -8,7 +8,6 @@ title = "Index" - 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 @@ -18,11 +17,12 @@ title = "Index" - Template rendering with any template engine - Define your format for the logger - Highly customizable - +- Automatic TLS via Let’s Encrypt +- Built-in graceful shutdown ## Performance -Performance +Performance ## Quick Start diff --git a/website/layouts/partials/footer.html b/website/layouts/partials/footer.html index 3082fb9ad..e091e8ec2 100644 --- a/website/layouts/partials/footer.html +++ b/website/layouts/partials/footer.html @@ -40,3 +40,4 @@ + diff --git a/website/layouts/partials/head.html b/website/layouts/partials/head.html index 87e0793dd..ef93554e4 100644 --- a/website/layouts/partials/head.html +++ b/website/layouts/partials/head.html @@ -24,7 +24,7 @@ - +