package tower import ( "context" "log" "net/http" "github.com/julienschmidt/httprouter" ) type Tower struct { router *httprouter.Router errorHandler ErrorHandler globalMiddlewares []Middleware server *http.Server } func New() *Tower { t := &Tower{ router: httprouter.New(), errorHandler: defaultErrorHandler, globalMiddlewares: []Middleware{}, } t.server = &http.Server{ Handler: t.router, } return t } func (t *Tower) Start(listenAddr string) error { t.server.Addr = listenAddr return t.server.ListenAndServe() } func (t *Tower) StartTLS(listenAddr, certFile, keyFile string) error { t.server.Addr = listenAddr return t.server.ListenAndServeTLS(certFile, keyFile) } func (t *Tower) Shutdown(ctx context.Context) error { return t.server.Shutdown(ctx) } func (t *Tower) SetErrorHandler(errorHandler ErrorHandler) { t.errorHandler = errorHandler } func (t *Tower) Use(globalMiddlewares ...Middleware) { t.globalMiddlewares = append(t.globalMiddlewares, globalMiddlewares...) } func (t *Tower) Group(prefix string, groupMiddlewares ...Middleware) *Group { return &Group{ prefix: normalizePath(prefix), parent: t, groupMiddlewares: groupMiddlewares, } } func (t *Tower) Static(prefix, dir string) { prefix = normalizePath(prefix) prefix += "/*filepath" t.router.ServeFiles(prefix, http.Dir(dir)) } func (t *Tower) GET(path string, h Handler, routeMiddlewares ...Middleware) { t.Handle(http.MethodGet, path, h, routeMiddlewares...) } func (t *Tower) POST(path string, h Handler, routeMiddlewares ...Middleware) { t.Handle(http.MethodPost, path, h, routeMiddlewares...) } func (t *Tower) PUT(path string, h Handler, routeMiddlewares ...Middleware) { t.Handle(http.MethodPut, path, h, routeMiddlewares...) } func (t *Tower) PATCH(path string, h Handler, routeMiddlewares ...Middleware) { t.Handle(http.MethodPatch, path, h, routeMiddlewares...) } func (t *Tower) DELETE(path string, h Handler, routeMiddlewares ...Middleware) { t.Handle(http.MethodDelete, path, h, routeMiddlewares...) } func (t *Tower) Handle(method string, path string, h Handler, routeMiddlewares ...Middleware) { t.router.Handle(method, path, t.buildHTTPRouterHandle(h, routeMiddlewares...)) } func (t *Tower) buildHTTPRouterHandle(h Handler, routeMiddlewares ...Middleware) httprouter.Handle { return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) { ctx := Context{ request: r, response: &responseWriter{ResponseWriter: w}, params: p, } wrappedHandler := h for i := len(routeMiddlewares) - 1; i >= 0; i-- { wrappedHandler = routeMiddlewares[i](wrappedHandler) } for i := len(t.globalMiddlewares) - 1; i >= 0; i-- { wrappedHandler = t.globalMiddlewares[i](wrappedHandler) } if err := wrappedHandler(&ctx); err != nil { if err := t.errorHandler(&ctx, err); err != nil { log.Printf("[Error] %v", err) } } } }