router: added middlewares
This commit is contained in:
@@ -11,6 +11,7 @@ type Context struct {
|
|||||||
Request *http.Request
|
Request *http.Request
|
||||||
Writer http.ResponseWriter
|
Writer http.ResponseWriter
|
||||||
PathMap map[string]string
|
PathMap map[string]string
|
||||||
|
StatusCode int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewContext(writer http.ResponseWriter, request *http.Request) *Context {
|
func NewContext(writer http.ResponseWriter, request *http.Request) *Context {
|
||||||
@@ -29,6 +30,7 @@ func (rctx *Context) SetHeader(key, value string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (rctx *Context) SetStatus(httpStatus int) {
|
func (rctx *Context) SetStatus(httpStatus int) {
|
||||||
|
rctx.StatusCode = httpStatus
|
||||||
rctx.Writer.WriteHeader(httpStatus)
|
rctx.Writer.WriteHeader(httpStatus)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package router
|
||||||
|
|
||||||
|
func NewCorsMiddleware() MiddlewareFunc {
|
||||||
|
mw := func(next Handler) Handler {
|
||||||
|
return newCorsHandler(next)
|
||||||
|
}
|
||||||
|
return mw
|
||||||
|
}
|
||||||
|
|
||||||
|
type corsHandler struct {
|
||||||
|
next Handler
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCorsHandler(next Handler) *corsHandler {
|
||||||
|
return &corsHandler{
|
||||||
|
next: next,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hand corsHandler) ServeHTTP(ctx *Context) {
|
||||||
|
origin := ctx.Request.Header.Get("Origin")
|
||||||
|
if origin != "" {
|
||||||
|
ctx.SetHeader("Access-Control-Allow-Origin", origin)
|
||||||
|
ctx.SetHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE, PATCH")
|
||||||
|
ctx.SetHeader("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
|
||||||
|
ctx.SetHeader("Access-Control-Max-Age", "86400")
|
||||||
|
ctx.SetHeader("Access-Control-Allow-Credentials", "true")
|
||||||
|
}
|
||||||
|
if ctx.Request.Method == "OPTIONS" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
hand.next.ServeHTTP(ctx)
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package router
|
||||||
|
|
||||||
|
func NewLoggingMiddleware(print func(string, ...any)) MiddlewareFunc {
|
||||||
|
mw := func(next Handler) Handler {
|
||||||
|
return newLoggingHandler(next, print)
|
||||||
|
}
|
||||||
|
return mw
|
||||||
|
}
|
||||||
|
|
||||||
|
type loggingHandler struct {
|
||||||
|
next Handler
|
||||||
|
printFunc func(string, ...any)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newLoggingHandler(next Handler, print func(string, ...any)) *loggingHandler {
|
||||||
|
return &loggingHandler{
|
||||||
|
next: next,
|
||||||
|
printFunc: print,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (logging loggingHandler) ServeHTTP(rctx *Context) {
|
||||||
|
logging.next.ServeHTTP(rctx)
|
||||||
|
logging.printFunc("%s %s %s %s %d", rctx.Request.RemoteAddr,
|
||||||
|
rctx.Request.Method, rctx.Request.URL.String(),
|
||||||
|
rctx.Request.Proto, rctx.StatusCode)
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package router
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"runtime/debug"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewRecoveryMiddleware(print func(string, ...any)) MiddlewareFunc {
|
||||||
|
mw := func(next Handler) Handler {
|
||||||
|
return newRecoveryHandler(next, print)
|
||||||
|
}
|
||||||
|
return mw
|
||||||
|
}
|
||||||
|
|
||||||
|
type recoveryHandler struct {
|
||||||
|
next Handler
|
||||||
|
print func(string, ...any)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newRecoveryHandler(next Handler, print func(string, ...any)) *recoveryHandler {
|
||||||
|
return &recoveryHandler{
|
||||||
|
next: next,
|
||||||
|
print: print,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hand recoveryHandler) ServeHTTP(rctx *Context) {
|
||||||
|
exitFunc := func() {
|
||||||
|
err := recover()
|
||||||
|
if err != nil {
|
||||||
|
rctx.Writer.WriteHeader(http.StatusInternalServerError)
|
||||||
|
stack := string(debug.Stack())
|
||||||
|
timestamp := time.Now().Format(time.RFC3339)
|
||||||
|
hand.print("%s %v ; %s\n", timestamp, err, stack)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defer exitFunc()
|
||||||
|
hand.next.ServeHTTP(rctx)
|
||||||
|
}
|
||||||
+11
-2
@@ -6,6 +6,8 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type MiddlewareFunc func(next Handler) Handler
|
||||||
|
|
||||||
type Handler interface {
|
type Handler interface {
|
||||||
ServeHTTP(rctx *Context)
|
ServeHTTP(rctx *Context)
|
||||||
}
|
}
|
||||||
@@ -17,15 +19,22 @@ func (handlerFunc HandlerFunc) ServeHTTP(rctx *Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Router struct {
|
type Router struct {
|
||||||
|
headHandler Handler
|
||||||
routeHandler *Selector
|
routeHandler *Selector
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRouter() *Router {
|
func NewRouter() *Router {
|
||||||
|
selector := NewSelector()
|
||||||
return &Router{
|
return &Router{
|
||||||
routeHandler: NewSelector(),
|
routeHandler: selector,
|
||||||
|
headHandler: selector,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rout *Router) Use(mwFunc MiddlewareFunc) {
|
||||||
|
rout.headHandler = mwFunc(rout.headHandler)
|
||||||
|
}
|
||||||
|
|
||||||
func (rout *Router) Selector() *Selector {
|
func (rout *Router) Selector() *Selector {
|
||||||
return rout.routeHandler
|
return rout.routeHandler
|
||||||
}
|
}
|
||||||
@@ -60,7 +69,7 @@ func (rout *Router) Delete(path string, handlerFunc HandlerFunc) {
|
|||||||
|
|
||||||
func (rout *Router) ServeHTTP(writer http.ResponseWriter, req *http.Request) {
|
func (rout *Router) ServeHTTP(writer http.ResponseWriter, req *http.Request) {
|
||||||
rctx := NewContext(writer, req)
|
rctx := NewContext(writer, req)
|
||||||
rout.routeHandler.ServeHTTP(rctx)
|
rout.headHandler.ServeHTTP(rctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rout *Router) NotFound(handlerFunc HandlerFunc) {
|
func (rout *Router) NotFound(handlerFunc HandlerFunc) {
|
||||||
|
|||||||
Reference in New Issue
Block a user