mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
add FromContext API for macaron and reqcontext, add API for standard middleware in macaron (#37057)
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
package macaron // import "gopkg.in/macaron.v1"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
@@ -151,6 +152,41 @@ func (m *Macaron) Handlers(handlers ...Handler) {
|
||||
// Macaron stops future process when it returns true.
|
||||
type BeforeHandler func(rw http.ResponseWriter, req *http.Request) bool
|
||||
|
||||
// macaronContextKey is used to store/fetch macaron.Context inside context.Context
|
||||
type macaronContextKey struct{}
|
||||
|
||||
// FromContext returns the macaron context stored in a context.Context, if any.
|
||||
func FromContext(c context.Context) *Context {
|
||||
if mc, ok := c.Value(macaronContextKey{}).(*Context); ok {
|
||||
return mc
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UseMiddleware is a traditional approach to writing middleware in Go.
|
||||
// A middleware is a function that has a reference to the next handler in the chain
|
||||
// and returns the actual middleware handler, that may do its job and optionally
|
||||
// call next.
|
||||
// Due to how Macaron handles/injects requests and responses we patch the macaron.Context
|
||||
// to use the new ResponseWriter and http.Request here. The caller may only call
|
||||
// `next.ServeHTTP(rw, req)` to pass a modified response writer and/or a request to the
|
||||
// further middlewares in the chain.
|
||||
func (m *Macaron) UseMiddleware(middleware func(http.Handler) http.Handler) {
|
||||
next := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||
c := FromContext(req.Context())
|
||||
c.Req.Request = req
|
||||
if mrw, ok := rw.(*responseWriter); ok {
|
||||
c.Resp = mrw
|
||||
} else {
|
||||
c.Resp = NewResponseWriter(req.Method, rw)
|
||||
}
|
||||
c.Map(req)
|
||||
c.MapTo(rw, (*http.ResponseWriter)(nil))
|
||||
c.Next()
|
||||
})
|
||||
m.handlers = append(m.handlers, Handler(middleware(next)))
|
||||
}
|
||||
|
||||
// Use adds a middleware Handler to the stack,
|
||||
// and panics if the handler is not a callable func.
|
||||
// Middleware Handlers are invoked in the order that they are added.
|
||||
@@ -165,15 +201,16 @@ func (m *Macaron) createContext(rw http.ResponseWriter, req *http.Request) *Cont
|
||||
handlers: m.handlers,
|
||||
index: 0,
|
||||
Router: m.Router,
|
||||
Req: Request{req},
|
||||
Resp: NewResponseWriter(req.Method, rw),
|
||||
Render: &DummyRender{rw},
|
||||
Data: make(map[string]interface{}),
|
||||
}
|
||||
req = req.WithContext(context.WithValue(req.Context(), macaronContextKey{}, c))
|
||||
c.SetParent(m)
|
||||
c.Map(c)
|
||||
c.MapTo(c.Resp, (*http.ResponseWriter)(nil))
|
||||
c.Map(req)
|
||||
c.Req = Request{req}
|
||||
return c
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,16 @@ func (h *ContextHandler) Init() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type reqContextKey struct{}
|
||||
|
||||
// FromContext returns the ReqContext value stored in a context.Context, if any.
|
||||
func FromContext(c context.Context) *models.ReqContext {
|
||||
if reqCtx, ok := c.Value(reqContextKey{}).(*models.ReqContext); ok {
|
||||
return reqCtx
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Middleware provides a middleware to initialize the Macaron context.
|
||||
func (h *ContextHandler) Middleware(mContext *macaron.Context) {
|
||||
span, _ := opentracing.StartSpanFromContext(mContext.Req.Context(), "Auth - Middleware")
|
||||
@@ -76,6 +86,10 @@ func (h *ContextHandler) Middleware(mContext *macaron.Context) {
|
||||
Logger: log.New("context"),
|
||||
}
|
||||
|
||||
// Inject ReqContext into a request context and replace the request instance in the macaron context
|
||||
mContext.Req.Request = mContext.Req.WithContext(context.WithValue(mContext.Req.Context(), reqContextKey{}, reqContext))
|
||||
mContext.Map(mContext.Req.Request)
|
||||
|
||||
traceID, exists := cw.ExtractTraceID(mContext.Req.Request.Context())
|
||||
if exists {
|
||||
reqContext.Logger = reqContext.Logger.New("traceID", traceID)
|
||||
|
||||
Reference in New Issue
Block a user