Macaron cleanup (#37795)

* simplify some dependency injection in macaron
* remove unused internal server error handler from macaron
* remove internal server error handler from the router
* remove unused combo router api
* remove unused parts of the macaron router
This commit is contained in:
Serge Zaitsev 2021-08-30 11:48:34 +02:00 committed by GitHub
parent 74afe809af
commit d15cbe4b4e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 38 additions and 235 deletions

View File

@ -47,7 +47,7 @@ func (hs *HTTPServer) initAppPluginRoutes(r *macaron.Macaron) {
}
}
handlers = append(handlers, AppPluginRoute(route, plugin.Id, hs))
r.Route(url, route.Method, handlers...)
r.Handle(route.Method, url, handlers)
log.Debugf("Plugins: Adding proxy route %s", url)
}
}

View File

@ -136,8 +136,6 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi
socialService social.Service, oauthTokenService oauthtoken.OAuthTokenService) (*HTTPServer, error) {
macaron.Env = cfg.Env
m := macaron.New()
// automatically set HEAD for every GET
m.SetAutoHead(true)
hs := &HTTPServer{
Cfg: cfg,

View File

@ -10,8 +10,8 @@ import (
)
type Router interface {
Handle(method, pattern string, handlers []macaron.Handler) *macaron.Route
Get(pattern string, handlers ...macaron.Handler) *macaron.Route
Handle(method, pattern string, handlers []macaron.Handler)
Get(pattern string, handlers ...macaron.Handler)
}
// RouteRegister allows you to add routes and macaron.Handlers

View File

@ -12,24 +12,20 @@ type fakeRouter struct {
route []route
}
func (fr *fakeRouter) Handle(method, pattern string, handlers []macaron.Handler) *macaron.Route {
func (fr *fakeRouter) Handle(method, pattern string, handlers []macaron.Handler) {
fr.route = append(fr.route, route{
pattern: pattern,
method: method,
handlers: handlers,
})
return &macaron.Route{}
}
func (fr *fakeRouter) Get(pattern string, handlers ...macaron.Handler) *macaron.Route {
func (fr *fakeRouter) Get(pattern string, handlers ...macaron.Handler) {
fr.route = append(fr.route, route{
pattern: pattern,
method: http.MethodGet,
handlers: handlers,
})
return &macaron.Route{}
}
func emptyHandlers(n int) []macaron.Handler {

View File

@ -17,7 +17,6 @@ package httpstatic
import (
"fmt"
"log"
"net/http"
"os"
"path"
@ -26,6 +25,7 @@ import (
"strings"
"sync"
"github.com/grafana/grafana/pkg/infra/log"
"gopkg.in/macaron.v1"
)
@ -115,7 +115,7 @@ func prepareStaticOptions(dir string, options []StaticOptions) StaticOptions {
return prepareStaticOption(dir, opt)
}
func staticHandler(ctx *macaron.Context, log *log.Logger, opt StaticOptions) bool {
func staticHandler(ctx *macaron.Context, log log.Logger, opt StaticOptions) bool {
if ctx.Req.Method != "GET" && ctx.Req.Method != "HEAD" {
return false
}
@ -138,7 +138,7 @@ func staticHandler(ctx *macaron.Context, log *log.Logger, opt StaticOptions) boo
}
defer func() {
if err := f.Close(); err != nil {
log.Printf("Failed to close file: %s\n", err)
log.Error("Failed to close file", "error", err)
}
}()
@ -171,7 +171,7 @@ func staticHandler(ctx *macaron.Context, log *log.Logger, opt StaticOptions) boo
}
defer func() {
if err := indexFile.Close(); err != nil {
log.Printf("Failed to close file: %s", err)
log.Error("Failed to close file", "error", err)
}
}()
@ -182,7 +182,7 @@ func staticHandler(ctx *macaron.Context, log *log.Logger, opt StaticOptions) boo
}
if !opt.SkipLogging {
log.Printf("[Static] Serving %s\n", file)
log.Info("[Static] Serving", "file", file)
}
// Add an Expires header to the static content
@ -198,7 +198,8 @@ func staticHandler(ctx *macaron.Context, log *log.Logger, opt StaticOptions) boo
func Static(directory string, staticOpt ...StaticOptions) macaron.Handler {
opt := prepareStaticOptions(directory, staticOpt)
return func(ctx *macaron.Context, log *log.Logger) {
staticHandler(ctx, log, opt)
logger := log.New("static")
return func(ctx *macaron.Context) {
staticHandler(ctx, logger, opt)
}
}

View File

@ -26,10 +26,6 @@ import (
type Injector interface {
Invoker
TypeMapper
// SetParent sets the parent of the injector. If the injector cannot find a
// dependency in its Type map it will check its parent before returning an
// error.
SetParent(Injector)
}
// Invoker represents an interface for calling functions via reflection.
@ -84,7 +80,6 @@ type TypeMapper interface {
type injector struct {
values map[reflect.Type]reflect.Value
parent Injector
}
// InterfaceOf dereferences a pointer to an Interface type.
@ -193,16 +188,5 @@ func (i *injector) GetVal(t reflect.Type) reflect.Value {
}
}
}
// Still no type found, try to look it up on the parent
if !val.IsValid() && i.parent != nil {
val = i.parent.GetVal(t)
}
return val
}
func (i *injector) SetParent(parent Injector) {
i.parent = parent
}

View File

@ -19,9 +19,7 @@ package macaron // import "gopkg.in/macaron.v1"
import (
"context"
"log"
"net/http"
"os"
"reflect"
"strings"
)
@ -56,14 +54,6 @@ func (invoke handlerFuncInvoker) Invoke(params []interface{}) ([]reflect.Value,
return nil, nil
}
// internalServerErrorInvoker is an inject.FastInvoker wrapper of func(rw http.ResponseWriter, err error).
type internalServerErrorInvoker func(rw http.ResponseWriter, err error)
func (invoke internalServerErrorInvoker) Invoke(params []interface{}) ([]reflect.Value, error) {
invoke(params[0].(http.ResponseWriter), params[1].(error))
return nil, nil
}
// validateAndWrapHandler makes sure a handler is a callable function, it panics if not.
// When the handler is also potential to be any built-in inject.FastInvoker,
// it wraps the handler automatically to have some performance gain.
@ -78,8 +68,6 @@ func validateAndWrapHandler(h Handler) Handler {
return ContextInvoker(v)
case func(http.ResponseWriter, *http.Request):
return handlerFuncInvoker(v)
case func(http.ResponseWriter, error):
return internalServerErrorInvoker(v)
}
}
return h
@ -99,32 +87,18 @@ func validateAndWrapHandlers(handlers []Handler) []Handler {
// Macaron represents the top level web application.
// Injector methods can be invoked to map services on a global level.
type Macaron struct {
Injector
befores []BeforeHandler
handlers []Handler
hasURLPrefix bool
urlPrefix string // For suburl support.
urlPrefix string // For suburl support.
*Router
logger *log.Logger
}
// New creates a bare bones Macaron instance.
// Use this method if you want to have full control over the middleware that is used.
func New() *Macaron {
m := &Macaron{
Injector: NewInjector(),
Router: NewRouter(),
logger: log.New(os.Stdout, "[Macaron] ", 0),
}
m := &Macaron{Router: NewRouter()}
m.Router.m = m
m.Map(m.logger)
m.Map(defaultReturnHandler())
m.NotFound(http.NotFound)
m.InternalServerError(func(rw http.ResponseWriter, err error) {
http.Error(rw, err.Error(), 500)
})
return m
}
@ -185,7 +159,7 @@ func (m *Macaron) createContext(rw http.ResponseWriter, req *http.Request) *Cont
Data: make(map[string]interface{}),
}
req = req.WithContext(context.WithValue(req.Context(), macaronContextKey{}, c))
c.SetParent(m)
c.Map(defaultReturnHandler())
c.Map(c)
c.MapTo(c.Resp, (*http.ResponseWriter)(nil))
c.Map(req)
@ -197,19 +171,11 @@ func (m *Macaron) createContext(rw http.ResponseWriter, req *http.Request) *Cont
// Useful if you want to control your own HTTP server.
// Be aware that none of middleware will run without registering any router.
func (m *Macaron) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
if m.hasURLPrefix {
req.URL.Path = strings.TrimPrefix(req.URL.Path, m.urlPrefix)
}
for _, h := range m.befores {
if h(rw, req) {
return
}
}
req.URL.Path = strings.TrimPrefix(req.URL.Path, m.urlPrefix)
m.Router.ServeHTTP(rw, req)
}
// SetURLPrefix sets URL prefix of router layer, so that it support suburl.
func (m *Macaron) SetURLPrefix(prefix string) {
m.urlPrefix = prefix
m.hasURLPrefix = len(m.urlPrefix) > 0
}

View File

@ -53,7 +53,7 @@ func defaultReturnHandler() ReturnHandler {
if isError(respVal) {
err := respVal.Interface().(error)
if err != nil {
ctx.internalServerError(ctx, err)
http.Error(resp, err.Error(), 500)
}
return
} else if canDeref(respVal) {

View File

@ -40,7 +40,7 @@ type routeMap struct {
}
// NewRouteMap initializes and returns a new routeMap.
func NewRouteMap() *routeMap {
func newRouteMap() *routeMap {
rm := &routeMap{
routes: make(map[string]map[string]*Leaf),
}
@ -73,61 +73,37 @@ type group struct {
// Router represents a Macaron router layer.
type Router struct {
m *Macaron
autoHead bool
routers map[string]*Tree
m *Macaron
routers map[string]*Tree
*routeMap
namedRoutes map[string]*Leaf
groups []group
notFound http.HandlerFunc
internalServerError func(*Context, error)
groups []group
notFound http.HandlerFunc
}
func NewRouter() *Router {
return &Router{
routers: make(map[string]*Tree),
routeMap: NewRouteMap(),
routeMap: newRouteMap(),
namedRoutes: make(map[string]*Leaf),
}
}
// SetAutoHead sets the value who determines whether add HEAD method automatically
// when GET method is added.
func (r *Router) SetAutoHead(v bool) {
r.autoHead = v
}
type Params map[string]string
// Handle is a function that can be registered to a route to handle HTTP requests.
// Like http.HandlerFunc, but has a third parameter for the values of wildcards (variables).
type Handle func(http.ResponseWriter, *http.Request, Params)
// Route represents a wrapper of leaf route and upper level router.
type Route struct {
router *Router
leaf *Leaf
}
// Name sets name of route.
func (r *Route) Name(name string) {
if len(name) == 0 {
panic("route name cannot be empty")
} else if r.router.namedRoutes[name] != nil {
panic("route with given name already exists: " + name)
}
r.router.namedRoutes[name] = r.leaf
}
// handle adds new route to the router tree.
func (r *Router) handle(method, pattern string, handle Handle) *Route {
func (r *Router) handle(method, pattern string, handle Handle) {
method = strings.ToUpper(method)
var leaf *Leaf
// Prevent duplicate routes.
if leaf = r.getLeaf(method, pattern); leaf != nil {
return &Route{r, leaf}
return
}
// Validate HTTP methods.
@ -156,11 +132,10 @@ func (r *Router) handle(method, pattern string, handle Handle) *Route {
}
r.add(m, pattern, leaf)
}
return &Route{r, leaf}
}
// Handle registers a new request handle with the given pattern, method and handlers.
func (r *Router) Handle(method string, pattern string, handlers []Handler) *Route {
func (r *Router) Handle(method string, pattern string, handlers []Handler) {
if len(r.groups) > 0 {
groupPattern := ""
h := make([]Handler, 0)
@ -175,7 +150,7 @@ func (r *Router) Handle(method string, pattern string, handlers []Handler) *Rout
}
handlers = validateAndWrapHandlers(handlers)
return r.handle(method, pattern, func(resp http.ResponseWriter, req *http.Request, params Params) {
r.handle(method, pattern, func(resp http.ResponseWriter, req *http.Request, params Params) {
c := r.m.createContext(resp, req)
c.params = params
c.handlers = make([]Handler, 0, len(r.m.handlers)+len(handlers))
@ -192,64 +167,31 @@ func (r *Router) Group(pattern string, fn func(), h ...Handler) {
}
// Get is a shortcut for r.Handle("GET", pattern, handlers)
func (r *Router) Get(pattern string, h ...Handler) (leaf *Route) {
leaf = r.Handle("GET", pattern, h)
if r.autoHead {
r.Head(pattern, h...)
}
return leaf
func (r *Router) Get(pattern string, h ...Handler) {
r.Handle("GET", pattern, h)
r.Head(pattern, h...)
}
// Patch is a shortcut for r.Handle("PATCH", pattern, handlers)
func (r *Router) Patch(pattern string, h ...Handler) *Route {
return r.Handle("PATCH", pattern, h)
}
func (r *Router) Patch(pattern string, h ...Handler) { r.Handle("PATCH", pattern, h) }
// Post is a shortcut for r.Handle("POST", pattern, handlers)
func (r *Router) Post(pattern string, h ...Handler) *Route {
return r.Handle("POST", pattern, h)
}
func (r *Router) Post(pattern string, h ...Handler) { r.Handle("POST", pattern, h) }
// Put is a shortcut for r.Handle("PUT", pattern, handlers)
func (r *Router) Put(pattern string, h ...Handler) *Route {
return r.Handle("PUT", pattern, h)
}
func (r *Router) Put(pattern string, h ...Handler) { r.Handle("PUT", pattern, h) }
// Delete is a shortcut for r.Handle("DELETE", pattern, handlers)
func (r *Router) Delete(pattern string, h ...Handler) *Route {
return r.Handle("DELETE", pattern, h)
}
func (r *Router) Delete(pattern string, h ...Handler) { r.Handle("DELETE", pattern, h) }
// Options is a shortcut for r.Handle("OPTIONS", pattern, handlers)
func (r *Router) Options(pattern string, h ...Handler) *Route {
return r.Handle("OPTIONS", pattern, h)
}
func (r *Router) Options(pattern string, h ...Handler) { r.Handle("OPTIONS", pattern, h) }
// Head is a shortcut for r.Handle("HEAD", pattern, handlers)
func (r *Router) Head(pattern string, h ...Handler) *Route {
return r.Handle("HEAD", pattern, h)
}
func (r *Router) Head(pattern string, h ...Handler) { r.Handle("HEAD", pattern, h) }
// Any is a shortcut for r.Handle("*", pattern, handlers)
func (r *Router) Any(pattern string, h ...Handler) *Route {
return r.Handle("*", pattern, h)
}
// Route is a shortcut for same handlers but different HTTP methods.
//
// Example:
// m.Route("/", "GET,POST", h)
func (r *Router) Route(pattern, methods string, h ...Handler) (route *Route) {
for _, m := range strings.Split(methods, ",") {
route = r.Handle(strings.TrimSpace(m), pattern, h)
}
return route
}
// Combo returns a combo router.
func (r *Router) Combo(pattern string, h ...Handler) *ComboRouter {
return &ComboRouter{r, pattern, h, map[string]bool{}, nil}
}
func (r *Router) Any(pattern string, h ...Handler) { r.Handle("*", pattern, h) }
// NotFound configurates http.HandlerFunc which is called when no matching route is
// found. If it is not set, http.NotFound is used.
@ -265,19 +207,6 @@ func (r *Router) NotFound(handlers ...Handler) {
}
}
// InternalServerError configurates handler which is called when route handler returns
// error. If it is not set, default handler is used.
// Be sure to set 500 response code in your handler.
func (r *Router) InternalServerError(handlers ...Handler) {
handlers = validateAndWrapHandlers(handlers)
r.internalServerError = func(c *Context, err error) {
c.index = 0
c.handlers = handlers
c.Map(err)
c.run()
}
}
func (r *Router) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
if t, ok := r.routers[req.Method]; ok {
// Fast match for static routes
@ -299,74 +228,3 @@ func (r *Router) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
r.notFound(rw, req)
}
// URLFor builds path part of URL by given pair values.
func (r *Router) URLFor(name string, pairs ...string) string {
leaf, ok := r.namedRoutes[name]
if !ok {
panic("route with given name does not exists: " + name)
}
return leaf.URLPath(pairs...)
}
// ComboRouter represents a combo router.
type ComboRouter struct {
router *Router
pattern string
handlers []Handler
methods map[string]bool // Registered methods.
lastRoute *Route
}
func (cr *ComboRouter) checkMethod(name string) {
if cr.methods[name] {
panic("method '" + name + "' has already been registered")
}
cr.methods[name] = true
}
func (cr *ComboRouter) route(fn func(string, ...Handler) *Route, method string, h ...Handler) *ComboRouter {
cr.checkMethod(method)
cr.lastRoute = fn(cr.pattern, append(cr.handlers, h...)...)
return cr
}
func (cr *ComboRouter) Get(h ...Handler) *ComboRouter {
if cr.router.autoHead {
cr.Head(h...)
}
return cr.route(cr.router.Get, "GET", h...)
}
func (cr *ComboRouter) Patch(h ...Handler) *ComboRouter {
return cr.route(cr.router.Patch, "PATCH", h...)
}
func (cr *ComboRouter) Post(h ...Handler) *ComboRouter {
return cr.route(cr.router.Post, "POST", h...)
}
func (cr *ComboRouter) Put(h ...Handler) *ComboRouter {
return cr.route(cr.router.Put, "PUT", h...)
}
func (cr *ComboRouter) Delete(h ...Handler) *ComboRouter {
return cr.route(cr.router.Delete, "DELETE", h...)
}
func (cr *ComboRouter) Options(h ...Handler) *ComboRouter {
return cr.route(cr.router.Options, "OPTIONS", h...)
}
func (cr *ComboRouter) Head(h ...Handler) *ComboRouter {
return cr.route(cr.router.Head, "HEAD", h...)
}
// Name sets name of ComboRouter route.
func (cr *ComboRouter) Name(name string) {
if cr.lastRoute == nil {
panic("no corresponding route to be named")
}
cr.lastRoute.Name(name)
}