1
0

Move the crudhandler to own repo (#27)

This commit is contained in:
konrad
2018-11-30 23:26:56 +00:00
committed by Gitea
parent d9304f6996
commit ce2cae9430
228 changed files with 13281 additions and 3292 deletions

View File

@ -1,9 +1,9 @@
y.output
# ignore intellij files
.idea
*.iml
*.ipr
*.iws
*.test
y.output
# ignore intellij files
.idea
*.iml
*.ipr
*.iws
*.test

View File

@ -1,18 +1,18 @@
TEST?=./...
default: test
fmt: generate
go fmt ./...
test: generate
go get -t ./...
go test $(TEST) $(TESTARGS)
generate:
go generate ./...
updatedeps:
go get -u golang.org/x/tools/cmd/stringer
.PHONY: default generate test updatedeps
TEST?=./...
default: test
fmt: generate
go fmt ./...
test: generate
go get -t ./...
go test $(TEST) $(TESTARGS)
generate:
go generate ./...
updatedeps:
go get -u golang.org/x/tools/cmd/stringer
.PHONY: default generate test updatedeps

View File

@ -2,7 +2,6 @@ language: go
go:
- 1.9.x
- 1.10.x
- 1.11.x
- tip
install:
- make dependency

View File

@ -2,113 +2,74 @@
[[projects]]
digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec"
name = "github.com/davecgh/go-spew"
packages = ["spew"]
pruneopts = "UT"
revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73"
version = "v1.1.1"
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
version = "v1.1.0"
[[projects]]
digest = "1:76dc72490af7174349349838f2fe118996381b31ea83243812a97e5a0fd5ed55"
name = "github.com/dgrijalva/jwt-go"
packages = ["."]
pruneopts = "UT"
revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e"
version = "v3.2.0"
[[projects]]
digest = "1:568171fc14a3d819b112c3e219d351ea7b05e8dad7935c4168c6b3373244a686"
name = "github.com/labstack/gommon"
packages = [
"bytes",
"color",
"log",
"random",
]
pruneopts = "UT"
revision = "2a618302b929cc20862dda3aa6f02f64dbe740dd"
version = "v0.2.7"
packages = ["bytes","color","log","random"]
revision = "6fe1405d73ec4bd4cd8a4ac8e2a2b2bf95d03954"
version = "0.2.4"
[[projects]]
digest = "1:c658e84ad3916da105a761660dcaeb01e63416c8ec7bc62256a9b411a05fcd67"
name = "github.com/mattn/go-colorable"
packages = ["."]
pruneopts = "UT"
revision = "167de6bfdfba052fa6b2d3664c8f5272e23c9072"
version = "v0.0.9"
[[projects]]
digest = "1:0981502f9816113c9c8c4ac301583841855c8cf4da8c72f696b3ebedf6d0e4e5"
name = "github.com/mattn/go-isatty"
packages = ["."]
pruneopts = "UT"
revision = "6ca4dbf54d38eea1a992b3c722a76a5d1c4cb25c"
version = "v0.0.4"
revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39"
version = "v0.0.3"
[[projects]]
digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe"
name = "github.com/pmezard/go-difflib"
packages = ["difflib"]
pruneopts = "UT"
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
version = "v1.0.0"
[[projects]]
digest = "1:18752d0b95816a1b777505a97f71c7467a8445b8ffb55631a7bf779f6ba4fa83"
name = "github.com/stretchr/testify"
packages = ["assert"]
pruneopts = "UT"
revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686"
version = "v1.2.2"
[[projects]]
digest = "1:c468422f334a6b46a19448ad59aaffdfc0a36b08fdcc1c749a0b29b6453d7e59"
name = "github.com/valyala/bytebufferpool"
packages = ["."]
pruneopts = "UT"
revision = "e746df99fe4a3986f4d4f79e13c1e0117ce9c2f7"
version = "v1.0.0"
revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71"
version = "v1.2.1"
[[projects]]
branch = "master"
name = "github.com/valyala/bytebufferpool"
packages = ["."]
revision = "e746df99fe4a3986f4d4f79e13c1e0117ce9c2f7"
[[projects]]
branch = "master"
digest = "1:268b8bce0064e8c057d7b913605459f9a26dcab864c0886a56d196540fbf003f"
name = "github.com/valyala/fasttemplate"
packages = ["."]
pruneopts = "UT"
revision = "dcecefd839c4193db0d35b88ec65b4c12d360ab0"
[[projects]]
branch = "master"
digest = "1:dedf20eb0d3e8d6aa8a4d3d2fae248222b688ed528201995e152cc497899123c"
name = "golang.org/x/crypto"
packages = [
"acme",
"acme/autocert",
]
pruneopts = "UT"
revision = "0e37d006457bf46f9e6692014ba72ef82c33022c"
packages = ["acme","acme/autocert"]
revision = "182114d582623c1caa54f73de9c7224e23a48487"
[[projects]]
branch = "master"
digest = "1:6eb2645d74b43d9c87b51947df39f7c668a4f422cd512053f7f6f75bfaad0197"
name = "golang.org/x/sys"
packages = ["unix"]
pruneopts = "UT"
revision = "d0be0721c37eeb5299f245a996a483160fc36940"
revision = "c28acc882ebcbfbe8ce9f0f14b9ac26ee138dd51"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
input-imports = [
"github.com/dgrijalva/jwt-go",
"github.com/labstack/gommon/bytes",
"github.com/labstack/gommon/color",
"github.com/labstack/gommon/log",
"github.com/labstack/gommon/random",
"github.com/stretchr/testify/assert",
"github.com/valyala/fasttemplate",
"golang.org/x/crypto/acme/autocert",
]
inputs-digest = "9c7b45e80fe353405800cf01f429b3a203cfb8d4468a04c64a908e11a98ea764"
solver-name = "gps-cdcl"
solver-version = 1

View File

@ -1,6 +1,7 @@
# Gopkg.toml example
#
# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
# 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"]
@ -16,13 +17,8 @@
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
#
# [prune]
# non-go = false
# go-tests = true
# unused-packages = true
# name = "github.com/x/y"
# version = "2.4.0"
[[constraint]]
@ -31,11 +27,11 @@
[[constraint]]
name = "github.com/labstack/gommon"
version = "0.2.7"
version = "0.2.4"
[[constraint]]
name = "github.com/stretchr/testify"
version = "1.2.2"
version = "1.2.1"
[[constraint]]
branch = "master"
@ -43,8 +39,4 @@
[[constraint]]
branch = "master"
name = "golang.org/x/crypto"
[prune]
go-tests = true
unused-packages = true
name = "golang.org/x/crypto"

View File

@ -32,7 +32,7 @@ Date: 2018/03/15<br>
Source: https://github.com/vishr/web-framework-benchmark<br>
Lower is better!
<img src="https://i.imgur.com/I32VdMJ.png">
<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">
## [Guide](https://echo.labstack.com/guide)

View File

@ -44,11 +44,12 @@ 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, field=%v, offset=%v", ute.Type, ute.Value, ute.Field, ute.Offset))
return NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Unmarshal type error: expected=%v, got=%v, offset=%v", ute.Type, ute.Value, ute.Offset))
} 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, err.Error())
}
case strings.HasPrefix(ctype, MIMEApplicationXML), strings.HasPrefix(ctype, MIMETextXML):
if err = xml.NewDecoder(req.Body).Decode(i); err != nil {
@ -56,8 +57,9 @@ func (b *DefaultBinder) Bind(i interface{}, c Context) (err error) {
return NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Unsupported type error: type=%v, error=%v", ute.Type, ute.Error()))
} 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, err.Error())
}
case strings.HasPrefix(ctype, MIMEApplicationForm), strings.HasPrefix(ctype, MIMEMultipartForm):
params, err := c.FormParams()
@ -94,29 +96,14 @@ 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 {
if err := b.bindData(structField.Addr().Interface(), data, tag); err != nil {
err := b.bindData(structField.Addr().Interface(), data, tag)
if 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
}
@ -139,9 +126,10 @@ 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

@ -103,7 +103,7 @@ type (
// MiddlewareFunc defines a function to process middleware.
MiddlewareFunc func(HandlerFunc) HandlerFunc
// HandlerFunc defines a function to serve HTTP requests.
// HandlerFunc defines a function to server HTTP requests.
HandlerFunc func(Context) error
// HTTPErrorHandler is a centralized HTTP error handler.
@ -217,7 +217,7 @@ const (
)
const (
Version = "3.3.6"
Version = "3.3.5"
website = "https://echo.labstack.com"
// http://patorjk.com/software/taag/#p=display&f=Small%20Slant&t=Echo
banner = `
@ -326,7 +326,7 @@ func (e *Echo) DefaultHTTPErrorHandler(err error, c Context) {
code = he.Code
msg = he.Message
if he.Internal != nil {
err = fmt.Errorf("%v, %v", err, he.Internal)
msg = fmt.Sprintf("%v, %v", err, he.Internal)
}
} else if e.Debug {
msg = err.Error()
@ -337,6 +337,8 @@ 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
@ -460,11 +462,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 with optional route-level middleware.
func (e *Echo) File(path, file string, m ...MiddlewareFunc) *Route {
// File registers a new route with path to serve a static file.
func (e *Echo) File(path, file string) *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
@ -557,17 +559,26 @@ 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 {
e.router.Find(r.Method, getPath(r), c)
path := r.URL.RawPath
if path == "" {
path = r.URL.Path
}
e.router.Find(m, 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 {
e.router.Find(r.Method, getPath(r), c)
path := r.URL.RawPath
if path == "" {
path = r.URL.Path
}
e.router.Find(m, getPath(r), c)
h := c.Handler()
for i := len(e.middleware) - 1; i >= 0; i-- {
h = e.middleware[i](h)

View File

@ -1,15 +0,0 @@
module github.com/labstack/echo
require (
github.com/davecgh/go-spew v1.1.0 // indirect
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/labstack/gommon v0.0.0-20180312174116-6fe1405d73ec
github.com/mattn/go-colorable v0.0.9 // indirect
github.com/mattn/go-isatty v0.0.3 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/testify v1.2.1
github.com/valyala/bytebufferpool v0.0.0-20160817181652-e746df99fe4a // indirect
github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4
golang.org/x/crypto v0.0.0-20180312195533-182114d58262
golang.org/x/sys v0.0.0-20180312081825-c28acc882ebc // indirect
)

View File

@ -1,22 +0,0 @@
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.0.0-20180312174116-6fe1405d73ec h1:aYKwS4iCpqxskMuvI8+Byq0CxnnWHO/xuLk2pZJ96tY=
github.com/labstack/gommon v0.0.0-20180312174116-6fe1405d73ec/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.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI=
github.com/mattn/go-isatty v0.0.3/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/testify v1.2.1 h1:52QO5WkIUcHGIR7EnGagH88x1bUzqGXTC5/1bDTUQ7U=
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/valyala/bytebufferpool v0.0.0-20160817181652-e746df99fe4a h1:AOcehBWpFhYPYw0ioDTppQzgI8pAAahVCiMSKTp9rbo=
github.com/valyala/bytebufferpool v0.0.0-20160817181652-e746df99fe4a/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-20180312195533-182114d58262 h1:1NLVUmR8SQ7cNNA5Vo7ronpXbR+5A+9IwIC/bLE7D8Y=
golang.org/x/crypto v0.0.0-20180312195533-182114d58262/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/sys v0.0.0-20180312081825-c28acc882ebc h1:eCzBKjjvhDDXMoH5l7eA+YK1PEtyJ2QLj3f4IArr+zg=
golang.org/x/sys v0.0.0-20180312081825-c28acc882ebc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=

View File

@ -94,10 +94,6 @@ 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

View File

@ -16,16 +16,6 @@ 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{}
@ -58,12 +48,6 @@ 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)
)
@ -75,6 +59,7 @@ const (
// Errors
var (
ErrJWTMissing = echo.NewHTTPError(http.StatusBadRequest, "missing or malformed jwt")
ErrJWTInvalid = echo.NewHTTPError(http.StatusUnauthorized, "invalid or expired jwt")
)
var (
@ -152,15 +137,8 @@ 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)
@ -175,17 +153,11 @@ 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: http.StatusUnauthorized,
Message: "invalid or expired jwt",
Code: ErrJWTInvalid.Code,
Message: ErrJWTInvalid.Message,
Internal: err,
}
}

View File

@ -33,11 +33,9 @@ type (
// - host
// - method
// - path
// - protocol
// - referer
// - user_agent
// - status
// - error
// - latency (In nanoseconds)
// - latency_human (Human readable)
// - bytes_in (Bytes received)
@ -69,7 +67,7 @@ var (
DefaultLoggerConfig = LoggerConfig{
Skipper: DefaultSkipper,
Format: `{"time":"${time_rfc3339_nano}","id":"${id}","remote_ip":"${remote_ip}","host":"${host}",` +
`"method":"${method}","uri":"${uri}","status":${status},"error":"${error}","latency":${latency},` +
`"method":"${method}","uri":"${uri}","status":${status}, "latency":${latency},` +
`"latency_human":"${latency_human}","bytes_in":${bytes_in},` +
`"bytes_out":${bytes_out}}` + "\n",
CustomTimeFormat: "2006-01-02 15:04:05.00000",
@ -155,8 +153,6 @@ 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":
@ -173,10 +169,6 @@ 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

@ -11,10 +11,7 @@ import (
type (
// Skipper defines a function to skip middleware. Returning true skips processing
// the middleware.
Skipper func(echo.Context) bool
// BeforeFunc defines a function which is executed just before the middleware.
BeforeFunc func(echo.Context)
Skipper func(c echo.Context) bool
)
func captureTokens(pattern *regexp.Regexp, input string) *strings.Replacer {

View File

@ -57,8 +57,7 @@ func RewriteWithConfig(config RewriteConfig) echo.MiddlewareFunc {
// Initialize
for k, v := range config.Rules {
k = strings.Replace(k, "*", "(.*)", -1)
k = k + "$"
k = strings.Replace(k, "*", "(\\S*)", -1)
config.rulesRegex[regexp.MustCompile(k)] = v
}
@ -75,9 +74,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

@ -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

@ -22,6 +22,7 @@ type (
Logger struct {
prefix string
level Lvl
skip int
output io.Writer
template *fasttemplate.Template
levels []string
@ -41,6 +42,8 @@ const (
WARN
ERROR
OFF
panicLevel
fatalLevel
)
var (
@ -49,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(),
@ -73,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),
}
}
@ -187,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)
}
@ -342,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(2)
_, file, line, _ := runtime.Caller(l.skip)
if v >= l.level || v == 0 {
message := ""

View File

@ -2,6 +2,10 @@ language: go
go:
- tip
os:
- linux
- osx
before_install:
- go get github.com/mattn/goveralls
- go get golang.org/x/tools/cmd/cover

View File

@ -3,7 +3,7 @@
package isatty
// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
// terminal. This is also always false on this environment.
func IsCygwinTerminal(fd uintptr) bool {
return false

19
vendor/github.com/op/go-logging/CHANGELOG.md generated vendored Normal file
View File

@ -0,0 +1,19 @@
# Changelog
## 2.0.0-rc1 (2016-02-11)
Time flies and it has been three years since this package was first released.
There have been a couple of API changes I have wanted to do for some time but
I've tried to maintain backwards compatibility. Some inconsistencies in the
API have started to show, proper vendor support in Go out of the box and
the fact that `go vet` will give warnings -- I have decided to bump the major
version.
* Make eg. `Info` and `Infof` do different things. You want to change all calls
to `Info` with a string format go to `Infof` etc. In many cases, `go vet` will
guide you.
* `Id` in `Record` is now called `ID`
## 1.0.0 (2013-02-21)
Initial release

View File

@ -7,6 +7,10 @@ is customizable and supports different logging backends like syslog, file and
memory. Multiple backends can be utilized with different log levels per backend
and logger.
**_NOTE:_** backwards compatibility promise have been dropped for master. Please
vendor this package or use `gopkg.in/op/go-logging.v1` for previous version. See
[changelog](CHANGELOG.md) for details.
## Example
Let's have a look at an [example](examples/example.go) which demonstrates most
@ -86,4 +90,4 @@ For docs, see http://godoc.org/github.com/op/go-logging or run:
## Additional resources
* [wslog](https://godoc.org/github.com/cryptix/go/logging/wslog) -- exposes log messages through a WebSocket.
* [wslog](https://godoc.org/github.com/cryptix/exp/wslog) -- exposes log messages through a WebSocket.

View File

@ -14,6 +14,7 @@ import (
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
"sync"
"time"
@ -81,7 +82,7 @@ var defaultVerbsLayout = []string{
"s",
"s",
"s",
"s",
"0",
"",
}
@ -162,7 +163,7 @@ type stringFormatter struct {
// %{message} Message (string)
// %{longfile} Full file name and line number: /a/b/c/d.go:23
// %{shortfile} Final file name element and line number: d.go:23
// %{callpath} Callpath like main.a.b.c...c "..." meaning recursive call
// %{callpath} Callpath like main.a.b.c...c "..." meaning recursive call ~. meaning truncated path
// %{color} ANSI color based on log level
//
// For normal types, the output can be customized by using the 'verbs' defined
@ -179,6 +180,9 @@ type stringFormatter struct {
// "%{color:bold}%{time:15:04:05} %{level:-8s}%{color:reset} %{message}" will
// just colorize the time and level, leaving the message uncolored.
//
// For the 'callpath' verb, the output can be adjusted to limit the printing
// the stack depth. i.e. '%{callpath:3}' will print '~.a.b.c'
//
// Colors on Windows is unfortunately not supported right now and is currently
// a no-op.
//
@ -216,12 +220,12 @@ func NewStringFormatter(format string) (Formatter, error) {
}
// Handle layout customizations or use the default. If this is not for the
// time or color formatting, we need to prefix with %.
// time, color formatting or callpath, we need to prefix with %.
layout := defaultVerbsLayout[verb]
if m[4] != -1 {
layout = format[m[4]:m[5]]
}
if verb != fmtVerbTime && verb != fmtVerbLevelColor {
if verb != fmtVerbTime && verb != fmtVerbLevelColor && verb != fmtVerbCallpath {
layout = "%" + layout
}
@ -238,12 +242,13 @@ func NewStringFormatter(format string) (Formatter, error) {
if err != nil {
panic(err)
}
testFmt := "hello %s"
r := &Record{
Id: 12345,
ID: 12345,
Time: t,
Module: "logger",
Args: []interface{}{"go"},
fmt: "hello %s",
fmt: &testFmt,
}
if err := fmter.Format(0, r, &bytes.Buffer{}); err != nil {
return nil, err
@ -274,6 +279,12 @@ func (f *stringFormatter) Format(calldepth int, r *Record, output io.Writer) err
output.Write([]byte(r.Time.Format(part.layout)))
} else if part.verb == fmtVerbLevelColor {
doFmtVerbLevelColor(part.layout, r.Level, output)
} else if part.verb == fmtVerbCallpath {
depth, err := strconv.Atoi(part.layout)
if err != nil {
depth = 0
}
output.Write([]byte(formatCallpath(calldepth+1, depth)))
} else {
var v interface{}
switch part.verb {
@ -281,7 +292,7 @@ func (f *stringFormatter) Format(calldepth int, r *Record, output io.Writer) err
v = r.Level
break
case fmtVerbID:
v = r.Id
v = r.ID
break
case fmtVerbPid:
v = pid
@ -313,8 +324,6 @@ func (f *stringFormatter) Format(calldepth int, r *Record, output io.Writer) err
v = formatFuncName(part.verb, f.Name())
}
}
case fmtVerbCallpath:
v = formatCallpath(calldepth + 1)
default:
panic("unhandled format part")
}
@ -350,14 +359,19 @@ func formatFuncName(v fmtVerb, f string) string {
panic("unexpected func formatter")
}
func formatCallpath(calldepth int) string {
func formatCallpath(calldepth int, depth int) string {
v := ""
callers := make([]uintptr, 64)
n := runtime.Callers(calldepth+2, callers)
oldPc := callers[n-1]
start := n - 3
if depth > 0 && start >= depth {
start = depth - 1
v += "~."
}
recursiveCall := false
for i := n - 3; i >= 0; i-- {
for i := start; i >= 0; i-- {
pc := callers[i]
if oldPc == pc {
recursiveCall = true
@ -368,7 +382,7 @@ func formatCallpath(calldepth int) string {
recursiveCall = false
v += ".."
}
if i < n-3 {
if i < start {
v += "."
}
if f := runtime.FuncForPC(pc); f != nil {

View File

@ -41,7 +41,7 @@ var (
// was created, an increasing id, filename and line and finally the actual
// formatted log line.
type Record struct {
Id uint64
ID uint64
Time time.Time
Module string
Level Level
@ -50,7 +50,7 @@ type Record struct {
// message is kept as a pointer to have shallow copies update this once
// needed.
message *string
fmt string
fmt *string
formatter Formatter
formatted string
}
@ -74,7 +74,15 @@ func (r *Record) Message() string {
r.Args[i] = redactor.Redacted()
}
}
msg := fmt.Sprintf(r.fmt, r.Args...)
var buf bytes.Buffer
if r.fmt != nil {
fmt.Fprintf(&buf, *r.fmt, r.Args...)
} else {
// use Fprintln to make sure we always get space between arguments
fmt.Fprintln(&buf, r.Args...)
buf.Truncate(buf.Len() - 1) // strip newline
}
msg := buf.String()
r.message = &msg
}
return *r.message
@ -132,14 +140,14 @@ func (l *Logger) IsEnabledFor(level Level) bool {
return defaultBackend.IsEnabledFor(level, l.Module)
}
func (l *Logger) log(lvl Level, format string, args ...interface{}) {
func (l *Logger) log(lvl Level, format *string, args ...interface{}) {
if !l.IsEnabledFor(lvl) {
return
}
// Create the logging record and pass it in to the backend
record := &Record{
Id: atomic.AddUint64(&sequenceNo, 1),
ID: atomic.AddUint64(&sequenceNo, 1),
Time: timeNow(),
Module: l.Module,
Level: lvl,
@ -164,84 +172,86 @@ func (l *Logger) log(lvl Level, format string, args ...interface{}) {
// Fatal is equivalent to l.Critical(fmt.Sprint()) followed by a call to os.Exit(1).
func (l *Logger) Fatal(args ...interface{}) {
s := fmt.Sprint(args...)
l.log(CRITICAL, "%s", s)
l.log(CRITICAL, nil, args...)
os.Exit(1)
}
// Fatalf is equivalent to l.Critical followed by a call to os.Exit(1).
func (l *Logger) Fatalf(format string, args ...interface{}) {
l.log(CRITICAL, format, args...)
l.log(CRITICAL, &format, args...)
os.Exit(1)
}
// Panic is equivalent to l.Critical(fmt.Sprint()) followed by a call to panic().
func (l *Logger) Panic(args ...interface{}) {
s := fmt.Sprint(args...)
l.log(CRITICAL, "%s", s)
panic(s)
l.log(CRITICAL, nil, args...)
panic(fmt.Sprint(args...))
}
// Panicf is equivalent to l.Critical followed by a call to panic().
func (l *Logger) Panicf(format string, args ...interface{}) {
s := fmt.Sprintf(format, args...)
l.log(CRITICAL, "%s", s)
panic(s)
l.log(CRITICAL, &format, args...)
panic(fmt.Sprintf(format, args...))
}
// Critical logs a message using CRITICAL as log level.
func (l *Logger) Critical(format string, args ...interface{}) {
l.log(CRITICAL, format, args...)
func (l *Logger) Critical(args ...interface{}) {
l.log(CRITICAL, nil, args...)
}
// Criticalf logs a message using CRITICAL as log level.
func (l *Logger) Criticalf(format string, args ...interface{}) {
l.log(CRITICAL, &format, args...)
}
// Error logs a message using ERROR as log level.
func (l *Logger) Error(format string, args ...interface{}) {
l.log(ERROR, format, args...)
func (l *Logger) Error(args ...interface{}) {
l.log(ERROR, nil, args...)
}
// Errorf logs a message using ERROR as log level.
func (l *Logger) Errorf(format string, args ...interface{}) {
l.log(ERROR, format, args...)
l.log(ERROR, &format, args...)
}
// Warning logs a message using WARNING as log level.
func (l *Logger) Warning(format string, args ...interface{}) {
l.log(WARNING, format, args...)
func (l *Logger) Warning(args ...interface{}) {
l.log(WARNING, nil, args...)
}
// Warningf logs a message using WARNING as log level.
func (l *Logger) Warningf(format string, args ...interface{}) {
l.log(WARNING, format, args...)
l.log(WARNING, &format, args...)
}
// Notice logs a message using NOTICE as log level.
func (l *Logger) Notice(format string, args ...interface{}) {
l.log(NOTICE, format, args...)
func (l *Logger) Notice(args ...interface{}) {
l.log(NOTICE, nil, args...)
}
// Noticef logs a message using NOTICE as log level.
func (l *Logger) Noticef(format string, args ...interface{}) {
l.log(NOTICE, format, args...)
l.log(NOTICE, &format, args...)
}
// Info logs a message using INFO as log level.
func (l *Logger) Info(format string, args ...interface{}) {
l.log(INFO, format, args...)
func (l *Logger) Info(args ...interface{}) {
l.log(INFO, nil, args...)
}
// Infof logs a message using INFO as log level.
func (l *Logger) Infof(format string, args ...interface{}) {
l.log(INFO, format, args...)
l.log(INFO, &format, args...)
}
// Debug logs a message using DEBUG as log level.
func (l *Logger) Debug(format string, args ...interface{}) {
l.log(DEBUG, format, args...)
func (l *Logger) Debug(args ...interface{}) {
l.log(DEBUG, nil, args...)
}
// Debugf logs a message using DEBUG as log level.
func (l *Logger) Debugf(format string, args ...interface{}) {
l.log(DEBUG, format, args...)
l.log(DEBUG, &format, args...)
}
func init() {

View File

@ -1,29 +1,29 @@
# This is a TOML document. Boom.
title = "TOML Example"
[owner]
name = "Tom Preston-Werner"
organization = "GitHub"
bio = "GitHub Cofounder & CEO\nLikes tater tots and beer."
dob = 1979-05-27T07:32:00Z # First class dates? Why not?
[database]
server = "192.168.1.1"
ports = [ 8001, 8001, 8002 ]
connection_max = 5000
enabled = true
[servers]
# You can indent as you please. Tabs or spaces. TOML don't care.
[servers.alpha]
ip = "10.0.0.1"
dc = "eqdc10"
[servers.beta]
ip = "10.0.0.2"
dc = "eqdc10"
[clients]
data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it
# This is a TOML document. Boom.
title = "TOML Example"
[owner]
name = "Tom Preston-Werner"
organization = "GitHub"
bio = "GitHub Cofounder & CEO\nLikes tater tots and beer."
dob = 1979-05-27T07:32:00Z # First class dates? Why not?
[database]
server = "192.168.1.1"
ports = [ 8001, 8001, 8002 ]
connection_max = 5000
enabled = true
[servers]
# You can indent as you please. Tabs or spaces. TOML don't care.
[servers.alpha]
ip = "10.0.0.1"
dc = "eqdc10"
[servers.beta]
ip = "10.0.0.2"
dc = "eqdc10"
[clients]
data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it

View File

@ -1,21 +1,21 @@
sudo: false
language: go
go:
- 1.9
- "1.10"
- tip
os:
- linux
- osx
matrix:
allow_failures:
- go: tip
fast_finish: true
script:
- go build
- go test -race -v ./...
sudo: false
language: go
go:
- 1.9
- "1.10"
- tip
os:
- linux
- osx
matrix:
allow_failures:
- go: tip
fast_finish: true
script:
- go build
- go test -race -v ./...