diff --git a/admin/admin.go b/admin/admin.go index 046ce0f..f928620 100644 --- a/admin/admin.go +++ b/admin/admin.go @@ -3,6 +3,7 @@ package admin import ( "net/http" + "git.pyer.club/kingecg/gohttpd/model" "git.pyer.club/kingecg/gohttpd/server" ) @@ -16,19 +17,13 @@ func setConfig(w http.ResponseWriter, r *http.Request) { } -var AdminRoutes = []server.Route{ - // Admin Routes - {Method: "GET", Path: "/about", Handle: about}, - {Method: "Post", Path: "/config", Handle: setConfig}, -} - var AdminServerMux *server.RestMux func init() { AdminServerMux = server.NewRestMux("/") - // AdminServerMux.routes = make(map[string]map[string]http.HandlerFunc) - for _, route := range AdminRoutes { - AdminServerMux.HandleFunc(route.Method, route.Path, route.Handle) - } + AdminServerMux.Use(server.BasicAuth) + AdminServerMux.HandleFunc("GET", "/about", http.HandlerFunc(about)) + postConfigRoute := AdminServerMux.HandleFunc("POST", "/config", http.HandlerFunc(setConfig)) + postConfigRoute.Add(server.Parse[model.HttpServerConfig]) AdminServerMux.Use(server.BasicAuth) } diff --git a/server/middleware.go b/server/middleware.go index 2d08971..f68ecb3 100644 --- a/server/middleware.go +++ b/server/middleware.go @@ -1,6 +1,7 @@ package server import ( + "container/list" "encoding/json" "net/http" "strings" @@ -10,6 +11,40 @@ import ( type Middleware func(w http.ResponseWriter, r *http.Request, next func()) +type MiddlewareLink struct { + *list.List +} + +func (ml *MiddlewareLink) Add(m Middleware) { + if ml.List.Len() == 0 { + ml.PushBack(m) + } else { + el := ml.Back() + ml.InsertBefore(m, el) + } +} + +func (ml *MiddlewareLink) ServeHTTP(w http.ResponseWriter, r *http.Request) bool { + canContinue := false + next := func() { + canContinue = true + } + for e := ml.Front(); e != nil && canContinue; e = e.Next() { + e.Value.(Middleware)(w, r, next) + if !canContinue { + break + } else { + canContinue = false + } + } + return canContinue +} +func NewMiddlewareLink() *MiddlewareLink { + ml := &MiddlewareLink{list.New()} + ml.Add(Done) + return ml +} + func BasicAuth(w http.ResponseWriter, r *http.Request, next func()) { config := model.GetConfig() @@ -60,3 +95,7 @@ func Parse[T any](w http.ResponseWriter, r *http.Request, next func()) { } next() } + +func Done(w http.ResponseWriter, r *http.Request, next func()) { + next() +} diff --git a/server/server.go b/server/server.go index 51eef4f..c0cd3f3 100644 --- a/server/server.go +++ b/server/server.go @@ -12,17 +12,16 @@ type RequestCtxKey string type Route struct { Method string Path string - Handle http.HandlerFunc Handler http.Handler matcher *UrlParamMatcher + middles *MiddlewareLink } func (route *Route) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if route.Handler != nil { - route.Handler.ServeHTTP(w, r) - } else { - route.Handle(w, r) + if route.middles.Len() > 0 && !route.middles.ServeHTTP(w, r) { + return } + route.Handler.ServeHTTP(w, r) } func (route *Route) Match(r *http.Request) bool { @@ -48,6 +47,22 @@ func (route *Route) Match(r *http.Request) bool { return strings.HasPrefix(r.URL.Path, route.Path) } +func (route *Route) Add(m Middleware) { + route.middles.Add(m) +} +func NewRoute(method string, path string, handleFn http.Handler) *Route { + ret := &Route{ + Method: method, + Path: path, + middles: NewMiddlewareLink(), + } + p := ParseUrl(path) + //使用handleFn构建handler + ret.Handler = handleFn + ret.matcher = &p + return ret +} + type Routes []*Route func (rs Routes) Less(i, j int) bool { @@ -79,36 +94,22 @@ func (rs Routes) Swap(i, j int) { type RestMux struct { Path string routes Routes - middlewares []Middleware + middlewares *MiddlewareLink } func (mux *RestMux) Use(m Middleware) { - mux.middlewares = append(mux.middlewares, m) + mux.middlewares.Add(m) } func (mux *RestMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { - canContinue := false + c := r.Context() data := map[string]interface{}{} cn := context.WithValue(c, RequestCtxKey("data"), data) newRequest := r.WithContext(cn) - if len(mux.middlewares) > 0 { - for _, m := range mux.middlewares { - canContinue = false - m(w, newRequest, func() { canContinue = true }) - if !canContinue { - return - } - } + if mux.middlewares.Len() > 0 && !mux.middlewares.ServeHTTP(w, newRequest) { + return } - // _, has := lo.Find(mux.rmuxPaths, func(s string) bool { - // return strings.HasPrefix(newRequest.URL.Path, s) - // }) - // if has { - // mux.imux.ServeHTTP(w, newRequest) - // return - // } - // 根据r 从routes中找到匹配的路由 for _, route := range mux.routes { if route.Match(newRequest) { @@ -116,76 +117,58 @@ func (mux *RestMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } } - // newRequest.URL.Path = "/" + strings.ToLower(newRequest.Method) + newRequest.URL.Path - // newRequest.RequestURI = "/" + strings.ToLower(newRequest.Method) + newRequest.RequestURI - // h, _ := mux.imux.Handler(newRequest) - // h.ServeHTTP(w, newRequest) http.NotFound(w, r) } -func (mux *RestMux) HandleFunc(method string, path string, f func(http.ResponseWriter, *http.Request)) { - r := &Route{ - Method: method, - Path: path, - Handle: f, - Handler: nil, - } - *r.matcher = ParseUrl(path) +func (mux *RestMux) HandleFunc(method string, path string, f func(http.ResponseWriter, *http.Request)) *Route { + r := NewRoute(method, path, http.HandlerFunc(f)) mux.routes = append(mux.routes, r) sort.Sort(mux.routes) + return r } -func (mux *RestMux) Get(path string, f func(http.ResponseWriter, *http.Request)) { - mux.HandleFunc("GET", path, f) +func (mux *RestMux) Get(path string, f func(http.ResponseWriter, *http.Request)) *Route { + return mux.HandleFunc("GET", path, f) } -func (mux *RestMux) Post(path string, f func(http.ResponseWriter, *http.Request)) { - mux.HandleFunc("POST", path, f) +func (mux *RestMux) Post(path string, f func(http.ResponseWriter, *http.Request)) *Route { + return mux.HandleFunc("POST", path, f) } -func (mux *RestMux) Put(path string, f func(http.ResponseWriter, *http.Request)) { - mux.HandleFunc("PUT", path, f) +func (mux *RestMux) Put(path string, f func(http.ResponseWriter, *http.Request)) *Route { + return mux.HandleFunc("PUT", path, f) } -func (mux *RestMux) Delete(path string, f func(http.ResponseWriter, *http.Request)) { - mux.HandleFunc("DELETE", path, f) +func (mux *RestMux) Delete(path string, f func(http.ResponseWriter, *http.Request)) *Route { + return mux.HandleFunc("DELETE", path, f) } -func (mux *RestMux) Patch(path string, f func(http.ResponseWriter, *http.Request)) { - mux.HandleFunc("PATCH", path, f) +func (mux *RestMux) Patch(path string, f func(http.ResponseWriter, *http.Request)) *Route { + return mux.HandleFunc("PATCH", path, f) } -func (mux *RestMux) Head(path string, f func(http.ResponseWriter, *http.Request)) { - mux.HandleFunc("HEAD", path, f) +func (mux *RestMux) Head(path string, f func(http.ResponseWriter, *http.Request)) *Route { + return mux.HandleFunc("HEAD", path, f) } -func (mux *RestMux) Option(path string, f func(http.ResponseWriter, *http.Request)) { - mux.HandleFunc("OPTION", path, f) +func (mux *RestMux) Option(path string, f func(http.ResponseWriter, *http.Request)) *Route { + return mux.HandleFunc("OPTION", path, f) } -func (mux *RestMux) HandleMux(nmux *RestMux) { +func (mux *RestMux) HandleMux(nmux *RestMux) *Route { p := nmux.Path if !strings.HasSuffix(p, "/") { p = p + "/" } - // mux.imux.Handle(p, http.StripPrefix(nmux.Path, nmux)) - // mux.rmuxPaths = append(mux.rmuxPaths, nmux.Path) - r := &Route{ - Method: "", - Path: p, - Handle: nil, - Handler: nmux, - } - r.matcher = &UrlParamMatcher{ - Params: []string{}, - Reg: nil, - } + r := NewRoute("", p, nmux) + mux.routes = append(mux.routes, r) sort.Sort(mux.routes) + return r } func NewRestMux(path string) *RestMux { ret := &RestMux{ Path: path, routes: Routes{}, - middlewares: []Middleware{}, + middlewares: NewMiddlewareLink(), } return ret }