157 lines
3.8 KiB
Go
157 lines
3.8 KiB
Go
package tower
|
|
|
|
import (
|
|
"context"
|
|
"io/fs"
|
|
"log"
|
|
"net/http"
|
|
"path"
|
|
|
|
"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) SetNotFoundHandler(notFoundHandler Handler) {
|
|
t.router.NotFound = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
ctx := Context{
|
|
request: r,
|
|
response: &responseWriter{ResponseWriter: w},
|
|
params: httprouter.Params{},
|
|
}
|
|
|
|
if err := notFoundHandler(&ctx); err != nil {
|
|
if err := t.errorHandler(&ctx, err); err != nil {
|
|
log.Printf("[Error] %v", err)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
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) StaticFS(prefix string, fsys fs.FS) {
|
|
fileServer := http.FileServer(http.FS(fsys))
|
|
|
|
handler := func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
|
fp := p.ByName("filepath")
|
|
if fp == "" {
|
|
fp = "/"
|
|
}
|
|
|
|
fp = path.Clean("/" + fp)
|
|
|
|
req := r.Clone(r.Context())
|
|
req.URL.Path = fp
|
|
|
|
fileServer.ServeHTTP(w, req)
|
|
}
|
|
|
|
t.router.Handle(http.MethodGet, buildFullPath(prefix, "/*filepath"), handler)
|
|
t.router.Handle(http.MethodHead, buildFullPath(prefix, "/*filepath"), handler)
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
}
|
|
}
|