diff options
Diffstat (limited to 'vendor/github.com/labstack/echo')
45 files changed, 495 insertions, 1391 deletions
diff --git a/vendor/github.com/labstack/echo/bind.go b/vendor/github.com/labstack/echo/bind.go index f2393ea6..186bd83d 100644 --- a/vendor/github.com/labstack/echo/bind.go +++ b/vendor/github.com/labstack/echo/bind.go @@ -30,16 +30,16 @@ type ( // Bind implements the `Binder#Bind` function. func (b *DefaultBinder) Bind(i interface{}, c Context) (err error) { req := c.Request() - if req.Method == GET { - if err = b.bindData(i, c.QueryParams(), "query"); err != nil { - return NewHTTPError(http.StatusBadRequest, err.Error()) - } - return - } - ctype := req.Header.Get(HeaderContentType) if req.ContentLength == 0 { + if req.Method == GET || req.Method == DELETE { + if err = b.bindData(i, c.QueryParams(), "query"); err != nil { + return NewHTTPError(http.StatusBadRequest, err.Error()) + } + return + } return NewHTTPError(http.StatusBadRequest, "Request body can't be empty") } + ctype := req.Header.Get(HeaderContentType) switch { case strings.HasPrefix(ctype, MIMEApplicationJSON): if err = json.NewDecoder(req.Body).Decode(i); err != nil { @@ -51,7 +51,7 @@ func (b *DefaultBinder) Bind(i interface{}, c Context) (err error) { return NewHTTPError(http.StatusBadRequest, err.Error()) } } - case strings.HasPrefix(ctype, MIMEApplicationXML): + case strings.HasPrefix(ctype, MIMEApplicationXML), strings.HasPrefix(ctype, MIMETextXML): if err = xml.NewDecoder(req.Body).Decode(i); err != nil { if ute, ok := err.(*xml.UnsupportedTypeError); ok { return NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Unsupported type error: type=%v, error=%v", ute.Type, ute.Error())) @@ -142,6 +142,8 @@ func setWithProperType(valueKind reflect.Kind, val string, structField reflect.V } switch valueKind { + case reflect.Ptr: + return setWithProperType(structField.Elem().Kind(), val, structField.Elem()) case reflect.Int: return setIntField(val, 0, structField) case reflect.Int8: diff --git a/vendor/github.com/labstack/echo/context.go b/vendor/github.com/labstack/echo/context.go index 1a6ebf47..242eec26 100644 --- a/vendor/github.com/labstack/echo/context.go +++ b/vendor/github.com/labstack/echo/context.go @@ -31,6 +31,9 @@ type ( // IsTLS returns true if HTTP connection is TLS otherwise false. IsTLS() bool + // IsWebSocket returns true if HTTP connection is WebSocket otherwise false. + IsWebSocket() bool + // Scheme returns the HTTP protocol scheme, `http` or `https`. Scheme() string @@ -219,19 +222,36 @@ func (c *context) IsTLS() bool { return c.request.TLS != nil } +func (c *context) IsWebSocket() bool { + upgrade := c.request.Header.Get(HeaderUpgrade) + return upgrade == "websocket" || upgrade == "Websocket" +} + func (c *context) Scheme() string { // Can't use `r.Request.URL.Scheme` // See: https://groups.google.com/forum/#!topic/golang-nuts/pMUkBlQBDF0 if c.IsTLS() { return "https" } + if scheme := c.request.Header.Get(HeaderXForwardedProto); scheme != "" { + return scheme + } + if scheme := c.request.Header.Get(HeaderXForwardedProtocol); scheme != "" { + return scheme + } + if ssl := c.request.Header.Get(HeaderXForwardedSsl); ssl == "on" { + return "https" + } + if scheme := c.request.Header.Get(HeaderXUrlScheme); scheme != "" { + return scheme + } return "http" } func (c *context) RealIP() string { ra := c.request.RemoteAddr if ip := c.request.Header.Get(HeaderXForwardedFor); ip != "" { - ra = ip + ra = strings.Split(ip, ", ")[0] } else if ip := c.request.Header.Get(HeaderXRealIP); ip != "" { ra = ip } else { @@ -275,7 +295,7 @@ func (c *context) SetParamNames(names ...string) { } func (c *context) ParamValues() []string { - return c.pvalues + return c.pvalues[:len(c.pnames)] } func (c *context) SetParamValues(values ...string) { @@ -385,7 +405,8 @@ func (c *context) String(code int, s string) (err error) { } func (c *context) JSON(code int, i interface{}) (err error) { - if c.echo.Debug { + _, pretty := c.QueryParams()["pretty"] + if c.echo.Debug || pretty { return c.JSONPretty(code, i, " ") } b, err := json.Marshal(i) @@ -429,7 +450,8 @@ func (c *context) JSONPBlob(code int, callback string, b []byte) (err error) { } func (c *context) XML(code int, i interface{}) (err error) { - if c.echo.Debug { + _, pretty := c.QueryParams()["pretty"] + if c.echo.Debug || pretty { return c.XMLPretty(code, i, " ") } b, err := xml.Marshal(i) @@ -471,7 +493,12 @@ func (c *context) Stream(code int, contentType string, r io.Reader) (err error) return } -func (c *context) File(file string) error { +func (c *context) File(file string) (err error) { + file, err = url.QueryUnescape(file) // Issue #839 + if err != nil { + return + } + f, err := os.Open(file) if err != nil { return ErrNotFound @@ -487,11 +514,11 @@ func (c *context) File(file string) error { } defer f.Close() if fi, err = f.Stat(); err != nil { - return err + return } } http.ServeContent(c.Response(), c.Request(), fi.Name(), fi.ModTime(), f) - return nil + return } func (c *context) Attachment(file, name string) (err error) { @@ -514,7 +541,7 @@ func (c *context) NoContent(code int) error { } func (c *context) Redirect(code int, url string) error { - if code < http.StatusMultipleChoices || code > http.StatusTemporaryRedirect { + if code < 300 || code > 308 { return ErrInvalidRedirectCode } c.response.Header().Set(HeaderLocation, url) @@ -548,4 +575,8 @@ func (c *context) Reset(r *http.Request, w http.ResponseWriter) { c.query = nil c.handler = NotFoundHandler c.store = nil + c.path = "" + c.pnames = nil + // NOTE: Don't reset because it has to have length c.echo.maxParam at all times + // c.pvalues = nil } diff --git a/vendor/github.com/labstack/echo/cookbook/auto-tls/server.go b/vendor/github.com/labstack/echo/cookbook/auto-tls/server.go deleted file mode 100644 index 4a8bbdfd..00000000 --- a/vendor/github.com/labstack/echo/cookbook/auto-tls/server.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "net/http" - - "golang.org/x/crypto/acme/autocert" - - "github.com/labstack/echo" - "github.com/labstack/echo/middleware" -) - -func main() { - e := echo.New() - // e.AutoTLSManager.HostPolicy = autocert.HostWhitelist("<DOMAIN>") - // Cache certificates - e.AutoTLSManager.Cache = autocert.DirCache("/var/www/.cache") - e.Use(middleware.Recover()) - e.Use(middleware.Logger()) - e.GET("/", func(c echo.Context) error { - return c.HTML(http.StatusOK, ` - <h1>Welcome to Echo!</h1> - <h3>TLS certificates automatically installed from Let's Encrypt :)</h3> - `) - }) - e.Logger.Fatal(e.StartAutoTLS(":443")) -} diff --git a/vendor/github.com/labstack/echo/cookbook/cors/server.go b/vendor/github.com/labstack/echo/cookbook/cors/server.go deleted file mode 100644 index 0cc5c345..00000000 --- a/vendor/github.com/labstack/echo/cookbook/cors/server.go +++ /dev/null @@ -1,38 +0,0 @@ -package main - -import ( - "net/http" - - "github.com/labstack/echo" - "github.com/labstack/echo/middleware" -) - -var ( - users = []string{"Joe", "Veer", "Zion"} -) - -func getUsers(c echo.Context) error { - return c.JSON(http.StatusOK, users) -} - -func main() { - e := echo.New() - e.Use(middleware.Logger()) - e.Use(middleware.Recover()) - - // CORS default - // Allows requests from any origin wth GET, HEAD, PUT, POST or DELETE method. - // e.Use(middleware.CORS()) - - // CORS restricted - // Allows requests from any `https://labstack.com` or `https://labstack.net` origin - // wth GET, PUT, POST or DELETE method. - e.Use(middleware.CORSWithConfig(middleware.CORSConfig{ - AllowOrigins: []string{"https://labstack.com", "https://labstack.net"}, - AllowMethods: []string{echo.GET, echo.PUT, echo.POST, echo.DELETE}, - })) - - e.GET("/api/users", getUsers) - - e.Logger.Fatal(e.Start(":1323")) -} diff --git a/vendor/github.com/labstack/echo/cookbook/crud/server.go b/vendor/github.com/labstack/echo/cookbook/crud/server.go deleted file mode 100644 index fbb5c754..00000000 --- a/vendor/github.com/labstack/echo/cookbook/crud/server.go +++ /dev/null @@ -1,75 +0,0 @@ -package main - -import ( - "net/http" - "strconv" - - "github.com/labstack/echo" - "github.com/labstack/echo/middleware" -) - -type ( - user struct { - ID int `json:"id"` - Name string `json:"name"` - } -) - -var ( - users = map[int]*user{} - seq = 1 -) - -//---------- -// Handlers -//---------- - -func createUser(c echo.Context) error { - u := &user{ - ID: seq, - } - if err := c.Bind(u); err != nil { - return err - } - users[u.ID] = u - seq++ - return c.JSON(http.StatusCreated, u) -} - -func getUser(c echo.Context) error { - id, _ := strconv.Atoi(c.Param("id")) - return c.JSON(http.StatusOK, users[id]) -} - -func updateUser(c echo.Context) error { - u := new(user) - if err := c.Bind(u); err != nil { - return err - } - id, _ := strconv.Atoi(c.Param("id")) - users[id].Name = u.Name - return c.JSON(http.StatusOK, users[id]) -} - -func deleteUser(c echo.Context) error { - id, _ := strconv.Atoi(c.Param("id")) - delete(users, id) - return c.NoContent(http.StatusNoContent) -} - -func main() { - e := echo.New() - - // Middleware - e.Use(middleware.Logger()) - e.Use(middleware.Recover()) - - // Routes - e.POST("/users", createUser) - e.GET("/users/:id", getUser) - e.PUT("/users/:id", updateUser) - e.DELETE("/users/:id", deleteUser) - - // Start server - e.Logger.Fatal(e.Start(":1323")) -} diff --git a/vendor/github.com/labstack/echo/cookbook/embed-resources/server.go b/vendor/github.com/labstack/echo/cookbook/embed-resources/server.go deleted file mode 100644 index e5b0c3db..00000000 --- a/vendor/github.com/labstack/echo/cookbook/embed-resources/server.go +++ /dev/null @@ -1,21 +0,0 @@ -package main - -import ( - "net/http" - - rice "github.com/GeertJohan/go.rice" - "github.com/labstack/echo" -) - -func main() { - e := echo.New() - // the file server for rice. "app" is the folder where the files come from. - assetHandler := http.FileServer(rice.MustFindBox("app").HTTPBox()) - // serves the index.html from rice - e.GET("/", echo.WrapHandler(assetHandler)) - - // servers other static files - e.GET("/static/*", echo.WrapHandler(http.StripPrefix("/static/", assetHandler))) - - e.Logger.Fatal(e.Start(":1323")) -} diff --git a/vendor/github.com/labstack/echo/cookbook/file-upload/multiple/server.go b/vendor/github.com/labstack/echo/cookbook/file-upload/multiple/server.go deleted file mode 100644 index cd0f54d3..00000000 --- a/vendor/github.com/labstack/echo/cookbook/file-upload/multiple/server.go +++ /dev/null @@ -1,65 +0,0 @@ -package main - -import ( - "fmt" - "io" - "os" - - "net/http" - - "github.com/labstack/echo" - "github.com/labstack/echo/middleware" -) - -func upload(c echo.Context) error { - // Read form fields - name := c.FormValue("name") - email := c.FormValue("email") - - //------------ - // Read files - //------------ - - // Multipart form - form, err := c.MultipartForm() - if err != nil { - return err - } - files := form.File["files"] - - for _, file := range files { - // Source - src, err := file.Open() - if err != nil { - return err - } - defer src.Close() - - // Destination - dst, err := os.Create(file.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, fmt.Sprintf("<p>Uploaded successfully %d files with fields name=%s and email=%s.</p>", len(files), name, email)) -} - -func main() { - e := echo.New() - - e.Use(middleware.Logger()) - e.Use(middleware.Recover()) - - e.Static("/", "public") - e.POST("/upload", upload) - - e.Logger.Fatal(e.Start(":1323")) -} diff --git a/vendor/github.com/labstack/echo/cookbook/file-upload/single/server.go b/vendor/github.com/labstack/echo/cookbook/file-upload/single/server.go deleted file mode 100644 index 1b84f220..00000000 --- a/vendor/github.com/labstack/echo/cookbook/file-upload/single/server.go +++ /dev/null @@ -1,59 +0,0 @@ -package main - -import ( - "fmt" - "io" - "os" - - "net/http" - - "github.com/labstack/echo" - "github.com/labstack/echo/middleware" -) - -func upload(c echo.Context) error { - // Read form fields - name := c.FormValue("name") - email := c.FormValue("email") - - //----------- - // Read file - //----------- - - // Source - file, err := c.FormFile("file") - if err != nil { - return err - } - src, err := file.Open() - if err != nil { - return err - } - defer src.Close() - - // Destination - dst, err := os.Create(file.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, fmt.Sprintf("<p>File %s uploaded successfully with fields name=%s and email=%s.</p>", file.Filename, name, email)) -} - -func main() { - e := echo.New() - - e.Use(middleware.Logger()) - e.Use(middleware.Recover()) - - e.Static("/", "public") - e.POST("/upload", upload) - - e.Logger.Fatal(e.Start(":1323")) -} diff --git a/vendor/github.com/labstack/echo/cookbook/google-app-engine/app-engine.go b/vendor/github.com/labstack/echo/cookbook/google-app-engine/app-engine.go deleted file mode 100644 index 0c1db087..00000000 --- a/vendor/github.com/labstack/echo/cookbook/google-app-engine/app-engine.go +++ /dev/null @@ -1,17 +0,0 @@ -// +build appengine - -package main - -import ( - "net/http" - - "github.com/labstack/echo" -) - -func createMux() *echo.Echo { - e := echo.New() - // note: we don't need to provide the middleware or static handlers, that's taken care of by the platform - // app engine has it's own "main" wrapper - we just need to hook echo into the default handler - http.Handle("/", e) - return e -} diff --git a/vendor/github.com/labstack/echo/cookbook/google-app-engine/app-managed.go b/vendor/github.com/labstack/echo/cookbook/google-app-engine/app-managed.go deleted file mode 100644 index 7b8eacf8..00000000 --- a/vendor/github.com/labstack/echo/cookbook/google-app-engine/app-managed.go +++ /dev/null @@ -1,25 +0,0 @@ -// +build appenginevm - -package main - -import ( - "net/http" - - "github.com/labstack/echo" - "google.golang.org/appengine" -) - -func createMux() *echo.Echo { - e := echo.New() - // note: we don't need to provide the middleware or static handlers - // for the appengine vm version - that's taken care of by the platform - return e -} - -func main() { - // the appengine package provides a convenient method to handle the health-check requests - // and also run the app on the correct port. We just need to add Echo to the default handler - e := echo.New(":8080") - http.Handle("/", e) - appengine.Main() -} diff --git a/vendor/github.com/labstack/echo/cookbook/google-app-engine/app-standalone.go b/vendor/github.com/labstack/echo/cookbook/google-app-engine/app-standalone.go deleted file mode 100644 index c3b44dc0..00000000 --- a/vendor/github.com/labstack/echo/cookbook/google-app-engine/app-standalone.go +++ /dev/null @@ -1,24 +0,0 @@ -// +build !appengine,!appenginevm - -package main - -import ( - "github.com/labstack/echo" - "github.com/labstack/echo/middleware" -) - -func createMux() *echo.Echo { - e := echo.New() - - e.Use(middleware.Recover()) - e.Use(middleware.Logger()) - e.Use(middleware.Gzip()) - - e.Static("/", "public") - - return e -} - -func main() { - e.Logger.Fatal(e.Start(":8080")) -} diff --git a/vendor/github.com/labstack/echo/cookbook/google-app-engine/app.go b/vendor/github.com/labstack/echo/cookbook/google-app-engine/app.go deleted file mode 100644 index 8d4d97a2..00000000 --- a/vendor/github.com/labstack/echo/cookbook/google-app-engine/app.go +++ /dev/null @@ -1,4 +0,0 @@ -package main - -// reference our echo instance and create it early -var e = createMux() diff --git a/vendor/github.com/labstack/echo/cookbook/google-app-engine/users.go b/vendor/github.com/labstack/echo/cookbook/google-app-engine/users.go deleted file mode 100644 index 19533e51..00000000 --- a/vendor/github.com/labstack/echo/cookbook/google-app-engine/users.go +++ /dev/null @@ -1,54 +0,0 @@ -package main - -import ( - "net/http" - - "github.com/labstack/echo" - "github.com/labstack/echo/middleware" -) - -type ( - user struct { - ID string `json:"id"` - Name string `json:"name"` - } -) - -var ( - users map[string]user -) - -func init() { - users = map[string]user{ - "1": user{ - ID: "1", - Name: "Wreck-It Ralph", - }, - } - - // hook into the echo instance to create an endpoint group - // and add specific middleware to it plus handlers - g := e.Group("/users") - g.Use(middleware.CORS()) - - g.POST("", createUser) - g.GET("", getUsers) - g.GET("/:id", getUser) -} - -func createUser(c echo.Context) error { - u := new(user) - if err := c.Bind(u); err != nil { - return err - } - users[u.ID] = *u - return c.JSON(http.StatusCreated, u) -} - -func getUsers(c echo.Context) error { - return c.JSON(http.StatusOK, users) -} - -func getUser(c echo.Context) error { - return c.JSON(http.StatusOK, users[c.Param("id")]) -} diff --git a/vendor/github.com/labstack/echo/cookbook/google-app-engine/welcome.go b/vendor/github.com/labstack/echo/cookbook/google-app-engine/welcome.go deleted file mode 100644 index 2639b209..00000000 --- a/vendor/github.com/labstack/echo/cookbook/google-app-engine/welcome.go +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "html/template" - "io" - "net/http" - - "github.com/labstack/echo" -) - -type ( - Template struct { - templates *template.Template - } -) - -func init() { - t := &Template{ - templates: template.Must(template.ParseFiles("templates/welcome.html")), - } - e.Renderer = t - e.GET("/welcome", welcome) -} - -func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error { - return t.templates.ExecuteTemplate(w, name, data) -} - -func welcome(c echo.Context) error { - return c.Render(http.StatusOK, "welcome", "Joe") -} diff --git a/vendor/github.com/labstack/echo/cookbook/graceful-shutdown/grace/server.go b/vendor/github.com/labstack/echo/cookbook/graceful-shutdown/grace/server.go deleted file mode 100644 index 1f9937b0..00000000 --- a/vendor/github.com/labstack/echo/cookbook/graceful-shutdown/grace/server.go +++ /dev/null @@ -1,20 +0,0 @@ -package main - -import ( - "net/http" - - "github.com/facebookgo/grace/gracehttp" - "github.com/labstack/echo" -) - -func main() { - // Setup - e := echo.New() - e.GET("/", func(c echo.Context) error { - return c.String(http.StatusOK, "Six sick bricks tick") - }) - e.Server.Addr = ":1323" - - // Serve it like a boss - e.Logger.Fatal(gracehttp.Serve(e.Server)) -} diff --git a/vendor/github.com/labstack/echo/cookbook/graceful-shutdown/graceful/server.go b/vendor/github.com/labstack/echo/cookbook/graceful-shutdown/graceful/server.go deleted file mode 100644 index 39e7b634..00000000 --- a/vendor/github.com/labstack/echo/cookbook/graceful-shutdown/graceful/server.go +++ /dev/null @@ -1,21 +0,0 @@ -package main - -import ( - "net/http" - "time" - - "github.com/labstack/echo" - "github.com/tylerb/graceful" -) - -func main() { - // Setup - e := echo.New() - e.GET("/", func(c echo.Context) error { - return c.String(http.StatusOK, "Sue sews rose on slow joe crows nose") - }) - e.Server.Addr = ":1323" - - // Serve it like a boss - graceful.ListenAndServe(e.Server, 5*time.Second) -} diff --git a/vendor/github.com/labstack/echo/cookbook/hello-world/server.go b/vendor/github.com/labstack/echo/cookbook/hello-world/server.go deleted file mode 100644 index 06e0718b..00000000 --- a/vendor/github.com/labstack/echo/cookbook/hello-world/server.go +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "net/http" - - "github.com/labstack/echo" - "github.com/labstack/echo/middleware" -) - -func main() { - // Echo instance - e := echo.New() - - // Middleware - e.Use(middleware.Logger()) - e.Use(middleware.Recover()) - - // Route => handler - e.GET("/", func(c echo.Context) error { - return c.String(http.StatusOK, "Hello, World!\n") - }) - - // Start server - e.Logger.Fatal(e.Start(":1323")) -} diff --git a/vendor/github.com/labstack/echo/cookbook/http2/server.go b/vendor/github.com/labstack/echo/cookbook/http2/server.go deleted file mode 100644 index 8db989c4..00000000 --- a/vendor/github.com/labstack/echo/cookbook/http2/server.go +++ /dev/null @@ -1,42 +0,0 @@ -package main - -import ( - "fmt" - "net/http" - "time" - - "github.com/labstack/echo" -) - -func request(c echo.Context) error { - req := c.Request() - format := "<pre><strong>Request Information</strong>\n\n<code>Protocol: %s\nHost: %s\nRemote Address: %s\nMethod: %s\nPath: %s\n</code></pre>" - return c.HTML(http.StatusOK, fmt.Sprintf(format, req.Proto, req.Host, req.RemoteAddr, req.Method, req.URL.Path)) -} - -func stream(c echo.Context) error { - res := c.Response() - gone := res.CloseNotify() - res.Header().Set(echo.HeaderContentType, echo.MIMETextHTMLCharsetUTF8) - res.WriteHeader(http.StatusOK) - ticker := time.NewTicker(1 * time.Second) - defer ticker.Stop() - - fmt.Fprint(res, "<pre><strong>Clock Stream</strong>\n\n<code>") - for { - fmt.Fprintf(res, "%v\n", time.Now()) - res.Flush() - select { - case <-ticker.C: - case <-gone: - break - } - } -} - -func main() { - e := echo.New() - e.GET("/request", request) - e.GET("/stream", stream) - e.Logger.Fatal(e.StartTLS(":1323", "cert.pem", "key.pem")) -} diff --git a/vendor/github.com/labstack/echo/cookbook/jsonp/server.go b/vendor/github.com/labstack/echo/cookbook/jsonp/server.go deleted file mode 100644 index ba46bab0..00000000 --- a/vendor/github.com/labstack/echo/cookbook/jsonp/server.go +++ /dev/null @@ -1,35 +0,0 @@ -package main - -import ( - "math/rand" - "net/http" - "time" - - "github.com/labstack/echo" - "github.com/labstack/echo/middleware" -) - -func main() { - e := echo.New() - e.Use(middleware.Logger()) - e.Use(middleware.Recover()) - - e.Static("/", "public") - - // JSONP - e.GET("/jsonp", func(c echo.Context) error { - callback := c.QueryParam("callback") - var content struct { - Response string `json:"response"` - Timestamp time.Time `json:"timestamp"` - Random int `json:"random"` - } - content.Response = "Sent via JSONP" - content.Timestamp = time.Now().UTC() - content.Random = rand.Intn(1000) - return c.JSONP(http.StatusOK, callback, &content) - }) - - // Start server - e.Logger.Fatal(e.Start(":1323")) -} diff --git a/vendor/github.com/labstack/echo/cookbook/jwt/custom-claims/server.go b/vendor/github.com/labstack/echo/cookbook/jwt/custom-claims/server.go deleted file mode 100644 index b3a13205..00000000 --- a/vendor/github.com/labstack/echo/cookbook/jwt/custom-claims/server.go +++ /dev/null @@ -1,86 +0,0 @@ -package main - -import ( - "net/http" - "time" - - jwt "github.com/dgrijalva/jwt-go" - "github.com/labstack/echo" - "github.com/labstack/echo/middleware" -) - -// jwtCustomClaims are custom claims extending default ones. -type jwtCustomClaims struct { - Name string `json:"name"` - Admin bool `json:"admin"` - jwt.StandardClaims -} - -func login(c echo.Context) error { - username := c.FormValue("username") - password := c.FormValue("password") - - if username == "jon" && password == "shhh!" { - - // Set custom claims - claims := &jwtCustomClaims{ - "Jon Snow", - true, - jwt.StandardClaims{ - ExpiresAt: time.Now().Add(time.Hour * 72).Unix(), - }, - } - - // Create token with claims - token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) - - // Generate encoded token and send it as response. - t, err := token.SignedString([]byte("secret")) - if err != nil { - return err - } - return c.JSON(http.StatusOK, echo.Map{ - "token": t, - }) - } - - return echo.ErrUnauthorized -} - -func accessible(c echo.Context) error { - return c.String(http.StatusOK, "Accessible") -} - -func restricted(c echo.Context) error { - user := c.Get("user").(*jwt.Token) - claims := user.Claims.(*jwtCustomClaims) - name := claims.Name - return c.String(http.StatusOK, "Welcome "+name+"!") -} - -func main() { - e := echo.New() - - // Middleware - e.Use(middleware.Logger()) - e.Use(middleware.Recover()) - - // Login route - e.POST("/login", login) - - // Unauthenticated route - e.GET("/", accessible) - - // Restricted group - r := e.Group("/restricted") - - // Configure middleware with the custom claims type - config := middleware.JWTConfig{ - Claims: &jwtCustomClaims{}, - SigningKey: []byte("secret"), - } - r.Use(middleware.JWTWithConfig(config)) - r.GET("", restricted) - - e.Logger.Fatal(e.Start(":1323")) -} diff --git a/vendor/github.com/labstack/echo/cookbook/jwt/map-claims/server.go b/vendor/github.com/labstack/echo/cookbook/jwt/map-claims/server.go deleted file mode 100644 index 678be490..00000000 --- a/vendor/github.com/labstack/echo/cookbook/jwt/map-claims/server.go +++ /dev/null @@ -1,69 +0,0 @@ -package main - -import ( - "net/http" - "time" - - jwt "github.com/dgrijalva/jwt-go" - "github.com/labstack/echo" - "github.com/labstack/echo/middleware" -) - -func login(c echo.Context) error { - username := c.FormValue("username") - password := c.FormValue("password") - - if username == "jon" && password == "shhh!" { - // Create token - token := jwt.New(jwt.SigningMethodHS256) - - // Set claims - claims := token.Claims.(jwt.MapClaims) - claims["name"] = "Jon Snow" - claims["admin"] = true - claims["exp"] = time.Now().Add(time.Hour * 72).Unix() - - // Generate encoded token and send it as response. - t, err := token.SignedString([]byte("secret")) - if err != nil { - return err - } - return c.JSON(http.StatusOK, map[string]string{ - "token": t, - }) - } - - return echo.ErrUnauthorized -} - -func accessible(c echo.Context) error { - return c.String(http.StatusOK, "Accessible") -} - -func restricted(c echo.Context) error { - user := c.Get("user").(*jwt.Token) - claims := user.Claims.(jwt.MapClaims) - name := claims["name"].(string) - return c.String(http.StatusOK, "Welcome "+name+"!") -} - -func main() { - e := echo.New() - - // Middleware - e.Use(middleware.Logger()) - e.Use(middleware.Recover()) - - // Login route - e.POST("/login", login) - - // Unauthenticated route - e.GET("/", accessible) - - // Restricted group - r := e.Group("/restricted") - r.Use(middleware.JWT([]byte("secret"))) - r.GET("", restricted) - - e.Logger.Fatal(e.Start(":1323")) -} diff --git a/vendor/github.com/labstack/echo/cookbook/middleware/server.go b/vendor/github.com/labstack/echo/cookbook/middleware/server.go deleted file mode 100644 index 2f21df50..00000000 --- a/vendor/github.com/labstack/echo/cookbook/middleware/server.go +++ /dev/null @@ -1,82 +0,0 @@ -package main - -import ( - "net/http" - "strconv" - "sync" - "time" - - "github.com/labstack/echo" -) - -type ( - Stats struct { - Uptime time.Time `json:"uptime"` - RequestCount uint64 `json:"requestCount"` - Statuses map[string]int `json:"statuses"` - mutex sync.RWMutex - } -) - -func NewStats() *Stats { - return &Stats{ - Uptime: time.Now(), - Statuses: make(map[string]int), - } -} - -// Process is the middleware function. -func (s *Stats) Process(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { - if err := next(c); err != nil { - c.Error(err) - } - s.mutex.Lock() - defer s.mutex.Unlock() - s.RequestCount++ - status := strconv.Itoa(c.Response().Status) - s.Statuses[status]++ - return nil - } -} - -// Handle is the endpoint to get stats. -func (s *Stats) Handle(c echo.Context) error { - s.mutex.RLock() - defer s.mutex.RUnlock() - return c.JSON(http.StatusOK, s) -} - -// ServerHeader middleware adds a `Server` header to the response. -func ServerHeader(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { - c.Response().Header().Set(echo.HeaderServer, "Echo/3.0") - return next(c) - } -} - -func main() { - e := echo.New() - - // Debug mode - e.Debug = true - - //------------------- - // Custom middleware - //------------------- - // Stats - s := NewStats() - e.Use(s.Process) - e.GET("/stats", s.Handle) // Endpoint to get stats - - // Server header - e.Use(ServerHeader) - - // Handler - e.GET("/", func(c echo.Context) error { - return c.String(http.StatusOK, "Hello, World!") - }) - - // Start server - e.Logger.Fatal(e.Start(":1323")) -} diff --git a/vendor/github.com/labstack/echo/cookbook/streaming-response/server.go b/vendor/github.com/labstack/echo/cookbook/streaming-response/server.go deleted file mode 100644 index a3a679ef..00000000 --- a/vendor/github.com/labstack/echo/cookbook/streaming-response/server.go +++ /dev/null @@ -1,45 +0,0 @@ -package main - -import ( - "net/http" - "time" - - "encoding/json" - - "github.com/labstack/echo" -) - -type ( - Geolocation struct { - Altitude float64 - Latitude float64 - Longitude float64 - } -) - -var ( - locations = []Geolocation{ - {-97, 37.819929, -122.478255}, - {1899, 39.096849, -120.032351}, - {2619, 37.865101, -119.538329}, - {42, 33.812092, -117.918974}, - {15, 37.77493, -122.419416}, - } -) - -func main() { - e := echo.New() - e.GET("/", func(c echo.Context) error { - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSON) - c.Response().WriteHeader(http.StatusOK) - for _, l := range locations { - if err := json.NewEncoder(c.Response()).Encode(l); err != nil { - return err - } - c.Response().Flush() - time.Sleep(1 * time.Second) - } - return nil - }) - e.Logger.Fatal(e.Start(":1323")) -} diff --git a/vendor/github.com/labstack/echo/cookbook/subdomains/server.go b/vendor/github.com/labstack/echo/cookbook/subdomains/server.go deleted file mode 100644 index ef4f65f9..00000000 --- a/vendor/github.com/labstack/echo/cookbook/subdomains/server.go +++ /dev/null @@ -1,78 +0,0 @@ -package main - -import ( - "net/http" - - "github.com/labstack/echo" - "github.com/labstack/echo/middleware" -) - -type ( - Host struct { - Echo *echo.Echo - } -) - -func main() { - // Hosts - hosts := make(map[string]*Host) - - //----- - // API - //----- - - api := echo.New() - api.Use(middleware.Logger()) - api.Use(middleware.Recover()) - - hosts["api.localhost:1323"] = &Host{api} - - api.GET("/", func(c echo.Context) error { - return c.String(http.StatusOK, "API") - }) - - //------ - // Blog - //------ - - blog := echo.New() - blog.Use(middleware.Logger()) - blog.Use(middleware.Recover()) - - hosts["blog.localhost:1323"] = &Host{blog} - - blog.GET("/", func(c echo.Context) error { - return c.String(http.StatusOK, "Blog") - }) - - //--------- - // Website - //--------- - - site := echo.New() - site.Use(middleware.Logger()) - site.Use(middleware.Recover()) - - hosts["localhost:1323"] = &Host{site} - - site.GET("/", func(c echo.Context) error { - return c.String(http.StatusOK, "Website") - }) - - // Server - e := echo.New() - e.Any("/*", func(c echo.Context) (err error) { - req := c.Request() - res := c.Response() - host := hosts[req.Host] - - if host == nil { - err = echo.ErrNotFound - } else { - host.Echo.ServeHTTP(res, req) - } - - return - }) - e.Logger.Fatal(e.Start(":1323")) -} diff --git a/vendor/github.com/labstack/echo/cookbook/twitter/handler/handler.go b/vendor/github.com/labstack/echo/cookbook/twitter/handler/handler.go deleted file mode 100644 index 263c5e21..00000000 --- a/vendor/github.com/labstack/echo/cookbook/twitter/handler/handler.go +++ /dev/null @@ -1,14 +0,0 @@ -package handler - -import mgo "gopkg.in/mgo.v2" - -type ( - Handler struct { - DB *mgo.Session - } -) - -const ( - // Key (Should come from somewhere else). - Key = "secret" -) diff --git a/vendor/github.com/labstack/echo/cookbook/twitter/handler/post.go b/vendor/github.com/labstack/echo/cookbook/twitter/handler/post.go deleted file mode 100644 index b1428a30..00000000 --- a/vendor/github.com/labstack/echo/cookbook/twitter/handler/post.go +++ /dev/null @@ -1,73 +0,0 @@ -package handler - -import ( - "net/http" - "strconv" - - "github.com/labstack/echo" - "github.com/labstack/echo/cookbook/twitter/model" - mgo "gopkg.in/mgo.v2" - "gopkg.in/mgo.v2/bson" -) - -func (h *Handler) CreatePost(c echo.Context) (err error) { - u := &model.User{ - ID: bson.ObjectIdHex(userIDFromToken(c)), - } - p := &model.Post{ - ID: bson.NewObjectId(), - From: u.ID.Hex(), - } - if err = c.Bind(p); err != nil { - return - } - - // Validation - if p.To == "" || p.Message == "" { - return &echo.HTTPError{Code: http.StatusBadRequest, Message: "invalid to or message fields"} - } - - // Find user from database - db := h.DB.Clone() - defer db.Close() - if err = db.DB("twitter").C("users").FindId(u.ID).One(u); err != nil { - if err == mgo.ErrNotFound { - return echo.ErrNotFound - } - return - } - - // Save post in database - if err = db.DB("twitter").C("posts").Insert(p); err != nil { - return - } - return c.JSON(http.StatusCreated, p) -} - -func (h *Handler) FetchPost(c echo.Context) (err error) { - userID := userIDFromToken(c) - page, _ := strconv.Atoi(c.QueryParam("page")) - limit, _ := strconv.Atoi(c.QueryParam("limit")) - - // Defaults - if page == 0 { - page = 1 - } - if limit == 0 { - limit = 100 - } - - // Retrieve posts from database - posts := []*model.Post{} - db := h.DB.Clone() - if err = db.DB("twitter").C("posts"). - Find(bson.M{"to": userID}). - Skip((page - 1) * limit). - Limit(limit). - All(&posts); err != nil { - return - } - defer db.Close() - - return c.JSON(http.StatusOK, posts) -} diff --git a/vendor/github.com/labstack/echo/cookbook/twitter/handler/user.go b/vendor/github.com/labstack/echo/cookbook/twitter/handler/user.go deleted file mode 100644 index a34d2f4e..00000000 --- a/vendor/github.com/labstack/echo/cookbook/twitter/handler/user.go +++ /dev/null @@ -1,97 +0,0 @@ -package handler - -import ( - "net/http" - "time" - - jwt "github.com/dgrijalva/jwt-go" - "github.com/labstack/echo" - "github.com/labstack/echo/cookbook/twitter/model" - mgo "gopkg.in/mgo.v2" - "gopkg.in/mgo.v2/bson" -) - -func (h *Handler) Signup(c echo.Context) (err error) { - // Bind - u := &model.User{ID: bson.NewObjectId()} - if err = c.Bind(u); err != nil { - return - } - - // Validate - if u.Email == "" || u.Password == "" { - return &echo.HTTPError{Code: http.StatusBadRequest, Message: "invalid email or password"} - } - - // Save user - db := h.DB.Clone() - defer db.Close() - if err = db.DB("twitter").C("users").Insert(u); err != nil { - return - } - - return c.JSON(http.StatusCreated, u) -} - -func (h *Handler) Login(c echo.Context) (err error) { - // Bind - u := new(model.User) - if err = c.Bind(u); err != nil { - return - } - - // Find user - db := h.DB.Clone() - defer db.Close() - if err = db.DB("twitter").C("users"). - Find(bson.M{"email": u.Email, "password": u.Password}).One(u); err != nil { - if err == mgo.ErrNotFound { - return &echo.HTTPError{Code: http.StatusUnauthorized, Message: "invalid email or password"} - } - return - } - - //----- - // JWT - //----- - - // Create token - token := jwt.New(jwt.SigningMethodHS256) - - // Set claims - claims := token.Claims.(jwt.MapClaims) - claims["id"] = u.ID - claims["exp"] = time.Now().Add(time.Hour * 72).Unix() - - // Generate encoded token and send it as response - u.Token, err = token.SignedString([]byte(Key)) - if err != nil { - return err - } - - u.Password = "" // Don't send password - return c.JSON(http.StatusOK, u) -} - -func (h *Handler) Follow(c echo.Context) (err error) { - userID := userIDFromToken(c) - id := c.Param("id") - - // Add a follower to user - db := h.DB.Clone() - defer db.Close() - if err = db.DB("twitter").C("users"). - UpdateId(bson.ObjectIdHex(id), bson.M{"$addToSet": bson.M{"followers": userID}}); err != nil { - if err == mgo.ErrNotFound { - return echo.ErrNotFound - } - } - - return -} - -func userIDFromToken(c echo.Context) string { - user := c.Get("user").(*jwt.Token) - claims := user.Claims.(jwt.MapClaims) - return claims["id"].(string) -} diff --git a/vendor/github.com/labstack/echo/cookbook/twitter/model/post.go b/vendor/github.com/labstack/echo/cookbook/twitter/model/post.go deleted file mode 100644 index 7344296e..00000000 --- a/vendor/github.com/labstack/echo/cookbook/twitter/model/post.go +++ /dev/null @@ -1,12 +0,0 @@ -package model - -import "gopkg.in/mgo.v2/bson" - -type ( - Post struct { - ID bson.ObjectId `json:"id" bson:"_id,omitempty"` - To string `json:"to" bson:"to"` - From string `json:"from" bson:"from"` - Message string `json:"message" bson:"message"` - } -) diff --git a/vendor/github.com/labstack/echo/cookbook/twitter/model/user.go b/vendor/github.com/labstack/echo/cookbook/twitter/model/user.go deleted file mode 100644 index e063c89b..00000000 --- a/vendor/github.com/labstack/echo/cookbook/twitter/model/user.go +++ /dev/null @@ -1,13 +0,0 @@ -package model - -import "gopkg.in/mgo.v2/bson" - -type ( - User struct { - ID bson.ObjectId `json:"id" bson:"_id,omitempty"` - Email string `json:"email" bson:"email"` - Password string `json:"password,omitempty" bson:"password"` - Token string `json:"token,omitempty" bson:"-"` - Followers []string `json:"followers,omitempty" bson:"followers,omitempty"` - } -) diff --git a/vendor/github.com/labstack/echo/cookbook/twitter/server.go b/vendor/github.com/labstack/echo/cookbook/twitter/server.go deleted file mode 100644 index 22db7aa0..00000000 --- a/vendor/github.com/labstack/echo/cookbook/twitter/server.go +++ /dev/null @@ -1,52 +0,0 @@ -package main - -import ( - "github.com/labstack/echo" - "github.com/labstack/echo/cookbook/twitter/handler" - "github.com/labstack/echo/middleware" - "github.com/labstack/gommon/log" - mgo "gopkg.in/mgo.v2" -) - -func main() { - e := echo.New() - e.Logger.SetLevel(log.ERROR) - e.Use(middleware.Logger()) - e.Use(middleware.JWTWithConfig(middleware.JWTConfig{ - SigningKey: []byte(handler.Key), - Skipper: func(c echo.Context) bool { - // Skip authentication for and signup login requests - if c.Path() == "/login" || c.Path() == "/signup" { - return true - } - return false - }, - })) - - // Database connection - db, err := mgo.Dial("localhost") - if err != nil { - e.Logger.Fatal(err) - } - - // Create indices - if err = db.Copy().DB("twitter").C("users").EnsureIndex(mgo.Index{ - Key: []string{"email"}, - Unique: true, - }); err != nil { - log.Fatal(err) - } - - // Initialize handler - h := &handler.Handler{DB: db} - - // Routes - e.POST("/signup", h.Signup) - e.POST("/login", h.Login) - e.POST("/follow/:id", h.Follow) - e.POST("/posts", h.CreatePost) - e.GET("/feed", h.FetchPost) - - // Start server - e.Logger.Fatal(e.Start(":1323")) -} diff --git a/vendor/github.com/labstack/echo/cookbook/websocket/gorilla/server.go b/vendor/github.com/labstack/echo/cookbook/websocket/gorilla/server.go deleted file mode 100644 index e9d52dbb..00000000 --- a/vendor/github.com/labstack/echo/cookbook/websocket/gorilla/server.go +++ /dev/null @@ -1,47 +0,0 @@ -package main - -import ( - "fmt" - "log" - - "github.com/labstack/echo" - - "github.com/gorilla/websocket" - "github.com/labstack/echo/middleware" -) - -var ( - upgrader = websocket.Upgrader{} -) - -func hello(c echo.Context) error { - ws, err := upgrader.Upgrade(c.Response(), c.Request(), nil) - if err != nil { - return err - } - defer ws.Close() - - for { - // Write - err := ws.WriteMessage(websocket.TextMessage, []byte("Hello, Client!")) - if err != nil { - log.Fatal(err) - } - - // Read - _, msg, err := ws.ReadMessage() - if err != nil { - log.Fatal(err) - } - fmt.Printf("%s\n", msg) - } -} - -func main() { - e := echo.New() - e.Use(middleware.Logger()) - e.Use(middleware.Recover()) - e.Static("/", "../public") - e.GET("/ws", hello) - e.Logger.Fatal(e.Start(":1323")) -} diff --git a/vendor/github.com/labstack/echo/cookbook/websocket/net/server.go b/vendor/github.com/labstack/echo/cookbook/websocket/net/server.go deleted file mode 100644 index aa746030..00000000 --- a/vendor/github.com/labstack/echo/cookbook/websocket/net/server.go +++ /dev/null @@ -1,41 +0,0 @@ -package main - -import ( - "fmt" - "log" - - "github.com/labstack/echo" - "github.com/labstack/echo/middleware" - "golang.org/x/net/websocket" -) - -func hello(c echo.Context) error { - websocket.Handler(func(ws *websocket.Conn) { - defer ws.Close() - for { - // Write - err := websocket.Message.Send(ws, "Hello, Client!") - if err != nil { - log.Fatal(err) - } - - // Read - msg := "" - err = websocket.Message.Receive(ws, &msg) - if err != nil { - log.Fatal(err) - } - fmt.Printf("%s\n", msg) - } - }).ServeHTTP(c.Response(), c.Request()) - return nil -} - -func main() { - e := echo.New() - e.Use(middleware.Logger()) - e.Use(middleware.Recover()) - e.Static("/", "../public") - e.GET("/ws", hello) - e.Logger.Fatal(e.Start(":1323")) -} diff --git a/vendor/github.com/labstack/echo/echo.go b/vendor/github.com/labstack/echo/echo.go index f0c1b72e..baa92fde 100644 --- a/vendor/github.com/labstack/echo/echo.go +++ b/vendor/github.com/labstack/echo/echo.go @@ -42,10 +42,11 @@ import ( "errors" "fmt" "io" - slog "log" + stdLog "log" "net" "net/http" "path" + "path/filepath" "reflect" "runtime" "sync" @@ -59,7 +60,7 @@ import ( type ( // Echo is the top-level framework instance. Echo struct { - stdLogger *slog.Logger + stdLogger *stdLog.Logger colorer *color.Color premiddleware []MiddlewareFunc middleware []MiddlewareFunc @@ -73,20 +74,21 @@ type ( TLSListener net.Listener DisableHTTP2 bool Debug bool + HideBanner bool HTTPErrorHandler HTTPErrorHandler Binder Binder Validator Validator Renderer Renderer AutoTLSManager autocert.Manager - Mutex sync.RWMutex - Logger Logger + // Mutex sync.RWMutex + Logger Logger } // Route contains a handler and information for matching against requests. Route struct { - Method string - Path string - Handler string + Method string `json:"method"` + Path string `json:"path"` + Handler string `json:"handler"` } // HTTPError represents an error that occurred while handling a request. @@ -144,6 +146,8 @@ const ( MIMEApplicationJavaScriptCharsetUTF8 = MIMEApplicationJavaScript + "; " + charsetUTF8 MIMEApplicationXML = "application/xml" MIMEApplicationXMLCharsetUTF8 = MIMEApplicationXML + "; " + charsetUTF8 + MIMETextXML = "text/xml" + MIMETextXMLCharsetUTF8 = MIMETextXML + "; " + charsetUTF8 MIMEApplicationForm = "application/x-www-form-urlencoded" MIMEApplicationProtobuf = "application/protobuf" MIMEApplicationMsgpack = "application/msgpack" @@ -161,27 +165,34 @@ const ( // Headers const ( - HeaderAcceptEncoding = "Accept-Encoding" - HeaderAllow = "Allow" - HeaderAuthorization = "Authorization" - HeaderContentDisposition = "Content-Disposition" - HeaderContentEncoding = "Content-Encoding" - HeaderContentLength = "Content-Length" - HeaderContentType = "Content-Type" - HeaderCookie = "Cookie" - HeaderSetCookie = "Set-Cookie" - HeaderIfModifiedSince = "If-Modified-Since" - HeaderLastModified = "Last-Modified" - HeaderLocation = "Location" - HeaderUpgrade = "Upgrade" - HeaderVary = "Vary" - HeaderWWWAuthenticate = "WWW-Authenticate" - HeaderXForwardedProto = "X-Forwarded-Proto" - HeaderXHTTPMethodOverride = "X-HTTP-Method-Override" - HeaderXForwardedFor = "X-Forwarded-For" - HeaderXRealIP = "X-Real-IP" - HeaderServer = "Server" - HeaderOrigin = "Origin" + HeaderAccept = "Accept" + HeaderAcceptEncoding = "Accept-Encoding" + HeaderAllow = "Allow" + HeaderAuthorization = "Authorization" + HeaderContentDisposition = "Content-Disposition" + HeaderContentEncoding = "Content-Encoding" + HeaderContentLength = "Content-Length" + HeaderContentType = "Content-Type" + HeaderCookie = "Cookie" + HeaderSetCookie = "Set-Cookie" + HeaderIfModifiedSince = "If-Modified-Since" + HeaderLastModified = "Last-Modified" + HeaderLocation = "Location" + HeaderUpgrade = "Upgrade" + HeaderVary = "Vary" + HeaderWWWAuthenticate = "WWW-Authenticate" + HeaderXForwardedFor = "X-Forwarded-For" + HeaderXForwardedProto = "X-Forwarded-Proto" + HeaderXForwardedProtocol = "X-Forwarded-Protocol" + HeaderXForwardedSsl = "X-Forwarded-Ssl" + HeaderXUrlScheme = "X-Url-Scheme" + HeaderXHTTPMethodOverride = "X-HTTP-Method-Override" + HeaderXRealIP = "X-Real-IP" + HeaderXRequestID = "X-Request-ID" + HeaderServer = "Server" + HeaderOrigin = "Origin" + + // Access control HeaderAccessControlRequestMethod = "Access-Control-Request-Method" HeaderAccessControlRequestHeaders = "Access-Control-Request-Headers" HeaderAccessControlAllowOrigin = "Access-Control-Allow-Origin" @@ -200,6 +211,22 @@ const ( HeaderXCSRFToken = "X-CSRF-Token" ) +const ( + version = "3.1.0" + website = "https://echo.labstack.com" + // http://patorjk.com/software/taag/#p=display&f=Small%20Slant&t=Echo + banner = ` + ____ __ + / __/___/ / ___ + / _// __/ _ \/ _ \ +/___/\__/_//_/\___/ %s +High performance, minimalist Go web framework +%s +____________________________________O/_______ + O\ +` +) + var ( methods = [...]string{ CONNECT, @@ -219,6 +246,7 @@ var ( ErrUnsupportedMediaType = NewHTTPError(http.StatusUnsupportedMediaType) ErrNotFound = NewHTTPError(http.StatusNotFound) ErrUnauthorized = NewHTTPError(http.StatusUnauthorized) + ErrForbidden = NewHTTPError(http.StatusForbidden) ErrMethodNotAllowed = NewHTTPError(http.StatusMethodNotAllowed) ErrStatusRequestEntityTooLarge = NewHTTPError(http.StatusRequestEntityTooLarge) ErrValidatorNotRegistered = errors.New("Validator not registered") @@ -255,7 +283,7 @@ func New() (e *Echo) { e.HTTPErrorHandler = e.DefaultHTTPErrorHandler e.Binder = &DefaultBinder{} e.Logger.SetLevel(log.OFF) - e.stdLogger = slog.New(e.Logger.Output(), e.Logger.Prefix()+": ", 0) + e.stdLogger = stdLog.New(e.Logger.Output(), e.Logger.Prefix()+": ", 0) e.pool.New = func() interface{} { return e.NewContext(nil, nil) } @@ -398,12 +426,16 @@ func (e *Echo) Match(methods []string, path string, handler HandlerFunc, middlew // Static registers a new route with path prefix to serve static files from the // provided root directory. func (e *Echo) Static(prefix, root string) { + if root == "" { + root = "." // For security we want to restrict to CWD. + } static(e, prefix, root) } func static(i i, prefix, root string) { h := func(c Context) error { - return c.File(path.Join(root, c.Param("*"))) + name := filepath.Join(root, path.Clean("/"+c.Param("*"))) // "/"+ for security + return c.File(name) } i.GET(prefix, h) if prefix == "/" { @@ -430,7 +462,7 @@ func (e *Echo) add(method, path string, handler HandlerFunc, middleware ...Middl } return h(c) }) - r := Route{ + r := &Route{ Method: method, Path: path, Handler: name, @@ -476,8 +508,8 @@ func (e *Echo) URL(h HandlerFunc, params ...interface{}) string { } // Routes returns the registered routes. -func (e *Echo) Routes() []Route { - routes := []Route{} +func (e *Echo) Routes() []*Route { + routes := []*Route{} for _, v := range e.router.routes { routes = append(routes, v) } @@ -499,8 +531,8 @@ func (e *Echo) ReleaseContext(c Context) { // ServeHTTP implements `http.Handler` interface, which serves HTTP requests. func (e *Echo) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Acquire lock - e.Mutex.RLock() - defer e.Mutex.RUnlock() + // e.Mutex.RLock() + // defer e.Mutex.RUnlock() // Acquire context c := e.pool.Get().(*context) @@ -510,7 +542,10 @@ func (e *Echo) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Middleware h := func(c Context) error { method := r.Method - path := r.URL.EscapedPath() + path := r.URL.RawPath + if path == "" { + path = r.URL.Path + } e.router.Find(method, path, c) h := c.Handler() for i := len(e.middleware) - 1; i >= 0; i-- { @@ -572,8 +607,15 @@ func (e *Echo) startTLS(address string) error { func (e *Echo) StartServer(s *http.Server) (err error) { // Setup e.colorer.SetOutput(e.Logger.Output()) - s.Handler = e s.ErrorLog = e.stdLogger + s.Handler = e + if e.Debug { + e.Logger.SetLevel(log.DEBUG) + } + + if !e.HideBanner { + e.colorer.Printf(banner, e.colorer.Red("v"+version), e.colorer.Blue(website)) + } if s.TLSConfig == nil { if e.Listener == nil { @@ -582,7 +624,9 @@ func (e *Echo) StartServer(s *http.Server) (err error) { return err } } - e.colorer.Printf("⇛ http server started on %s\n", e.colorer.Green(e.Listener.Addr())) + if !e.HideBanner { + e.colorer.Printf("⇨ http server started on %s\n", e.colorer.Green(e.Listener.Addr())) + } return s.Serve(e.Listener) } if e.TLSListener == nil { @@ -592,7 +636,9 @@ func (e *Echo) StartServer(s *http.Server) (err error) { } e.TLSListener = tls.NewListener(l, s.TLSConfig) } - e.colorer.Printf("⇛ https server started on %s\n", e.colorer.Green(e.TLSListener.Addr())) + if !e.HideBanner { + e.colorer.Printf("⇨ https server started on %s\n", e.colorer.Green(e.TLSListener.Addr())) + } return s.Serve(e.TLSListener) } diff --git a/vendor/github.com/labstack/echo/echo_go1.8.go b/vendor/github.com/labstack/echo/echo_go1.8.go new file mode 100644 index 00000000..340bed70 --- /dev/null +++ b/vendor/github.com/labstack/echo/echo_go1.8.go @@ -0,0 +1,25 @@ +// +build go1.8 + +package echo + +import ( + stdContext "context" +) + +// Close immediately stops the server. +// It internally calls `http.Server#Close()`. +func (e *Echo) Close() error { + if err := e.TLSServer.Close(); err != nil { + return err + } + return e.Server.Close() +} + +// Shutdown stops server the gracefully. +// It internally calls `http.Server#Shutdown()`. +func (e *Echo) Shutdown(ctx stdContext.Context) error { + if err := e.TLSServer.Shutdown(ctx); err != nil { + return err + } + return e.Server.Shutdown(ctx) +} diff --git a/vendor/github.com/labstack/echo/group.go b/vendor/github.com/labstack/echo/group.go index 9767bb19..799a8f90 100644 --- a/vendor/github.com/labstack/echo/group.go +++ b/vendor/github.com/labstack/echo/group.go @@ -1,8 +1,12 @@ package echo +import ( + "path" +) + type ( // Group is a set of sub-routes for a specified route. It can be used for inner - // routes that share a common middlware or functionality that should be separate + // routes that share a common middleware or functionality that should be separate // from the parent echo instance while still inheriting from it. Group struct { prefix string @@ -14,6 +18,11 @@ type ( // Use implements `Echo#Use()` for sub-routes within the Group. func (g *Group) Use(middleware ...MiddlewareFunc) { g.middleware = append(g.middleware, middleware...) + // Allow all requests to reach the group as they might get dropped if router + // doesn't find a match, making none of the group middleware process. + g.echo.Any(path.Clean(g.prefix+"/*"), func(c Context) error { + return ErrNotFound + }, g.middleware...) } // CONNECT implements `Echo#CONNECT()` for sub-routes within the Group. diff --git a/vendor/github.com/labstack/echo/middleware/basic_auth.go b/vendor/github.com/labstack/echo/middleware/basic_auth.go index e98a87e3..c1f34c8f 100644 --- a/vendor/github.com/labstack/echo/middleware/basic_auth.go +++ b/vendor/github.com/labstack/echo/middleware/basic_auth.go @@ -2,6 +2,7 @@ package middleware import ( "encoding/base64" + "strconv" "github.com/labstack/echo" ) @@ -15,20 +16,26 @@ type ( // Validator is a function to validate BasicAuth credentials. // Required. Validator BasicAuthValidator + + // Realm is a string to define realm attribute of BasicAuth. + // Default value "Restricted". + Realm string } // BasicAuthValidator defines a function to validate BasicAuth credentials. - BasicAuthValidator func(string, string, echo.Context) bool + BasicAuthValidator func(string, string, echo.Context) (bool, error) ) const ( - basic = "Basic" + basic = "Basic" + defaultRealm = "Restricted" ) var ( // DefaultBasicAuthConfig is the default BasicAuth middleware config. DefaultBasicAuthConfig = BasicAuthConfig{ Skipper: DefaultSkipper, + Realm: defaultRealm, } ) @@ -52,6 +59,9 @@ func BasicAuthWithConfig(config BasicAuthConfig) echo.MiddlewareFunc { if config.Skipper == nil { config.Skipper = DefaultBasicAuthConfig.Skipper } + if config.Realm == "" { + config.Realm = defaultRealm + } return func(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { @@ -71,15 +81,25 @@ func BasicAuthWithConfig(config BasicAuthConfig) echo.MiddlewareFunc { for i := 0; i < len(cred); i++ { if cred[i] == ':' { // Verify credentials - if config.Validator(cred[:i], cred[i+1:], c) { + valid, err := config.Validator(cred[:i], cred[i+1:], c) + if err != nil { + return err + } else if valid { return next(c) } } } } + realm := "" + if config.Realm == defaultRealm { + realm = defaultRealm + } else { + realm = strconv.Quote(config.Realm) + } + // Need to return `401` for browsers to pop-up login box. - c.Response().Header().Set(echo.HeaderWWWAuthenticate, basic+" realm=Restricted") + c.Response().Header().Set(echo.HeaderWWWAuthenticate, basic+" realm="+realm) return echo.ErrUnauthorized } } diff --git a/vendor/github.com/labstack/echo/middleware/compress.go b/vendor/github.com/labstack/echo/middleware/compress.go index eee67b37..cffadbd1 100644 --- a/vendor/github.com/labstack/echo/middleware/compress.go +++ b/vendor/github.com/labstack/echo/middleware/compress.go @@ -108,8 +108,8 @@ func (w *gzipResponseWriter) Write(b []byte) (int, error) { return w.Writer.Write(b) } -func (w *gzipResponseWriter) Flush() error { - return w.Writer.(*gzip.Writer).Flush() +func (w *gzipResponseWriter) Flush() { + w.Writer.(*gzip.Writer).Flush() } func (w *gzipResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { diff --git a/vendor/github.com/labstack/echo/middleware/jwt.go b/vendor/github.com/labstack/echo/middleware/jwt.go index b2658739..5d2072e7 100644 --- a/vendor/github.com/labstack/echo/middleware/jwt.go +++ b/vendor/github.com/labstack/echo/middleware/jwt.go @@ -91,7 +91,7 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc { config.Skipper = DefaultJWTConfig.Skipper } if config.SigningKey == nil { - panic("jwt middleware requires signing key") + panic("echo: jwt middleware requires signing key") } if config.SigningMethod == "" { config.SigningMethod = DefaultJWTConfig.SigningMethod diff --git a/vendor/github.com/labstack/echo/middleware/key_auth.go b/vendor/github.com/labstack/echo/middleware/key_auth.go index 4d4cb940..5ef87e3d 100644 --- a/vendor/github.com/labstack/echo/middleware/key_auth.go +++ b/vendor/github.com/labstack/echo/middleware/key_auth.go @@ -32,7 +32,7 @@ type ( } // KeyAuthValidator defines a function to validate KeyAuth credentials. - KeyAuthValidator func(string, echo.Context) bool + KeyAuthValidator func(string, echo.Context) (bool, error) keyExtractor func(echo.Context) (string, error) ) @@ -94,7 +94,10 @@ func KeyAuthWithConfig(config KeyAuthConfig) echo.MiddlewareFunc { if err != nil { return echo.NewHTTPError(http.StatusBadRequest, err.Error()) } - if config.Validator(key, c) { + valid, err := config.Validator(key, c) + if err != nil { + return err + } else if valid { return next(c) } diff --git a/vendor/github.com/labstack/echo/middleware/logger.go b/vendor/github.com/labstack/echo/middleware/logger.go index e26b5496..b9c54468 100644 --- a/vendor/github.com/labstack/echo/middleware/logger.go +++ b/vendor/github.com/labstack/echo/middleware/logger.go @@ -26,7 +26,7 @@ type ( // - time_unix_nano // - time_rfc3339 // - time_rfc3339_nano - // - id (Request ID - Not implemented) + // - id (Request ID) // - remote_ip // - uri // - host @@ -62,7 +62,7 @@ var ( // DefaultLoggerConfig is the default Logger middleware config. DefaultLoggerConfig = LoggerConfig{ Skipper: DefaultSkipper, - Format: `{"time":"${time_rfc3339_nano}","remote_ip":"${remote_ip}","host":"${host}",` + + Format: `{"time":"${time_rfc3339_nano}","id":"${id}","remote_ip":"${remote_ip}","host":"${host}",` + `"method":"${method}","uri":"${uri}","status":${status}, "latency":${latency},` + `"latency_human":"${latency_human}","bytes_in":${bytes_in},` + `"bytes_out":${bytes_out}}` + "\n", @@ -126,6 +126,12 @@ func LoggerWithConfig(config LoggerConfig) echo.MiddlewareFunc { return buf.WriteString(time.Now().Format(time.RFC3339)) case "time_rfc3339_nano": return buf.WriteString(time.Now().Format(time.RFC3339Nano)) + case "id": + id := req.Header.Get(echo.HeaderXRequestID) + if id == "" { + id = res.Header().Get(echo.HeaderXRequestID) + } + return buf.WriteString(id) case "remote_ip": return buf.WriteString(c.RealIP()) case "host": @@ -177,6 +183,11 @@ func LoggerWithConfig(config LoggerConfig) echo.MiddlewareFunc { return buf.Write([]byte(c.QueryParam(tag[6:]))) case strings.HasPrefix(tag, "form:"): return buf.Write([]byte(c.FormValue(tag[5:]))) + case strings.HasPrefix(tag, "cookie:"): + cookie, err := c.Cookie(tag[7:]) + if err == nil { + return buf.Write([]byte(cookie.Value)) + } } } return 0, nil diff --git a/vendor/github.com/labstack/echo/middleware/middleware.go b/vendor/github.com/labstack/echo/middleware/middleware.go index 7edccc1d..efcbab91 100644 --- a/vendor/github.com/labstack/echo/middleware/middleware.go +++ b/vendor/github.com/labstack/echo/middleware/middleware.go @@ -9,6 +9,6 @@ type ( ) // DefaultSkipper returns false which processes the middleware. -func DefaultSkipper(c echo.Context) bool { +func DefaultSkipper(echo.Context) bool { return false } diff --git a/vendor/github.com/labstack/echo/middleware/proxy.go b/vendor/github.com/labstack/echo/middleware/proxy.go new file mode 100644 index 00000000..7eb24abf --- /dev/null +++ b/vendor/github.com/labstack/echo/middleware/proxy.go @@ -0,0 +1,160 @@ +package middleware + +import ( + "errors" + "fmt" + "io" + "math/rand" + "net" + "net/http" + "net/http/httputil" + "net/url" + "sync/atomic" + "time" + + "github.com/labstack/echo" +) + +// TODO: Handle TLS proxy + +type ( + // ProxyConfig defines the config for Proxy middleware. + ProxyConfig struct { + // Skipper defines a function to skip middleware. + Skipper Skipper + + // Balancer defines a load balancing technique. + // Required. + // Possible values: + // - RandomBalancer + // - RoundRobinBalancer + Balancer ProxyBalancer + } + + // ProxyTarget defines the upstream target. + ProxyTarget struct { + URL *url.URL + } + + // RandomBalancer implements a random load balancing technique. + RandomBalancer struct { + Targets []*ProxyTarget + random *rand.Rand + } + + // RoundRobinBalancer implements a round-robin load balancing technique. + RoundRobinBalancer struct { + Targets []*ProxyTarget + i uint32 + } + + // ProxyBalancer defines an interface to implement a load balancing technique. + ProxyBalancer interface { + Next() *ProxyTarget + } +) + +func proxyHTTP(t *ProxyTarget) http.Handler { + return httputil.NewSingleHostReverseProxy(t.URL) +} + +func proxyRaw(t *ProxyTarget, c echo.Context) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + h, ok := w.(http.Hijacker) + if !ok { + c.Error(errors.New("proxy raw, not a hijacker")) + return + } + in, _, err := h.Hijack() + if err != nil { + c.Error(fmt.Errorf("proxy raw, hijack error=%v, url=%s", r.URL, err)) + return + } + defer in.Close() + + out, err := net.Dial("tcp", t.URL.Host) + if err != nil { + he := echo.NewHTTPError(http.StatusBadGateway, fmt.Sprintf("proxy raw, dial error=%v, url=%s", r.URL, err)) + c.Error(he) + return + } + defer out.Close() + + err = r.Write(out) + if err != nil { + he := echo.NewHTTPError(http.StatusBadGateway, fmt.Sprintf("proxy raw, request copy error=%v, url=%s", r.URL, err)) + c.Error(he) + return + } + + errc := make(chan error, 2) + cp := func(dst io.Writer, src io.Reader) { + _, err := io.Copy(dst, src) + errc <- err + } + + go cp(out, in) + go cp(in, out) + err = <-errc + if err != nil && err != io.EOF { + c.Logger().Errorf("proxy raw, error=%v, url=%s", r.URL, err) + } + }) +} + +// Next randomly returns an upstream target. +func (r *RandomBalancer) Next() *ProxyTarget { + if r.random == nil { + r.random = rand.New(rand.NewSource(int64(time.Now().Nanosecond()))) + } + return r.Targets[r.random.Intn(len(r.Targets))] +} + +// Next returns an upstream target using round-robin technique. +func (r *RoundRobinBalancer) Next() *ProxyTarget { + r.i = r.i % uint32(len(r.Targets)) + t := r.Targets[r.i] + atomic.AddUint32(&r.i, 1) + return t +} + +// Proxy returns an HTTP/WebSocket reverse proxy middleware. +func Proxy(config ProxyConfig) echo.MiddlewareFunc { + // Defaults + if config.Skipper == nil { + config.Skipper = DefaultLoggerConfig.Skipper + } + if config.Balancer == nil { + panic("echo: proxy middleware requires balancer") + } + + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) (err error) { + req := c.Request() + res := c.Response() + tgt := config.Balancer.Next() + + // Fix header + if req.Header.Get(echo.HeaderXRealIP) == "" { + req.Header.Set(echo.HeaderXRealIP, c.RealIP()) + } + if req.Header.Get(echo.HeaderXForwardedProto) == "" { + req.Header.Set(echo.HeaderXForwardedProto, c.Scheme()) + } + if c.IsWebSocket() && req.Header.Get(echo.HeaderXForwardedFor) == "" { // For HTTP, it is automatically set by Go HTTP reverse proxy. + req.Header.Set(echo.HeaderXForwardedFor, c.RealIP()) + } + + // Proxy + switch { + case c.IsWebSocket(): + proxyRaw(tgt, c).ServeHTTP(res, req) + case req.Header.Get(echo.HeaderAccept) == "text/event-stream": + default: + proxyHTTP(tgt).ServeHTTP(res, req) + } + + return + } + } +} diff --git a/vendor/github.com/labstack/echo/middleware/request_id.go b/vendor/github.com/labstack/echo/middleware/request_id.go new file mode 100644 index 00000000..f376c296 --- /dev/null +++ b/vendor/github.com/labstack/echo/middleware/request_id.go @@ -0,0 +1,64 @@ +package middleware + +import ( + "github.com/labstack/echo" + "github.com/labstack/gommon/random" +) + +type ( + // RequestIDConfig defines the config for RequestID middleware. + RequestIDConfig struct { + // Skipper defines a function to skip middleware. + Skipper Skipper + + // Generator defines a function to generate an ID. + // Optional. Default value random.String(32). + Generator func() string + } +) + +var ( + // DefaultRequestIDConfig is the default RequestID middleware config. + DefaultRequestIDConfig = RequestIDConfig{ + Skipper: DefaultSkipper, + Generator: generator, + } +) + +// RequestID returns a X-Request-ID middleware. +func RequestID() echo.MiddlewareFunc { + return RequestIDWithConfig(DefaultRequestIDConfig) +} + +// RequestIDWithConfig returns a X-Request-ID middleware with config. +func RequestIDWithConfig(config RequestIDConfig) echo.MiddlewareFunc { + // Defaults + if config.Skipper == nil { + config.Skipper = DefaultRequestIDConfig.Skipper + } + if config.Generator == nil { + config.Generator = generator + } + + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + if config.Skipper(c) { + return next(c) + } + + req := c.Request() + res := c.Response() + rid := req.Header.Get(echo.HeaderXRequestID) + if rid == "" { + rid = config.Generator() + } + res.Header().Set(echo.HeaderXRequestID, rid) + + return next(c) + } + } +} + +func generator() string { + return random.String(32) +} diff --git a/vendor/github.com/labstack/echo/middleware/static.go b/vendor/github.com/labstack/echo/middleware/static.go index 793c1445..e715c1c4 100644 --- a/vendor/github.com/labstack/echo/middleware/static.go +++ b/vendor/github.com/labstack/echo/middleware/static.go @@ -3,7 +3,9 @@ package middleware import ( "fmt" "os" + "path" "path/filepath" + "strings" "github.com/labstack/echo" ) @@ -53,6 +55,9 @@ func Static(root string) echo.MiddlewareFunc { // See `Static()`. func StaticWithConfig(config StaticConfig) echo.MiddlewareFunc { // Defaults + if config.Root == "" { + config.Root = "." // For security we want to restrict to CWD. + } if config.Skipper == nil { config.Skipper = DefaultStaticConfig.Skipper } @@ -62,26 +67,44 @@ func StaticWithConfig(config StaticConfig) echo.MiddlewareFunc { return func(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { - p := c.Param("*") - name := filepath.Join(config.Root, p) - fi, err := os.Stat(name) + if config.Skipper(c) { + return next(c) + } + p := c.Request().URL.Path + if strings.HasSuffix(c.Path(), "*") { // When serving from a group, e.g. `/static*`. + p = c.Param("*") + } + name := filepath.Join(config.Root, path.Clean("/"+p)) // "/"+ for security + + fi, err := os.Stat(name) if err != nil { if os.IsNotExist(err) { - if config.HTML5 { + if config.HTML5 && path.Ext(p) == "" { return c.File(filepath.Join(config.Root, config.Index)) } - return echo.ErrNotFound + return next(c) } return err } if fi.IsDir() { - if config.Browse { - return listDir(name, c.Response()) + index := filepath.Join(name, config.Index) + fi, err = os.Stat(index) + + if err != nil { + if config.Browse { + return listDir(name, c.Response()) + } + if os.IsNotExist(err) { + return next(c) + } + return err } - return c.File(filepath.Join(name, config.Index)) + + return c.File(index) } + return c.File(name) } } diff --git a/vendor/github.com/labstack/echo/router.go b/vendor/github.com/labstack/echo/router.go index 5cb47116..2ef904e0 100644 --- a/vendor/github.com/labstack/echo/router.go +++ b/vendor/github.com/labstack/echo/router.go @@ -7,7 +7,7 @@ type ( // request matching and URL path parameter parsing. Router struct { tree *node - routes map[string]Route + routes map[string]*Route echo *Echo } node struct { @@ -47,7 +47,7 @@ func NewRouter(e *Echo) *Router { tree: &node{ methodHandler: new(methodHandler), }, - routes: make(map[string]Route), + routes: map[string]*Route{}, echo: e, } } @@ -101,7 +101,7 @@ func (r *Router) insert(method, path string, h HandlerFunc, t kind, ppath string cn := r.tree // Current node as root if cn == nil { - panic("echo ⇛ invalid method") + panic("echo: invalid method") } search := path @@ -296,18 +296,19 @@ func (n *node) checkMethodNotAllowed() HandlerFunc { // - Get context from `Echo#AcquireContext()` // - Reset it `Context#Reset()` // - Return it `Echo#ReleaseContext()`. -func (r *Router) Find(method, path string, context Context) { - context.SetPath(path) +func (r *Router) Find(method, path string, c Context) { + ctx := c.(*context) + ctx.path = path cn := r.tree // Current node as root var ( search = path - c *node // Child node - n int // Param counter - nk kind // Next kind - nn *node // Next node - ns string // Next search - pvalues = context.ParamValues() + child *node // Child node + n int // Param counter + nk kind // Next kind + nn *node // Next node + ns string // Next search + pvalues = ctx.pvalues // Use the internal slice so the interface can keep the illusion of a dynamic slice ) // Search order static > param > any @@ -352,20 +353,20 @@ func (r *Router) Find(method, path string, context Context) { } // Static node - if c = cn.findChild(search[0], skind); c != nil { + if child = cn.findChild(search[0], skind); child != nil { // Save next if cn.prefix[len(cn.prefix)-1] == '/' { // Issue #623 nk = pkind nn = cn ns = search } - cn = c + cn = child continue } // Param node Param: - if c = cn.findChildByKind(pkind); c != nil { + if child = cn.findChildByKind(pkind); child != nil { // Issue #378 if len(pvalues) == n { continue @@ -378,7 +379,7 @@ func (r *Router) Find(method, path string, context Context) { ns = search } - cn = c + cn = child i, l := 0, len(search) for ; i < l && search[i] != '/'; i++ { } @@ -409,13 +410,13 @@ func (r *Router) Find(method, path string, context Context) { } End: - context.SetHandler(cn.findHandler(method)) - context.SetPath(cn.ppath) - context.SetParamNames(cn.pnames...) + ctx.handler = cn.findHandler(method) + ctx.path = cn.ppath + ctx.pnames = cn.pnames // NOTE: Slow zone... - if context.Handler() == nil { - context.SetHandler(cn.checkMethodNotAllowed()) + if ctx.handler == nil { + ctx.handler = cn.checkMethodNotAllowed() // Dig further for any, might have an empty value for *, e.g. // serving a directory. Issue #207. @@ -423,12 +424,12 @@ End: return } if h := cn.findHandler(method); h != nil { - context.SetHandler(h) + ctx.handler = h } else { - context.SetHandler(cn.checkMethodNotAllowed()) + ctx.handler = cn.checkMethodNotAllowed() } - context.SetPath(cn.ppath) - context.SetParamNames(cn.pnames...) + ctx.path = cn.ppath + ctx.pnames = cn.pnames pvalues[len(cn.pnames)-1] = "" } |