feat: uses alice to better readability of the chained handlers and adds access logging again
This commit is contained in:
parent
fc1a89088a
commit
21b64e658e
1
go.mod
1
go.mod
@ -5,6 +5,7 @@ go 1.15
|
|||||||
require (
|
require (
|
||||||
github.com/golangci/golangci-lint v1.43.0
|
github.com/golangci/golangci-lint v1.43.0
|
||||||
github.com/goreleaser/goreleaser v1.3.0
|
github.com/goreleaser/goreleaser v1.3.0
|
||||||
|
github.com/justinas/alice v1.2.0
|
||||||
github.com/rs/zerolog v1.20.0
|
github.com/rs/zerolog v1.20.0
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
)
|
)
|
||||||
|
2
go.sum
2
go.sum
@ -785,6 +785,8 @@ github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSg
|
|||||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
github.com/julz/importas v0.0.0-20210419104244-841f0c0fe66d h1:XeSMXURZPtUffuWAaq90o6kLgZdgu+QA8wk4MPC8ikI=
|
github.com/julz/importas v0.0.0-20210419104244-841f0c0fe66d h1:XeSMXURZPtUffuWAaq90o6kLgZdgu+QA8wk4MPC8ikI=
|
||||||
github.com/julz/importas v0.0.0-20210419104244-841f0c0fe66d/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0=
|
github.com/julz/importas v0.0.0-20210419104244-841f0c0fe66d/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0=
|
||||||
|
github.com/justinas/alice v1.2.0 h1:+MHSA/vccVCF4Uq37S42jwlkvI2Xzl7zTPCN5BnZNVo=
|
||||||
|
github.com/justinas/alice v1.2.0/go.mod h1:fN5HRH/reO/zrUflLfTN43t3vXvKzvZIENsNEe7i7qA=
|
||||||
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
|
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
|
||||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||||
|
@ -4,7 +4,9 @@ package logginghandler
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/justinas/alice"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"github.com/rs/zerolog/hlog"
|
"github.com/rs/zerolog/hlog"
|
||||||
)
|
)
|
||||||
@ -24,23 +26,26 @@ func Logger(r *http.Request) zerolog.Logger {
|
|||||||
return *hlog.FromRequest(r)
|
return *hlog.FromRequest(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler sets up all the logging.
|
func Handler(log zerolog.Logger) func(http.Handler) http.Handler {
|
||||||
func Handler(logger zerolog.Logger) func(http.Handler) http.Handler {
|
|
||||||
return func(next http.Handler) http.Handler {
|
return func(next http.Handler) http.Handler {
|
||||||
return hlog.NewHandler(logger)(
|
chain := alice.New(
|
||||||
hlog.RemoteAddrHandler("remote")(
|
hlog.NewHandler(log),
|
||||||
hlog.UserAgentHandler("user-agent")(
|
hlog.AccessHandler(func(r *http.Request, status, size int, duration time.Duration) {
|
||||||
hlog.RefererHandler("referer")(
|
hlog.FromRequest(r).Info().
|
||||||
hlog.MethodHandler("method")(
|
Str("method", r.Method).
|
||||||
hlog.RequestIDHandler("uuid", "X-Request-ID")(
|
Str("proto", r.Proto).
|
||||||
hlog.URLHandler("request-url")(
|
Stringer("request-url", r.URL).
|
||||||
next,
|
Int("status", status).
|
||||||
),
|
Int("size", size).
|
||||||
),
|
Dur("duration", duration).
|
||||||
),
|
Msg("")
|
||||||
),
|
}),
|
||||||
),
|
hlog.RemoteAddrHandler("remote"),
|
||||||
),
|
hlog.UserAgentHandler("user-agent"),
|
||||||
)
|
hlog.RefererHandler("referer"),
|
||||||
|
hlog.RequestIDHandler("uuid", "X-Request-ID"),
|
||||||
|
).Then(next)
|
||||||
|
|
||||||
|
return chain
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
19
vendor/github.com/justinas/alice/.travis.yml
generated
vendored
Normal file
19
vendor/github.com/justinas/alice/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
language: go
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- go: 1.2.x
|
||||||
|
- go: 1.3.x
|
||||||
|
- go: 1.4.x
|
||||||
|
- go: 1.5.x
|
||||||
|
- go: 1.6.x
|
||||||
|
- go: 1.7.x
|
||||||
|
- go: 1.8.x
|
||||||
|
- go: 1.9.x
|
||||||
|
- go: 1.10.x
|
||||||
|
- go: 1.11.x
|
||||||
|
- go: 1.12.x
|
||||||
|
- go: 1.13.x
|
||||||
|
- go: tip
|
||||||
|
allow_failures:
|
||||||
|
- go: tip
|
20
vendor/github.com/justinas/alice/LICENSE
generated
vendored
Normal file
20
vendor/github.com/justinas/alice/LICENSE
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 Justinas Stankevicius
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
98
vendor/github.com/justinas/alice/README.md
generated
vendored
Normal file
98
vendor/github.com/justinas/alice/README.md
generated
vendored
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
# Alice
|
||||||
|
|
||||||
|
[![GoDoc](https://godoc.org/github.com/golang/gddo?status.svg)](http://godoc.org/github.com/justinas/alice)
|
||||||
|
[![Build Status](https://travis-ci.org/justinas/alice.svg?branch=master)](https://travis-ci.org/justinas/alice)
|
||||||
|
[![Coverage](http://gocover.io/_badge/github.com/justinas/alice)](http://gocover.io/github.com/justinas/alice)
|
||||||
|
|
||||||
|
Alice provides a convenient way to chain
|
||||||
|
your HTTP middleware functions and the app handler.
|
||||||
|
|
||||||
|
In short, it transforms
|
||||||
|
|
||||||
|
```go
|
||||||
|
Middleware1(Middleware2(Middleware3(App)))
|
||||||
|
```
|
||||||
|
|
||||||
|
to
|
||||||
|
|
||||||
|
```go
|
||||||
|
alice.New(Middleware1, Middleware2, Middleware3).Then(App)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Why?
|
||||||
|
|
||||||
|
None of the other middleware chaining solutions
|
||||||
|
behaves exactly like Alice.
|
||||||
|
Alice is as minimal as it gets:
|
||||||
|
in essence, it's just a for loop that does the wrapping for you.
|
||||||
|
|
||||||
|
Check out [this blog post](http://justinas.org/alice-painless-middleware-chaining-for-go/)
|
||||||
|
for explanation how Alice is different from other chaining solutions.
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
Your middleware constructors should have the form of
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (http.Handler) http.Handler
|
||||||
|
```
|
||||||
|
|
||||||
|
Some middleware provide this out of the box.
|
||||||
|
For ones that don't, it's trivial to write one yourself.
|
||||||
|
|
||||||
|
```go
|
||||||
|
func myStripPrefix(h http.Handler) http.Handler {
|
||||||
|
return http.StripPrefix("/old", h)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This complete example shows the full power of Alice.
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/throttled/throttled"
|
||||||
|
"github.com/justinas/alice"
|
||||||
|
"github.com/justinas/nosurf"
|
||||||
|
)
|
||||||
|
|
||||||
|
func timeoutHandler(h http.Handler) http.Handler {
|
||||||
|
return http.TimeoutHandler(h, 1*time.Second, "timed out")
|
||||||
|
}
|
||||||
|
|
||||||
|
func myApp(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Write([]byte("Hello world!"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
th := throttled.Interval(throttled.PerSec(10), 1, &throttled.VaryBy{Path: true}, 50)
|
||||||
|
myHandler := http.HandlerFunc(myApp)
|
||||||
|
|
||||||
|
chain := alice.New(th.Throttle, timeoutHandler, nosurf.NewPure).Then(myHandler)
|
||||||
|
http.ListenAndServe(":8000", chain)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Here, the request will pass [throttled](https://github.com/PuerkitoBio/throttled) first,
|
||||||
|
then an http.TimeoutHandler we've set up,
|
||||||
|
then [nosurf](https://github.com/justinas/nosurf)
|
||||||
|
and will finally reach our handler.
|
||||||
|
|
||||||
|
Note that Alice makes **no guarantees** for
|
||||||
|
how one or another piece of middleware will behave.
|
||||||
|
Once it passes the execution to the outer layer of middleware,
|
||||||
|
it has no saying in whether middleware will execute the inner handlers.
|
||||||
|
This is intentional behavior.
|
||||||
|
|
||||||
|
Alice works with Go 1.0 and higher.
|
||||||
|
|
||||||
|
### Contributing
|
||||||
|
|
||||||
|
0. Find an issue that bugs you / open a new one.
|
||||||
|
1. Discuss.
|
||||||
|
2. Branch off, commit, test.
|
||||||
|
3. Make a pull request / attach the commits to the issue.
|
112
vendor/github.com/justinas/alice/chain.go
generated
vendored
Normal file
112
vendor/github.com/justinas/alice/chain.go
generated
vendored
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
// Package alice provides a convenient way to chain http handlers.
|
||||||
|
package alice
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
// A constructor for a piece of middleware.
|
||||||
|
// Some middleware use this constructor out of the box,
|
||||||
|
// so in most cases you can just pass somepackage.New
|
||||||
|
type Constructor func(http.Handler) http.Handler
|
||||||
|
|
||||||
|
// Chain acts as a list of http.Handler constructors.
|
||||||
|
// Chain is effectively immutable:
|
||||||
|
// once created, it will always hold
|
||||||
|
// the same set of constructors in the same order.
|
||||||
|
type Chain struct {
|
||||||
|
constructors []Constructor
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new chain,
|
||||||
|
// memorizing the given list of middleware constructors.
|
||||||
|
// New serves no other function,
|
||||||
|
// constructors are only called upon a call to Then().
|
||||||
|
func New(constructors ...Constructor) Chain {
|
||||||
|
return Chain{append(([]Constructor)(nil), constructors...)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then chains the middleware and returns the final http.Handler.
|
||||||
|
// New(m1, m2, m3).Then(h)
|
||||||
|
// is equivalent to:
|
||||||
|
// m1(m2(m3(h)))
|
||||||
|
// When the request comes in, it will be passed to m1, then m2, then m3
|
||||||
|
// and finally, the given handler
|
||||||
|
// (assuming every middleware calls the following one).
|
||||||
|
//
|
||||||
|
// A chain can be safely reused by calling Then() several times.
|
||||||
|
// stdStack := alice.New(ratelimitHandler, csrfHandler)
|
||||||
|
// indexPipe = stdStack.Then(indexHandler)
|
||||||
|
// authPipe = stdStack.Then(authHandler)
|
||||||
|
// Note that constructors are called on every call to Then()
|
||||||
|
// and thus several instances of the same middleware will be created
|
||||||
|
// when a chain is reused in this way.
|
||||||
|
// For proper middleware, this should cause no problems.
|
||||||
|
//
|
||||||
|
// Then() treats nil as http.DefaultServeMux.
|
||||||
|
func (c Chain) Then(h http.Handler) http.Handler {
|
||||||
|
if h == nil {
|
||||||
|
h = http.DefaultServeMux
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range c.constructors {
|
||||||
|
h = c.constructors[len(c.constructors)-1-i](h)
|
||||||
|
}
|
||||||
|
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
// ThenFunc works identically to Then, but takes
|
||||||
|
// a HandlerFunc instead of a Handler.
|
||||||
|
//
|
||||||
|
// The following two statements are equivalent:
|
||||||
|
// c.Then(http.HandlerFunc(fn))
|
||||||
|
// c.ThenFunc(fn)
|
||||||
|
//
|
||||||
|
// ThenFunc provides all the guarantees of Then.
|
||||||
|
func (c Chain) ThenFunc(fn http.HandlerFunc) http.Handler {
|
||||||
|
if fn == nil {
|
||||||
|
return c.Then(nil)
|
||||||
|
}
|
||||||
|
return c.Then(fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append extends a chain, adding the specified constructors
|
||||||
|
// as the last ones in the request flow.
|
||||||
|
//
|
||||||
|
// Append returns a new chain, leaving the original one untouched.
|
||||||
|
//
|
||||||
|
// stdChain := alice.New(m1, m2)
|
||||||
|
// extChain := stdChain.Append(m3, m4)
|
||||||
|
// // requests in stdChain go m1 -> m2
|
||||||
|
// // requests in extChain go m1 -> m2 -> m3 -> m4
|
||||||
|
func (c Chain) Append(constructors ...Constructor) Chain {
|
||||||
|
newCons := make([]Constructor, 0, len(c.constructors)+len(constructors))
|
||||||
|
newCons = append(newCons, c.constructors...)
|
||||||
|
newCons = append(newCons, constructors...)
|
||||||
|
|
||||||
|
return Chain{newCons}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extend extends a chain by adding the specified chain
|
||||||
|
// as the last one in the request flow.
|
||||||
|
//
|
||||||
|
// Extend returns a new chain, leaving the original one untouched.
|
||||||
|
//
|
||||||
|
// stdChain := alice.New(m1, m2)
|
||||||
|
// ext1Chain := alice.New(m3, m4)
|
||||||
|
// ext2Chain := stdChain.Extend(ext1Chain)
|
||||||
|
// // requests in stdChain go m1 -> m2
|
||||||
|
// // requests in ext1Chain go m3 -> m4
|
||||||
|
// // requests in ext2Chain go m1 -> m2 -> m3 -> m4
|
||||||
|
//
|
||||||
|
// Another example:
|
||||||
|
// aHtmlAfterNosurf := alice.New(m2)
|
||||||
|
// aHtml := alice.New(m1, func(h http.Handler) http.Handler {
|
||||||
|
// csrf := nosurf.New(h)
|
||||||
|
// csrf.SetFailureHandler(aHtmlAfterNosurf.ThenFunc(csrfFail))
|
||||||
|
// return csrf
|
||||||
|
// }).Extend(aHtmlAfterNosurf)
|
||||||
|
// // requests to aHtml hitting nosurfs success handler go m1 -> nosurf -> m2 -> target-handler
|
||||||
|
// // requests to aHtml hitting nosurfs failure handler go m1 -> nosurf -> m2 -> csrfFail
|
||||||
|
func (c Chain) Extend(chain Chain) Chain {
|
||||||
|
return c.Append(chain.constructors...)
|
||||||
|
}
|
3
vendor/github.com/justinas/alice/go.mod
generated
vendored
Normal file
3
vendor/github.com/justinas/alice/go.mod
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module github.com/justinas/alice
|
||||||
|
|
||||||
|
go 1.12
|
3
vendor/modules.txt
vendored
3
vendor/modules.txt
vendored
@ -681,6 +681,9 @@ github.com/jirfag/go-printf-func-name/pkg/analyzer
|
|||||||
github.com/jmespath/go-jmespath
|
github.com/jmespath/go-jmespath
|
||||||
# github.com/julz/importas v0.0.0-20210419104244-841f0c0fe66d
|
# github.com/julz/importas v0.0.0-20210419104244-841f0c0fe66d
|
||||||
github.com/julz/importas
|
github.com/julz/importas
|
||||||
|
# github.com/justinas/alice v1.2.0
|
||||||
|
## explicit
|
||||||
|
github.com/justinas/alice
|
||||||
# github.com/kevinburke/ssh_config v1.1.0
|
# github.com/kevinburke/ssh_config v1.1.0
|
||||||
github.com/kevinburke/ssh_config
|
github.com/kevinburke/ssh_config
|
||||||
# github.com/kisielk/errcheck v1.6.0
|
# github.com/kisielk/errcheck v1.6.0
|
||||||
|
Loading…
Reference in New Issue
Block a user