4
0
mirror of https://github.com/cwinfo/matterbridge.git synced 2025-07-03 08:27:44 +00:00

Update vendor, move to labstack/echo/v4 Fixes #698

This commit is contained in:
Wim
2019-01-31 17:06:36 +01:00
parent f8a1ab4622
commit c81c0dd22a
265 changed files with 32014 additions and 7207 deletions

View File

@ -1,14 +0,0 @@
language: go
go:
- 1.9.x
- 1.10.x
- tip
install:
- make dependency
script:
- make test
after_success:
- bash <(curl -s https://codecov.io/bash)
matrix:
allow_failures:
- go: tip

View File

@ -1,75 +0,0 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
name = "github.com/davecgh/go-spew"
packages = ["spew"]
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
version = "v1.1.0"
[[projects]]
name = "github.com/dgrijalva/jwt-go"
packages = ["."]
revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e"
version = "v3.2.0"
[[projects]]
name = "github.com/labstack/gommon"
packages = ["bytes","color","log","random"]
revision = "6fe1405d73ec4bd4cd8a4ac8e2a2b2bf95d03954"
version = "0.2.4"
[[projects]]
name = "github.com/mattn/go-colorable"
packages = ["."]
revision = "167de6bfdfba052fa6b2d3664c8f5272e23c9072"
version = "v0.0.9"
[[projects]]
name = "github.com/mattn/go-isatty"
packages = ["."]
revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39"
version = "v0.0.3"
[[projects]]
name = "github.com/pmezard/go-difflib"
packages = ["difflib"]
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
version = "v1.0.0"
[[projects]]
name = "github.com/stretchr/testify"
packages = ["assert"]
revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71"
version = "v1.2.1"
[[projects]]
branch = "master"
name = "github.com/valyala/bytebufferpool"
packages = ["."]
revision = "e746df99fe4a3986f4d4f79e13c1e0117ce9c2f7"
[[projects]]
branch = "master"
name = "github.com/valyala/fasttemplate"
packages = ["."]
revision = "dcecefd839c4193db0d35b88ec65b4c12d360ab0"
[[projects]]
branch = "master"
name = "golang.org/x/crypto"
packages = ["acme","acme/autocert"]
revision = "182114d582623c1caa54f73de9c7224e23a48487"
[[projects]]
branch = "master"
name = "golang.org/x/sys"
packages = ["unix"]
revision = "c28acc882ebcbfbe8ce9f0f14b9ac26ee138dd51"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "9c7b45e80fe353405800cf01f429b3a203cfb8d4468a04c64a908e11a98ea764"
solver-name = "gps-cdcl"
solver-version = 1

View File

@ -1,42 +0,0 @@
# Gopkg.toml example
#
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
[[constraint]]
name = "github.com/dgrijalva/jwt-go"
version = "3.2.0"
[[constraint]]
name = "github.com/labstack/gommon"
version = "0.2.4"
[[constraint]]
name = "github.com/stretchr/testify"
version = "1.2.1"
[[constraint]]
branch = "master"
name = "github.com/valyala/fasttemplate"
[[constraint]]
branch = "master"
name = "golang.org/x/crypto"

View File

@ -1,17 +0,0 @@
DEP_VERSION=0.4.1
dependency:
curl -fsSL -o ${GOPATH}/bin/dep https://github.com/golang/dep/releases/download/v${DEP_VERSION}/dep-linux-amd64
chmod +x ${GOPATH}/bin/dep
dep ensure
test:
echo "" > coverage.txt
for d in $(shell go list ./... | grep -v vendor); do \
go test -race -coverprofile=profile.out -covermode=atomic $$d || exit 1; \
[ -f profile.out ] && cat profile.out >> coverage.txt && rm profile.out; \
done
tag:
@git tag `grep -P '^\tversion = ' echo.go|cut -f2 -d'"'`
@git tag|grep -v ^v

16
vendor/github.com/labstack/echo/v4/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,16 @@
language: go
go:
- 1.11.x
- tip
env:
- GO111MODULE=on
install:
- go get -v golang.org/x/lint/golint
script:
- golint -set_exit_status ./...
- go test -race -coverprofile=coverage.txt -covermode=atomic ./...
after_success:
- bash <(curl -s https://codecov.io/bash)
matrix:
allow_failures:
- go: tip

3
vendor/github.com/labstack/echo/v4/Makefile generated vendored Normal file
View File

@ -0,0 +1,3 @@
tag:
@git tag `grep -P '^\tversion = ' echo.go|cut -f2 -d'"'`
@git tag|grep -v ^v

View File

@ -4,12 +4,26 @@
[![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](http://godoc.org/github.com/labstack/echo)
[![Go Report Card](https://goreportcard.com/badge/github.com/labstack/echo?style=flat-square)](https://goreportcard.com/report/github.com/labstack/echo)
[![Build Status](http://img.shields.io/travis/labstack/echo.svg?style=flat-square)](https://travis-ci.org/labstack/echo)
[![Codecov](https://img.shields.io/codecov/c/github/labstack/echo.svg?style=flat-square)](https://codecov.io/gh/labstack/echo)
[![Codecov](https://img.shields.io/codecov/c/github/labstack/echo.svg?style=flat-square)](https://codecov.io/gh/labstack/echo)
[![Join the chat at https://gitter.im/labstack/echo](https://img.shields.io/badge/gitter-join%20chat-brightgreen.svg?style=flat-square)](https://gitter.im/labstack/echo)
[![Forum](https://img.shields.io/badge/community-forum-00afd1.svg?style=flat-square)](https://forum.labstack.com)
[![Twitter](https://img.shields.io/badge/twitter-@labstack-55acee.svg?style=flat-square)](https://twitter.com/labstack)
[![License](http://img.shields.io/badge/license-mit-blue.svg?style=flat-square)](https://raw.githubusercontent.com/labstack/echo/master/LICENSE)
## Supported Go versions
As of version 4.0.0, Echo is available as a [Go module](https://github.com/golang/go/wiki/Modules).
Therefore a Go version capable of understanding /vN suffixed imports is required:
- 1.9.7+
- 1.10.3+
- 1.11+
Any of these versions will allow you to import Echo as `github.com/labstack/echo/v4` which is the recommended
way of using Echo going forward.
For older versions, please use the latest v3 tag.
## Feature Overview
- Optimized HTTP router which smartly prioritize routes
@ -32,7 +46,7 @@ Date: 2018/03/15<br>
Source: https://github.com/vishr/web-framework-benchmark<br>
Lower is better!
<img src="https://api.labstack.com/chart/bar?values=37223,55382,2985,5265|42013,59865,3350,6424&labels=Static,GitHub%20API,Parse%20API,Gplus%20API&titles=Echo,Gin&colors=lightseagreen,goldenrod&x_title=Routes&y_title=ns/op">
<img src="https://i.imgur.com/I32VdMJ.png">
## [Guide](https://echo.labstack.com/guide)
@ -44,8 +58,8 @@ package main
import (
"net/http"
"github.com/labstack/echo"
"github.com/labstack/echo/middleware"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
func main() {
@ -90,6 +104,7 @@ func hello(c echo.Context) error {
- Improve/fix documentation
## Credits
- [Vishal Rana](https://github.com/vishr) - Author
- [Nitin Rana](https://github.com/nr17) - Consultant
- [Contributors](https://github.com/labstack/echo/graphs/contributors)

View File

@ -31,9 +31,9 @@ type (
func (b *DefaultBinder) Bind(i interface{}, c Context) (err error) {
req := c.Request()
if req.ContentLength == 0 {
if req.Method == GET || req.Method == DELETE {
if req.Method == http.MethodGet || req.Method == http.MethodDelete {
if err = b.bindData(i, c.QueryParams(), "query"); err != nil {
return NewHTTPError(http.StatusBadRequest, err.Error())
return NewHTTPError(http.StatusBadRequest, err.Error()).SetInternal(err)
}
return
}
@ -44,30 +44,28 @@ func (b *DefaultBinder) Bind(i interface{}, c Context) (err error) {
case strings.HasPrefix(ctype, MIMEApplicationJSON):
if err = json.NewDecoder(req.Body).Decode(i); err != nil {
if ute, ok := err.(*json.UnmarshalTypeError); ok {
return NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Unmarshal type error: expected=%v, got=%v, offset=%v", ute.Type, ute.Value, ute.Offset))
return NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Unmarshal type error: expected=%v, got=%v, field=%v, offset=%v", ute.Type, ute.Value, ute.Field, ute.Offset)).SetInternal(err)
} else if se, ok := err.(*json.SyntaxError); ok {
return NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Syntax error: offset=%v, error=%v", se.Offset, se.Error()))
} else {
return NewHTTPError(http.StatusBadRequest, err.Error())
return NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Syntax error: offset=%v, error=%v", se.Offset, se.Error())).SetInternal(err)
}
return NewHTTPError(http.StatusBadRequest, err.Error()).SetInternal(err)
}
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()))
return NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Unsupported type error: type=%v, error=%v", ute.Type, ute.Error())).SetInternal(err)
} else if se, ok := err.(*xml.SyntaxError); ok {
return NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Syntax error: line=%v, error=%v", se.Line, se.Error()))
} else {
return NewHTTPError(http.StatusBadRequest, err.Error())
return NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Syntax error: line=%v, error=%v", se.Line, se.Error())).SetInternal(err)
}
return NewHTTPError(http.StatusBadRequest, err.Error()).SetInternal(err)
}
case strings.HasPrefix(ctype, MIMEApplicationForm), strings.HasPrefix(ctype, MIMEMultipartForm):
params, err := c.FormParams()
if err != nil {
return NewHTTPError(http.StatusBadRequest, err.Error())
return NewHTTPError(http.StatusBadRequest, err.Error()).SetInternal(err)
}
if err = b.bindData(i, params, "form"); err != nil {
return NewHTTPError(http.StatusBadRequest, err.Error())
return NewHTTPError(http.StatusBadRequest, err.Error()).SetInternal(err)
}
default:
return ErrUnsupportedMediaType
@ -96,14 +94,29 @@ func (b *DefaultBinder) bindData(ptr interface{}, data map[string][]string, tag
inputFieldName = typeField.Name
// If tag is nil, we inspect if the field is a struct.
if _, ok := bindUnmarshaler(structField); !ok && structFieldKind == reflect.Struct {
err := b.bindData(structField.Addr().Interface(), data, tag)
if err != nil {
if err := b.bindData(structField.Addr().Interface(), data, tag); err != nil {
return err
}
continue
}
}
inputValue, exists := data[inputFieldName]
if !exists {
// Go json.Unmarshal supports case insensitive binding. However the
// url params are bound case sensitive which is inconsistent. To
// fix this we must check all of the map values in a
// case-insensitive search.
inputFieldName = strings.ToLower(inputFieldName)
for k, v := range data {
if strings.ToLower(k) == inputFieldName {
inputValue = v
exists = true
break
}
}
}
if !exists {
continue
}
@ -126,10 +139,9 @@ func (b *DefaultBinder) bindData(ptr interface{}, data map[string][]string, tag
}
}
val.Field(i).Set(slice)
} else {
if err := setWithProperType(typeField.Type.Kind(), inputValue[0], structField); err != nil {
return err
}
} else if err := setWithProperType(typeField.Type.Kind(), inputValue[0], structField); err != nil {
return err
}
}
return nil

View File

@ -204,6 +204,7 @@ type (
const (
defaultMemory = 32 << 20 // 32 MB
indexPage = "index.html"
defaultIndent = " "
)
func (c *context) writeContentType(value string) {
@ -256,14 +257,13 @@ func (c *context) Scheme() string {
}
func (c *context) RealIP() string {
ra := c.request.RemoteAddr
if ip := c.request.Header.Get(HeaderXForwardedFor); ip != "" {
ra = strings.Split(ip, ", ")[0]
} else if ip := c.request.Header.Get(HeaderXRealIP); ip != "" {
ra = ip
} else {
ra, _, _ = net.SplitHostPort(ra)
return strings.Split(ip, ", ")[0]
}
if ip := c.request.Header.Get(HeaderXRealIP); ip != "" {
return ip
}
ra, _, _ := net.SplitHostPort(c.request.RemoteAddr)
return ra
}
@ -404,24 +404,46 @@ func (c *context) String(code int, s string) (err error) {
return c.Blob(code, MIMETextPlainCharsetUTF8, []byte(s))
}
func (c *context) JSON(code int, i interface{}) (err error) {
func (c *context) jsonPBlob(code int, callback string, i interface{}) (err error) {
enc := json.NewEncoder(c.response)
_, pretty := c.QueryParams()["pretty"]
if c.echo.Debug || pretty {
return c.JSONPretty(code, i, " ")
enc.SetIndent("", " ")
}
b, err := json.Marshal(i)
if err != nil {
c.writeContentType(MIMEApplicationJavaScriptCharsetUTF8)
c.response.WriteHeader(code)
if _, err = c.response.Write([]byte(callback + "(")); err != nil {
return
}
return c.JSONBlob(code, b)
if err = enc.Encode(i); err != nil {
return
}
if _, err = c.response.Write([]byte(");")); err != nil {
return
}
return
}
func (c *context) json(code int, i interface{}, indent string) error {
enc := json.NewEncoder(c.response)
if indent != "" {
enc.SetIndent("", indent)
}
c.writeContentType(MIMEApplicationJSONCharsetUTF8)
c.response.WriteHeader(code)
return enc.Encode(i)
}
func (c *context) JSON(code int, i interface{}) (err error) {
indent := ""
if _, pretty := c.QueryParams()["pretty"]; c.echo.Debug || pretty {
indent = defaultIndent
}
return c.json(code, i, indent)
}
func (c *context) JSONPretty(code int, i interface{}, indent string) (err error) {
b, err := json.MarshalIndent(i, "", indent)
if err != nil {
return
}
return c.JSONBlob(code, b)
return c.json(code, i, indent)
}
func (c *context) JSONBlob(code int, b []byte) (err error) {
@ -429,11 +451,7 @@ func (c *context) JSONBlob(code int, b []byte) (err error) {
}
func (c *context) JSONP(code int, callback string, i interface{}) (err error) {
b, err := json.Marshal(i)
if err != nil {
return
}
return c.JSONPBlob(code, callback, b)
return c.jsonPBlob(code, callback, i)
}
func (c *context) JSONPBlob(code int, callback string, b []byte) (err error) {
@ -449,24 +467,29 @@ func (c *context) JSONPBlob(code int, callback string, b []byte) (err error) {
return
}
func (c *context) XML(code int, i interface{}) (err error) {
_, pretty := c.QueryParams()["pretty"]
if c.echo.Debug || pretty {
return c.XMLPretty(code, i, " ")
func (c *context) xml(code int, i interface{}, indent string) (err error) {
c.writeContentType(MIMEApplicationXMLCharsetUTF8)
c.response.WriteHeader(code)
enc := xml.NewEncoder(c.response)
if indent != "" {
enc.Indent("", indent)
}
b, err := xml.Marshal(i)
if err != nil {
if _, err = c.response.Write([]byte(xml.Header)); err != nil {
return
}
return c.XMLBlob(code, b)
return enc.Encode(i)
}
func (c *context) XML(code int, i interface{}) (err error) {
indent := ""
if _, pretty := c.QueryParams()["pretty"]; c.echo.Debug || pretty {
indent = defaultIndent
}
return c.xml(code, i, indent)
}
func (c *context) XMLPretty(code int, i interface{}, indent string) (err error) {
b, err := xml.MarshalIndent(i, "", indent)
if err != nil {
return
}
return c.XMLBlob(code, b)
return c.xml(code, i, indent)
}
func (c *context) XMLBlob(code int, b []byte) (err error) {
@ -574,3 +597,4 @@ func (c *context) Reset(r *http.Request, w http.ResponseWriter) {
// NOTE: Don't reset because it has to have length c.echo.maxParam at all times
// c.pvalues = nil
}

View File

@ -8,8 +8,8 @@ Example:
import (
"net/http"
"github.com/labstack/echo"
"github.com/labstack/echo/middleware"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
// Handler
@ -62,7 +62,7 @@ import (
type (
// Echo is the top-level framework instance.
Echo struct {
stdLogger *stdLog.Logger
StdLogger *stdLog.Logger
colorer *color.Color
premiddleware []MiddlewareFunc
middleware []MiddlewareFunc
@ -103,7 +103,7 @@ type (
// MiddlewareFunc defines a function to process middleware.
MiddlewareFunc func(HandlerFunc) HandlerFunc
// HandlerFunc defines a function to server HTTP requests.
// HandlerFunc defines a function to serve HTTP requests.
HandlerFunc func(Context) error
// HTTPErrorHandler is a centralized HTTP error handler.
@ -129,17 +129,18 @@ type (
)
// HTTP methods
// NOTE: Deprecated, please use the stdlib constants directly instead.
const (
CONNECT = "CONNECT"
DELETE = "DELETE"
GET = "GET"
HEAD = "HEAD"
OPTIONS = "OPTIONS"
PATCH = "PATCH"
POST = "POST"
PROPFIND = "PROPFIND"
PUT = "PUT"
TRACE = "TRACE"
CONNECT = http.MethodConnect
DELETE = http.MethodDelete
GET = http.MethodGet
HEAD = http.MethodHead
OPTIONS = http.MethodOptions
PATCH = http.MethodPatch
POST = http.MethodPost
// PROPFIND = "PROPFIND"
PUT = http.MethodPut
TRACE = http.MethodTrace
)
// MIME types
@ -165,6 +166,8 @@ const (
const (
charsetUTF8 = "charset=UTF-8"
// PROPFIND Method can be used on collection and property resources.
PROPFIND = "PROPFIND"
)
// Headers
@ -217,7 +220,8 @@ const (
)
const (
Version = "3.3.5"
// Version of Echo
Version = "4.0.0"
website = "https://echo.labstack.com"
// http://patorjk.com/software/taag/#p=display&f=Small%20Slant&t=Echo
banner = `
@ -234,16 +238,16 @@ ____________________________________O/_______
var (
methods = [...]string{
CONNECT,
DELETE,
GET,
HEAD,
OPTIONS,
PATCH,
POST,
http.MethodConnect,
http.MethodDelete,
http.MethodGet,
http.MethodHead,
http.MethodOptions,
http.MethodPatch,
http.MethodPost,
PROPFIND,
PUT,
TRACE,
http.MethodPut,
http.MethodTrace,
}
)
@ -255,6 +259,12 @@ var (
ErrForbidden = NewHTTPError(http.StatusForbidden)
ErrMethodNotAllowed = NewHTTPError(http.StatusMethodNotAllowed)
ErrStatusRequestEntityTooLarge = NewHTTPError(http.StatusRequestEntityTooLarge)
ErrTooManyRequests = NewHTTPError(http.StatusTooManyRequests)
ErrBadRequest = NewHTTPError(http.StatusBadRequest)
ErrBadGateway = NewHTTPError(http.StatusBadGateway)
ErrInternalServerError = NewHTTPError(http.StatusInternalServerError)
ErrRequestTimeout = NewHTTPError(http.StatusRequestTimeout)
ErrServiceUnavailable = NewHTTPError(http.StatusServiceUnavailable)
ErrValidatorNotRegistered = errors.New("validator not registered")
ErrRendererNotRegistered = errors.New("renderer not registered")
ErrInvalidRedirectCode = errors.New("invalid redirect status code")
@ -289,7 +299,7 @@ func New() (e *Echo) {
e.HTTPErrorHandler = e.DefaultHTTPErrorHandler
e.Binder = &DefaultBinder{}
e.Logger.SetLevel(log.ERROR)
e.stdLogger = stdLog.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)
}
@ -326,7 +336,7 @@ func (e *Echo) DefaultHTTPErrorHandler(err error, c Context) {
code = he.Code
msg = he.Message
if he.Internal != nil {
msg = fmt.Sprintf("%v, %v", err, he.Internal)
err = fmt.Errorf("%v, %v", err, he.Internal)
}
} else if e.Debug {
msg = err.Error()
@ -337,11 +347,9 @@ func (e *Echo) DefaultHTTPErrorHandler(err error, c Context) {
msg = Map{"message": msg}
}
e.Logger.Error(err)
// Send response
if !c.Response().Committed {
if c.Request().Method == HEAD { // Issue #608
if c.Request().Method == http.MethodHead { // Issue #608
err = c.NoContent(code)
} else {
err = c.JSON(code, msg)
@ -365,55 +373,55 @@ func (e *Echo) Use(middleware ...MiddlewareFunc) {
// CONNECT registers a new CONNECT route for a path with matching handler in the
// router with optional route-level middleware.
func (e *Echo) CONNECT(path string, h HandlerFunc, m ...MiddlewareFunc) *Route {
return e.Add(CONNECT, path, h, m...)
return e.Add(http.MethodConnect, path, h, m...)
}
// DELETE registers a new DELETE route for a path with matching handler in the router
// with optional route-level middleware.
func (e *Echo) DELETE(path string, h HandlerFunc, m ...MiddlewareFunc) *Route {
return e.Add(DELETE, path, h, m...)
return e.Add(http.MethodDelete, path, h, m...)
}
// GET registers a new GET route for a path with matching handler in the router
// with optional route-level middleware.
func (e *Echo) GET(path string, h HandlerFunc, m ...MiddlewareFunc) *Route {
return e.Add(GET, path, h, m...)
return e.Add(http.MethodGet, path, h, m...)
}
// HEAD registers a new HEAD route for a path with matching handler in the
// router with optional route-level middleware.
func (e *Echo) HEAD(path string, h HandlerFunc, m ...MiddlewareFunc) *Route {
return e.Add(HEAD, path, h, m...)
return e.Add(http.MethodHead, path, h, m...)
}
// OPTIONS registers a new OPTIONS route for a path with matching handler in the
// router with optional route-level middleware.
func (e *Echo) OPTIONS(path string, h HandlerFunc, m ...MiddlewareFunc) *Route {
return e.Add(OPTIONS, path, h, m...)
return e.Add(http.MethodOptions, path, h, m...)
}
// PATCH registers a new PATCH route for a path with matching handler in the
// router with optional route-level middleware.
func (e *Echo) PATCH(path string, h HandlerFunc, m ...MiddlewareFunc) *Route {
return e.Add(PATCH, path, h, m...)
return e.Add(http.MethodPatch, path, h, m...)
}
// POST registers a new POST route for a path with matching handler in the
// router with optional route-level middleware.
func (e *Echo) POST(path string, h HandlerFunc, m ...MiddlewareFunc) *Route {
return e.Add(POST, path, h, m...)
return e.Add(http.MethodPost, path, h, m...)
}
// PUT registers a new PUT route for a path with matching handler in the
// router with optional route-level middleware.
func (e *Echo) PUT(path string, h HandlerFunc, m ...MiddlewareFunc) *Route {
return e.Add(PUT, path, h, m...)
return e.Add(http.MethodPut, path, h, m...)
}
// TRACE registers a new TRACE route for a path with matching handler in the
// router with optional route-level middleware.
func (e *Echo) TRACE(path string, h HandlerFunc, m ...MiddlewareFunc) *Route {
return e.Add(TRACE, path, h, m...)
return e.Add(http.MethodTrace, path, h, m...)
}
// Any registers a new route for all HTTP methods and path with matching handler
@ -462,11 +470,11 @@ func static(i i, prefix, root string) *Route {
return i.GET(prefix+"/*", h)
}
// File registers a new route with path to serve a static file.
func (e *Echo) File(path, file string) *Route {
// File registers a new route with path to serve a static file with optional route-level middleware.
func (e *Echo) File(path, file string, m ...MiddlewareFunc) *Route {
return e.GET(path, func(c Context) error {
return c.File(file)
})
}, m...)
}
// Add registers a new route for an HTTP method and path with matching handler
@ -559,26 +567,17 @@ func (e *Echo) ServeHTTP(w http.ResponseWriter, r *http.Request) {
c := e.pool.Get().(*context)
c.Reset(r, w)
m := r.Method
h := NotFoundHandler
if e.premiddleware == nil {
path := r.URL.RawPath
if path == "" {
path = r.URL.Path
}
e.router.Find(m, getPath(r), c)
e.router.Find(r.Method, getPath(r), c)
h = c.Handler()
for i := len(e.middleware) - 1; i >= 0; i-- {
h = e.middleware[i](h)
}
} else {
h = func(c Context) error {
path := r.URL.RawPath
if path == "" {
path = r.URL.Path
}
e.router.Find(m, getPath(r), c)
e.router.Find(r.Method, getPath(r), c)
h := c.Handler()
for i := len(e.middleware) - 1; i >= 0; i-- {
h = e.middleware[i](h)
@ -622,10 +621,6 @@ func (e *Echo) StartTLS(address string, certFile, keyFile string) (err error) {
// StartAutoTLS starts an HTTPS server using certificates automatically installed from https://letsencrypt.org.
func (e *Echo) StartAutoTLS(address string) error {
if e.Listener == nil {
go http.ListenAndServe(":http", e.AutoTLSManager.HTTPHandler(nil))
}
s := e.TLSServer
s.TLSConfig = new(tls.Config)
s.TLSConfig.GetCertificate = e.AutoTLSManager.GetCertificate
@ -645,7 +640,7 @@ func (e *Echo) startTLS(address string) error {
func (e *Echo) StartServer(s *http.Server) (err error) {
// Setup
e.colorer.SetOutput(e.Logger.Output())
s.ErrorLog = e.stdLogger
s.ErrorLog = e.StdLogger
s.Handler = e
if e.Debug {
e.Logger.SetLevel(log.DEBUG)
@ -689,7 +684,7 @@ func (e *Echo) Close() error {
return e.Server.Close()
}
// Shutdown stops server the gracefully.
// Shutdown stops the server gracefully.
// It internally calls `http.Server#Shutdown()`.
func (e *Echo) Shutdown(ctx stdContext.Context) error {
if err := e.TLSServer.Shutdown(ctx); err != nil {
@ -712,6 +707,12 @@ func (he *HTTPError) Error() string {
return fmt.Sprintf("code=%d, message=%v", he.Code, he.Message)
}
// SetInternal sets error to HTTPError.Internal
func (he *HTTPError) SetInternal(err error) *HTTPError {
he.Internal = err
return he
}
// WrapHandler wraps `http.Handler` into `echo.HandlerFunc`.
func WrapHandler(h http.Handler) HandlerFunc {
return func(c Context) error {

13
vendor/github.com/labstack/echo/v4/go.mod generated vendored Normal file
View File

@ -0,0 +1,13 @@
module github.com/labstack/echo/v4
require (
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/labstack/gommon v0.2.8
github.com/mattn/go-colorable v0.0.9 // indirect
github.com/mattn/go-isatty v0.0.4 // indirect
github.com/stretchr/testify v1.3.0
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4
golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc // indirect
)

23
vendor/github.com/labstack/echo/v4/go.sum generated vendored Normal file
View File

@ -0,0 +1,23 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/labstack/gommon v0.2.8 h1:JvRqmeZcfrHC5u6uVleB4NxxNbzx6gpbJiQknDbKQu0=
github.com/labstack/gommon v0.2.8/go.mod h1:/tj9csK2iPSBvn+3NLM9e52usepMtrd5ilFYA+wQNJ4=
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4 h1:gKMu1Bf6QINDnvyZuTaACm9ofY+PRh+5vFz4oxBZeF8=
github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4/go.mod h1:50wTf68f99/Zt14pr046Tgt3Lp2vLyFZKzbFXTOabXw=
golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664 h1:YbZJ76lQ1BqNhVe7dKTSB67wDrc2VPRR75IyGyyPDX8=
golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc h1:WiYx1rIFmx8c0mXAFtv5D/mHyKe1+jmuP7PViuwqwuQ=
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=

View File

@ -1,6 +1,7 @@
package echo
import (
"net/http"
"path"
)
@ -29,47 +30,47 @@ func (g *Group) Use(middleware ...MiddlewareFunc) {
// CONNECT implements `Echo#CONNECT()` for sub-routes within the Group.
func (g *Group) CONNECT(path string, h HandlerFunc, m ...MiddlewareFunc) *Route {
return g.Add(CONNECT, path, h, m...)
return g.Add(http.MethodConnect, path, h, m...)
}
// DELETE implements `Echo#DELETE()` for sub-routes within the Group.
func (g *Group) DELETE(path string, h HandlerFunc, m ...MiddlewareFunc) *Route {
return g.Add(DELETE, path, h, m...)
return g.Add(http.MethodDelete, path, h, m...)
}
// GET implements `Echo#GET()` for sub-routes within the Group.
func (g *Group) GET(path string, h HandlerFunc, m ...MiddlewareFunc) *Route {
return g.Add(GET, path, h, m...)
return g.Add(http.MethodGet, path, h, m...)
}
// HEAD implements `Echo#HEAD()` for sub-routes within the Group.
func (g *Group) HEAD(path string, h HandlerFunc, m ...MiddlewareFunc) *Route {
return g.Add(HEAD, path, h, m...)
return g.Add(http.MethodHead, path, h, m...)
}
// OPTIONS implements `Echo#OPTIONS()` for sub-routes within the Group.
func (g *Group) OPTIONS(path string, h HandlerFunc, m ...MiddlewareFunc) *Route {
return g.Add(OPTIONS, path, h, m...)
return g.Add(http.MethodOptions, path, h, m...)
}
// PATCH implements `Echo#PATCH()` for sub-routes within the Group.
func (g *Group) PATCH(path string, h HandlerFunc, m ...MiddlewareFunc) *Route {
return g.Add(PATCH, path, h, m...)
return g.Add(http.MethodPatch, path, h, m...)
}
// POST implements `Echo#POST()` for sub-routes within the Group.
func (g *Group) POST(path string, h HandlerFunc, m ...MiddlewareFunc) *Route {
return g.Add(POST, path, h, m...)
return g.Add(http.MethodPost, path, h, m...)
}
// PUT implements `Echo#PUT()` for sub-routes within the Group.
func (g *Group) PUT(path string, h HandlerFunc, m ...MiddlewareFunc) *Route {
return g.Add(PUT, path, h, m...)
return g.Add(http.MethodPut, path, h, m...)
}
// TRACE implements `Echo#TRACE()` for sub-routes within the Group.
func (g *Group) TRACE(path string, h HandlerFunc, m ...MiddlewareFunc) *Route {
return g.Add(TRACE, path, h, m...)
return g.Add(http.MethodTrace, path, h, m...)
}
// Any implements `Echo#Any()` for sub-routes within the Group.

View File

@ -15,6 +15,7 @@ type (
SetPrefix(p string)
Level() log.Lvl
SetLevel(v log.Lvl)
SetHeader(h string)
Print(i ...interface{})
Printf(format string, args ...interface{})
Printj(j log.JSON)

View File

@ -5,7 +5,7 @@ import (
"strconv"
"strings"
"github.com/labstack/echo"
"github.com/labstack/echo/v4"
)
type (

View File

@ -8,7 +8,7 @@ import (
"net"
"net/http"
"github.com/labstack/echo"
"github.com/labstack/echo/v4"
)
type (
@ -105,7 +105,3 @@ func (w *bodyDumpResponseWriter) Flush() {
func (w *bodyDumpResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
return w.ResponseWriter.(http.Hijacker).Hijack()
}
func (w *bodyDumpResponseWriter) CloseNotify() <-chan bool {
return w.ResponseWriter.(http.CloseNotifier).CloseNotify()
}

View File

@ -5,7 +5,7 @@ import (
"io"
"sync"
"github.com/labstack/echo"
"github.com/labstack/echo/v4"
"github.com/labstack/gommon/bytes"
)

View File

@ -9,7 +9,7 @@ import (
"net/http"
"strings"
"github.com/labstack/echo"
"github.com/labstack/echo/v4"
)
type (
@ -116,7 +116,3 @@ func (w *gzipResponseWriter) Flush() {
func (w *gzipResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
return w.ResponseWriter.(http.Hijacker).Hijack()
}
func (w *gzipResponseWriter) CloseNotify() <-chan bool {
return w.ResponseWriter.(http.CloseNotifier).CloseNotify()
}

View File

@ -5,7 +5,7 @@ import (
"strconv"
"strings"
"github.com/labstack/echo"
"github.com/labstack/echo/v4"
)
type (
@ -24,7 +24,7 @@ type (
AllowMethods []string `yaml:"allow_methods"`
// AllowHeaders defines a list of request headers that can be used when
// making the actual request. This in response to a preflight request.
// making the actual request. This is in response to a preflight request.
// Optional. Default value []string{}.
AllowHeaders []string `yaml:"allow_headers"`
@ -52,7 +52,7 @@ var (
DefaultCORSConfig = CORSConfig{
Skipper: DefaultSkipper,
AllowOrigins: []string{"*"},
AllowMethods: []string{echo.GET, echo.HEAD, echo.PUT, echo.PATCH, echo.POST, echo.DELETE},
AllowMethods: []string{http.MethodGet, http.MethodHead, http.MethodPut, http.MethodPatch, http.MethodPost, http.MethodDelete},
}
)
@ -94,6 +94,10 @@ func CORSWithConfig(config CORSConfig) echo.MiddlewareFunc {
// Check allowed origins
for _, o := range config.AllowOrigins {
if o == "*" && config.AllowCredentials {
allowOrigin = origin
break
}
if o == "*" || o == origin {
allowOrigin = o
break
@ -101,7 +105,7 @@ func CORSWithConfig(config CORSConfig) echo.MiddlewareFunc {
}
// Simple request
if req.Method != echo.OPTIONS {
if req.Method != http.MethodOptions {
res.Header().Add(echo.HeaderVary, echo.HeaderOrigin)
res.Header().Set(echo.HeaderAccessControlAllowOrigin, allowOrigin)
if config.AllowCredentials {

View File

@ -7,7 +7,7 @@ import (
"strings"
"time"
"github.com/labstack/echo"
"github.com/labstack/echo/v4"
"github.com/labstack/gommon/random"
)
@ -135,7 +135,7 @@ func CSRFWithConfig(config CSRFConfig) echo.MiddlewareFunc {
}
switch req.Method {
case echo.GET, echo.HEAD, echo.OPTIONS, echo.TRACE:
case http.MethodGet, http.MethodHead, http.MethodOptions, http.MethodTrace:
default:
// Validate token only for requests which are not defined as 'safe' by RFC7231
clientToken, err := extractor(c)

View File

@ -7,7 +7,7 @@ import (
"strings"
"github.com/dgrijalva/jwt-go"
"github.com/labstack/echo"
"github.com/labstack/echo/v4"
)
type (
@ -16,6 +16,16 @@ type (
// Skipper defines a function to skip middleware.
Skipper Skipper
// BeforeFunc defines a function which is executed just before the middleware.
BeforeFunc BeforeFunc
// SuccessHandler defines a function which is executed for a valid token.
SuccessHandler JWTSuccessHandler
// ErrorHandler defines a function which is executed for an invalid token.
// It may be used to define a custom JWT error.
ErrorHandler JWTErrorHandler
// Signing key to validate token.
// Required.
SigningKey interface{}
@ -48,6 +58,12 @@ type (
keyFunc jwt.Keyfunc
}
// JWTSuccessHandler defines a function which is executed for a valid token.
JWTSuccessHandler func(echo.Context)
// JWTErrorHandler defines a function which is executed for an invalid token.
JWTErrorHandler func(error) error
jwtExtractor func(echo.Context) (string, error)
)
@ -59,7 +75,6 @@ const (
// Errors
var (
ErrJWTMissing = echo.NewHTTPError(http.StatusBadRequest, "missing or malformed jwt")
ErrJWTInvalid = echo.NewHTTPError(http.StatusUnauthorized, "invalid or expired jwt")
)
var (
@ -137,8 +152,15 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
return next(c)
}
if config.BeforeFunc != nil {
config.BeforeFunc(c)
}
auth, err := extractor(c)
if err != nil {
if config.ErrorHandler != nil {
return config.ErrorHandler(err)
}
return err
}
token := new(jwt.Token)
@ -153,11 +175,17 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
if err == nil && token.Valid {
// Store user information from token into context.
c.Set(config.ContextKey, token)
if config.SuccessHandler != nil {
config.SuccessHandler(c)
}
return next(c)
}
if config.ErrorHandler != nil {
return config.ErrorHandler(err)
}
return &echo.HTTPError{
Code: ErrJWTInvalid.Code,
Message: ErrJWTInvalid.Message,
Code: http.StatusUnauthorized,
Message: "invalid or expired jwt",
Internal: err,
}
}

View File

@ -5,7 +5,7 @@ import (
"net/http"
"strings"
"github.com/labstack/echo"
"github.com/labstack/echo/v4"
)
type (

View File

@ -9,7 +9,7 @@ import (
"sync"
"time"
"github.com/labstack/echo"
"github.com/labstack/echo/v4"
"github.com/labstack/gommon/color"
"github.com/valyala/fasttemplate"
)
@ -33,9 +33,11 @@ type (
// - host
// - method
// - path
// - protocol
// - referer
// - user_agent
// - status
// - error
// - latency (In nanoseconds)
// - latency_human (Human readable)
// - bytes_in (Bytes received)
@ -66,10 +68,10 @@ var (
// DefaultLoggerConfig is the default Logger middleware config.
DefaultLoggerConfig = LoggerConfig{
Skipper: DefaultSkipper,
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",
Format: `{"time":"${time_rfc3339_nano}","id":"${id}","remote_ip":"${remote_ip}",` +
`"host":"${host}","method":"${method}","uri":"${uri}","user_agent":"${user_agent}",` +
`"status":${status},"error":"${error}","latency":${latency},"latency_human":"${latency_human}"` +
`,"bytes_in":${bytes_in},"bytes_out":${bytes_out}}` + "\n",
CustomTimeFormat: "2006-01-02 15:04:05.00000",
Output: os.Stdout,
colorer: color.New(),
@ -153,6 +155,8 @@ func LoggerWithConfig(config LoggerConfig) echo.MiddlewareFunc {
p = "/"
}
return buf.WriteString(p)
case "protocol":
return buf.WriteString(req.Proto)
case "referer":
return buf.WriteString(req.Referer())
case "user_agent":
@ -169,6 +173,10 @@ func LoggerWithConfig(config LoggerConfig) echo.MiddlewareFunc {
s = config.colorer.Cyan(n)
}
return buf.WriteString(s)
case "error":
if err != nil {
return buf.WriteString(err.Error())
}
case "latency":
l := stop.Sub(start)
return buf.WriteString(strconv.FormatInt(int64(l), 10))

View File

@ -1,6 +1,10 @@
package middleware
import "github.com/labstack/echo"
import (
"net/http"
"github.com/labstack/echo/v4"
)
type (
// MethodOverrideConfig defines the config for MethodOverride middleware.
@ -52,7 +56,7 @@ func MethodOverrideWithConfig(config MethodOverrideConfig) echo.MiddlewareFunc {
}
req := c.Request()
if req.Method == echo.POST {
if req.Method == http.MethodPost {
m := config.Getter(c)
if m != "" {
req.Method = m

View File

@ -5,13 +5,16 @@ import (
"strconv"
"strings"
"github.com/labstack/echo"
"github.com/labstack/echo/v4"
)
type (
// Skipper defines a function to skip middleware. Returning true skips processing
// the middleware.
Skipper func(c echo.Context) bool
Skipper func(echo.Context) bool
// BeforeFunc defines a function which is executed just before the middleware.
BeforeFunc func(echo.Context)
)
func captureTokens(pattern *regexp.Regexp, input string) *strings.Replacer {

View File

@ -6,7 +6,6 @@ import (
"math/rand"
"net"
"net/http"
"net/http/httputil"
"net/url"
"regexp"
"strings"
@ -14,7 +13,7 @@ import (
"sync/atomic"
"time"
"github.com/labstack/echo"
"github.com/labstack/echo/v4"
)
// TODO: Handle TLS proxy
@ -38,6 +37,14 @@ type (
// "/users/*/orders/*": "/user/$1/order/$2",
Rewrite map[string]string
// Context key to store selected ProxyTarget into context.
// Optional. Default value "target".
ContextKey string
// To customize the transport to remote.
// Examples: If custom TLS certificates are required.
Transport http.RoundTripper
rewriteRegex map[*regexp.Regexp]string
}
@ -45,13 +52,14 @@ type (
ProxyTarget struct {
Name string
URL *url.URL
Meta echo.Map
}
// ProxyBalancer defines an interface to implement a load balancing technique.
ProxyBalancer interface {
AddTarget(*ProxyTarget) bool
RemoveTarget(string) bool
Next() *ProxyTarget
Next(echo.Context) *ProxyTarget
}
commonBalancer struct {
@ -75,14 +83,11 @@ type (
var (
// DefaultProxyConfig is the default Proxy middleware config.
DefaultProxyConfig = ProxyConfig{
Skipper: DefaultSkipper,
Skipper: DefaultSkipper,
ContextKey: "target",
}
)
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) {
in, _, err := c.Response().Hijack()
@ -164,7 +169,7 @@ func (b *commonBalancer) RemoveTarget(name string) bool {
}
// Next randomly returns an upstream target.
func (b *randomBalancer) Next() *ProxyTarget {
func (b *randomBalancer) Next(c echo.Context) *ProxyTarget {
if b.random == nil {
b.random = rand.New(rand.NewSource(int64(time.Now().Nanosecond())))
}
@ -174,7 +179,7 @@ func (b *randomBalancer) Next() *ProxyTarget {
}
// Next returns an upstream target using round-robin technique.
func (b *roundRobinBalancer) Next() *ProxyTarget {
func (b *roundRobinBalancer) Next(c echo.Context) *ProxyTarget {
b.i = b.i % uint32(len(b.targets))
t := b.targets[b.i]
atomic.AddUint32(&b.i, 1)
@ -216,7 +221,8 @@ func ProxyWithConfig(config ProxyConfig) echo.MiddlewareFunc {
req := c.Request()
res := c.Response()
tgt := config.Balancer.Next()
tgt := config.Balancer.Next(c)
c.Set(config.ContextKey, tgt)
// Rewrite
for k, v := range config.rewriteRegex {
@ -243,7 +249,7 @@ func ProxyWithConfig(config ProxyConfig) echo.MiddlewareFunc {
proxyRaw(tgt, c).ServeHTTP(res, req)
case req.Header.Get(echo.HeaderAccept) == "text/event-stream":
default:
proxyHTTP(tgt).ServeHTTP(res, req)
proxyHTTP(tgt, c, config).ServeHTTP(res, req)
}
return

View File

@ -0,0 +1,25 @@
// +build go1.11
package middleware
import (
"fmt"
"net/http"
"net/http/httputil"
"github.com/labstack/echo/v4"
)
func proxyHTTP(tgt *ProxyTarget, c echo.Context, config ProxyConfig) http.Handler {
proxy := httputil.NewSingleHostReverseProxy(tgt.URL)
proxy.ErrorHandler = func(resp http.ResponseWriter, req *http.Request, err error) {
desc := tgt.URL.String()
if tgt.Name != "" {
desc = fmt.Sprintf("%s(%s)", tgt.Name, tgt.URL.String())
}
c.Logger().Errorf("remote %s unreachable, could not forward: %v", desc, err)
c.Error(echo.NewHTTPError(http.StatusServiceUnavailable))
}
proxy.Transport = config.Transport
return proxy
}

View File

@ -0,0 +1,14 @@
// +build !go1.11
package middleware
import (
"net/http"
"net/http/httputil"
"github.com/labstack/echo/v4"
)
func proxyHTTP(t *ProxyTarget, c echo.Context, config ProxyConfig) http.Handler {
return httputil.NewSingleHostReverseProxy(t.URL)
}

View File

@ -4,7 +4,7 @@ import (
"fmt"
"runtime"
"github.com/labstack/echo"
"github.com/labstack/echo/v4"
)
type (

View File

@ -3,7 +3,7 @@ package middleware
import (
"net/http"
"github.com/labstack/echo"
"github.com/labstack/echo/v4"
)
// RedirectConfig defines the config for Redirect middleware.

View File

@ -1,7 +1,7 @@
package middleware
import (
"github.com/labstack/echo"
"github.com/labstack/echo/v4"
"github.com/labstack/gommon/random"
)

View File

@ -4,7 +4,7 @@ import (
"regexp"
"strings"
"github.com/labstack/echo"
"github.com/labstack/echo/v4"
)
type (
@ -57,7 +57,8 @@ func RewriteWithConfig(config RewriteConfig) echo.MiddlewareFunc {
// Initialize
for k, v := range config.Rules {
k = strings.Replace(k, "*", "(\\S*)", -1)
k = strings.Replace(k, "*", "(.*)", -1)
k = k + "$"
config.rulesRegex[regexp.MustCompile(k)] = v
}
@ -74,9 +75,9 @@ func RewriteWithConfig(config RewriteConfig) echo.MiddlewareFunc {
replacer := captureTokens(k, req.URL.Path)
if replacer != nil {
req.URL.Path = replacer.Replace(v)
break
}
}
return next(c)
}
}

View File

@ -3,7 +3,7 @@ package middleware
import (
"fmt"
"github.com/labstack/echo"
"github.com/labstack/echo/v4"
)
type (

View File

@ -1,7 +1,7 @@
package middleware
import (
"github.com/labstack/echo"
"github.com/labstack/echo/v4"
)
type (

View File

@ -10,7 +10,7 @@ import (
"path/filepath"
"strings"
"github.com/labstack/echo"
"github.com/labstack/echo/v4"
"github.com/labstack/gommon/bytes"
)
@ -76,7 +76,7 @@ const html = `
transition: opacity 0.25s;
}
li span {
color: #707070;
color: #707070;
font-size: 12px;
}
li a:hover {

View File

@ -91,15 +91,6 @@ func (r *Response) Hijack() (net.Conn, *bufio.ReadWriter, error) {
return r.Writer.(http.Hijacker).Hijack()
}
// CloseNotify implements the http.CloseNotifier interface to allow detecting
// when the underlying connection has gone away.
// This mechanism can be used to cancel long operations on the server if the
// client has disconnected before the response is ready.
// See [http.CloseNotifier](https://golang.org/pkg/net/http/#CloseNotifier)
func (r *Response) CloseNotify() <-chan bool {
return r.Writer.(http.CloseNotifier).CloseNotify()
}
func (r *Response) reset(w http.ResponseWriter) {
r.beforeFuncs = nil
r.afterFuncs = nil

View File

@ -1,5 +1,7 @@
package echo
import "net/http"
type (
// Router is the registry of all registered routes for an `Echo` instance for
// request matching and URL path parameter parsing.
@ -79,7 +81,7 @@ func (r *Router) Add(method, path string, h HandlerFunc) {
r.insert(method, path[:i], h, pkind, ppath, pnames)
return
}
r.insert(method, path[:i], nil, pkind, ppath, pnames)
r.insert(method, path[:i], nil, pkind, "", nil)
} else if path[i] == '*' {
r.insert(method, path[:i], nil, skind, "", nil)
pnames = append(pnames, "*")
@ -226,50 +228,50 @@ func (n *node) findChildByKind(t kind) *node {
func (n *node) addHandler(method string, h HandlerFunc) {
switch method {
case CONNECT:
case http.MethodConnect:
n.methodHandler.connect = h
case DELETE:
case http.MethodDelete:
n.methodHandler.delete = h
case GET:
case http.MethodGet:
n.methodHandler.get = h
case HEAD:
case http.MethodHead:
n.methodHandler.head = h
case OPTIONS:
case http.MethodOptions:
n.methodHandler.options = h
case PATCH:
case http.MethodPatch:
n.methodHandler.patch = h
case POST:
case http.MethodPost:
n.methodHandler.post = h
case PROPFIND:
n.methodHandler.propfind = h
case PUT:
case http.MethodPut:
n.methodHandler.put = h
case TRACE:
case http.MethodTrace:
n.methodHandler.trace = h
}
}
func (n *node) findHandler(method string) HandlerFunc {
switch method {
case CONNECT:
case http.MethodConnect:
return n.methodHandler.connect
case DELETE:
case http.MethodDelete:
return n.methodHandler.delete
case GET:
case http.MethodGet:
return n.methodHandler.get
case HEAD:
case http.MethodHead:
return n.methodHandler.head
case OPTIONS:
case http.MethodOptions:
return n.methodHandler.options
case PATCH:
case http.MethodPatch:
return n.methodHandler.patch
case POST:
case http.MethodPost:
return n.methodHandler.post
case PROPFIND:
return n.methodHandler.propfind
case PUT:
case http.MethodPut:
return n.methodHandler.put
case TRACE:
case http.MethodTrace:
return n.methodHandler.trace
default:
return nil
@ -311,7 +313,7 @@ func (r *Router) Find(method, path string, c Context) {
// Search order static > param > any
for {
if search == "" {
goto End
break
}
pl := 0 // Prefix length
@ -346,7 +348,7 @@ func (r *Router) Find(method, path string, c Context) {
}
if search == "" {
goto End
break
}
// Static node
@ -403,10 +405,9 @@ func (r *Router) Find(method, path string, c Context) {
return
}
pvalues[len(cn.pnames)-1] = search
goto End
break
}
End:
ctx.handler = cn.findHandler(method)
ctx.path = cn.ppath
ctx.pnames = cn.pnames

View File

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2015 labstack
Copyright (c) 2018 labstack
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -7,12 +7,12 @@ import (
)
type (
Bytes struct {
}
// Bytes struct
Bytes struct{}
)
const (
B = 1 << (10 * iota)
_ = 1.0 << (10 * iota) // ignore first value by assigning to blank identifier
KB
MB
GB
@ -22,7 +22,7 @@ const (
)
var (
pattern = regexp.MustCompile(`(?i)^(-?\d+)([KMGTP]B?|B)$`)
pattern = regexp.MustCompile(`(?i)^(-?\d+(?:\.\d+)?)([KMGTPE]B?|B?)$`)
global = New()
)
@ -38,29 +38,31 @@ func (*Bytes) Format(b int64) string {
value := float64(b)
switch {
case b < KB:
return strconv.FormatInt(b, 10) + "B"
case b < MB:
value /= KB
multiple = "KB"
case b < MB:
value /= KB
multiple = "KB"
case b < GB:
value /= MB
multiple = "MB"
case b < TB:
value /= GB
multiple = "GB"
case b < PB:
value /= TB
multiple = "TB"
case b < EB:
case b >= EB:
value /= EB
multiple = "EB"
case b >= PB:
value /= PB
multiple = "PB"
case b >= TB:
value /= TB
multiple = "TB"
case b >= GB:
value /= GB
multiple = "GB"
case b >= MB:
value /= MB
multiple = "MB"
case b >= KB:
value /= KB
multiple = "KB"
case b == 0:
return "0"
default:
return strconv.FormatInt(b, 10) + "B"
}
return fmt.Sprintf("%.02f%s", value, multiple)
return fmt.Sprintf("%.2f%s", value, multiple)
}
// Parse parses human readable bytes string to bytes integer.
@ -72,27 +74,27 @@ func (*Bytes) Parse(value string) (i int64, err error) {
}
bytesString := parts[1]
multiple := parts[2]
bytes, err := strconv.ParseInt(bytesString, 10, 64)
bytes, err := strconv.ParseFloat(bytesString, 64)
if err != nil {
return
}
switch multiple {
case "B":
return bytes * B, nil
default:
return int64(bytes), nil
case "K", "KB":
return bytes * KB, nil
return int64(bytes * KB), nil
case "M", "MB":
return bytes * MB, nil
return int64(bytes * MB), nil
case "G", "GB":
return bytes * GB, nil
return int64(bytes * GB), nil
case "T", "TB":
return bytes * TB, nil
return int64(bytes * TB), nil
case "P", "PB":
return bytes * PB, nil
return int64(bytes * PB), nil
case "E", "EB":
return int64(bytes * EB), nil
}
return
}
// Format wraps global Bytes's Format function.

View File

@ -8,11 +8,10 @@ import (
"os"
"path"
"runtime"
"strconv"
"sync"
"time"
"strconv"
"github.com/mattn/go-isatty"
"github.com/valyala/fasttemplate"
@ -23,6 +22,7 @@ type (
Logger struct {
prefix string
level Lvl
skip int
output io.Writer
template *fasttemplate.Template
levels []string
@ -42,6 +42,8 @@ const (
WARN
ERROR
OFF
panicLevel
fatalLevel
)
var (
@ -50,9 +52,14 @@ var (
`"file":"${short_file}","line":"${line}"}`
)
func init() {
global.skip = 3
}
func New(prefix string) (l *Logger) {
l = &Logger{
level: INFO,
skip: 2,
prefix: prefix,
template: l.newTemplate(defaultHeader),
color: color.New(),
@ -74,6 +81,9 @@ func (l *Logger) initLevels() {
l.color.Green("INFO"),
l.color.Yellow("WARN"),
l.color.Red("ERROR"),
"",
l.color.Yellow("PANIC", color.U),
l.color.Red("FATAL", color.U),
}
}
@ -188,32 +198,32 @@ func (l *Logger) Errorj(j JSON) {
}
func (l *Logger) Fatal(i ...interface{}) {
l.Print(i...)
l.log(fatalLevel, "", i...)
os.Exit(1)
}
func (l *Logger) Fatalf(format string, args ...interface{}) {
l.Printf(format, args...)
l.log(fatalLevel, format, args...)
os.Exit(1)
}
func (l *Logger) Fatalj(j JSON) {
l.Printj(j)
l.log(fatalLevel, "json", j)
os.Exit(1)
}
func (l *Logger) Panic(i ...interface{}) {
l.Print(i...)
l.log(panicLevel, "", i...)
panic(fmt.Sprint(i...))
}
func (l *Logger) Panicf(format string, args ...interface{}) {
l.Printf(format, args...)
panic(fmt.Sprintf(format, args))
l.log(panicLevel, format, args...)
panic(fmt.Sprintf(format, args...))
}
func (l *Logger) Panicj(j JSON) {
l.Printj(j)
l.log(panicLevel, "json", j)
panic(j)
}
@ -343,7 +353,7 @@ func (l *Logger) log(v Lvl, format string, args ...interface{}) {
buf := l.bufferPool.Get().(*bytes.Buffer)
buf.Reset()
defer l.bufferPool.Put(buf)
_, file, line, _ := runtime.Caller(3)
_, file, line, _ := runtime.Caller(l.skip)
if v >= l.level || v == 0 {
message := ""

View File

@ -13,13 +13,13 @@ type (
// Charsets
const (
Uppercase string = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Lowercase = "abcdefghijklmnopqrstuvwxyz"
Alphabetic = Uppercase + Lowercase
Numeric = "0123456789"
Alphanumeric = Alphabetic + Numeric
Symbols = "`" + `~!@#$%^&*()-_+={}[]|\;:"<>,./?`
Hex = Numeric + "abcdef"
Uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Lowercase = "abcdefghijklmnopqrstuvwxyz"
Alphabetic = Uppercase + Lowercase
Numeric = "0123456789"
Alphanumeric = Alphabetic + Numeric
Symbols = "`" + `~!@#$%^&*()-_+={}[]|\;:"<>,./?`
Hex = Numeric + "abcdef"
)
var (