refactor route

This commit is contained in:
kingecg 2023-12-12 00:42:21 +08:00
parent d6752cd324
commit 18e319b407
2 changed files with 116 additions and 34 deletions

View File

@ -6,12 +6,6 @@ import (
"git.pyer.club/kingecg/gohttpd/server" "git.pyer.club/kingecg/gohttpd/server"
) )
type Route struct {
Method string
Path string
Handle http.HandlerFunc
}
func about(w http.ResponseWriter, r *http.Request) { func about(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
w.Write([]byte("About Page")) w.Write([]byte("About Page"))
@ -22,10 +16,10 @@ func setConfig(w http.ResponseWriter, r *http.Request) {
} }
var AdminRoutes = []Route{ var AdminRoutes = []server.Route{
// Admin Routes // Admin Routes
{"GET", "/about", about}, {Method: "GET", Path: "/about", Handle: about},
{"Post", "/config", setConfig}, {Method: "Post", Path: "/config", Handle: setConfig},
} }
var AdminServerMux *server.RestMux var AdminServerMux *server.RestMux

View File

@ -3,18 +3,82 @@ package server
import ( import (
"context" "context"
"net/http" "net/http"
"sort"
"strings" "strings"
"github.com/samber/lo"
) )
type RequestCtxKey string type RequestCtxKey string
type Route struct {
Method string
Path string
Handle http.HandlerFunc
Handler http.Handler
matcher *UrlParamMatcher
}
func (route *Route) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if route.Handler != nil {
route.Handler.ServeHTTP(w, r)
} else {
route.Handle(w, r)
}
}
func (route *Route) Match(r *http.Request) bool {
if route.Method != "" && route.Method != r.Method {
return false
}
if route.matcher != nil {
params, matched := MatchUrlParam(r.URL.Path, route.matcher)
if matched {
ctx := r.Context()
data := ctx.Value(RequestCtxKey("data")).(map[string]interface{})
for _, p := range route.matcher.Params {
data[p] = params[p]
}
return true
}
return false
}
if route.Path == "" {
return true
}
return strings.HasPrefix(r.URL.Path, route.Path)
}
type Routes []*Route
func (rs Routes) Less(i, j int) bool {
iPaths := strings.Split(rs[i].Path, "/")
jPaths := strings.Split(rs[j].Path, "/")
if len(iPaths) > len(jPaths) {
return true
}
if len(iPaths) < len(jPaths) {
return false
}
for k := 0; k < len(iPaths); k++ {
if iPaths[k] != jPaths[k] {
return iPaths[k] < jPaths[k]
}
}
return false
}
func (rs Routes) Len() int {
return len(rs)
}
func (rs Routes) Swap(i, j int) {
rs[i], rs[j] = rs[j], rs[i]
}
// 可以嵌套的Rest http server mux // 可以嵌套的Rest http server mux
type RestMux struct { type RestMux struct {
Path string Path string
imux *http.ServeMux routes Routes
rmuxPaths []string
middlewares []Middleware middlewares []Middleware
} }
@ -37,27 +101,39 @@ func (mux *RestMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
} }
} }
_, has := lo.Find(mux.rmuxPaths, func(s string) bool { // _, has := lo.Find(mux.rmuxPaths, func(s string) bool {
return strings.HasPrefix(newRequest.URL.Path, s) // return strings.HasPrefix(newRequest.URL.Path, s)
}) // })
if has { // if has {
mux.imux.ServeHTTP(w, newRequest) // mux.imux.ServeHTTP(w, newRequest)
// return
// }
// 根据r 从routes中找到匹配的路由
for _, route := range mux.routes {
if route.Match(newRequest) {
route.ServeHTTP(w, newRequest)
return return
} }
}
// newRequest.URL.Path = "/" + strings.ToLower(newRequest.Method) + newRequest.URL.Path
// newRequest.RequestURI = "/" + strings.ToLower(newRequest.Method) + newRequest.RequestURI
// h, _ := mux.imux.Handler(newRequest)
newRequest.URL.Path = "/" + strings.ToLower(newRequest.Method) + newRequest.URL.Path // h.ServeHTTP(w, newRequest)
newRequest.RequestURI = "/" + strings.ToLower(newRequest.Method) + newRequest.RequestURI http.NotFound(w, r)
h, _ := mux.imux.Handler(newRequest)
h.ServeHTTP(w, newRequest)
} }
func (mux *RestMux) HandleFunc(method string, path string, f func(http.ResponseWriter, *http.Request)) { func (mux *RestMux) HandleFunc(method string, path string, f func(http.ResponseWriter, *http.Request)) {
m := path r := &Route{
if !strings.HasPrefix(path, "/") { Method: method,
m = "/" + path Path: path,
Handle: f,
Handler: nil,
} }
mux.imux.HandleFunc("/"+strings.ToLower(method)+m, f) *r.matcher = ParseUrl(path)
mux.routes = append(mux.routes, r)
sort.Sort(mux.routes)
} }
func (mux *RestMux) Get(path string, f func(http.ResponseWriter, *http.Request)) { func (mux *RestMux) Get(path string, f func(http.ResponseWriter, *http.Request)) {
@ -90,14 +166,26 @@ func (mux *RestMux) HandleMux(nmux *RestMux) {
if !strings.HasSuffix(p, "/") { if !strings.HasSuffix(p, "/") {
p = p + "/" p = p + "/"
} }
mux.imux.Handle(p, http.StripPrefix(nmux.Path, nmux)) // mux.imux.Handle(p, http.StripPrefix(nmux.Path, nmux))
mux.rmuxPaths = append(mux.rmuxPaths, nmux.Path) // mux.rmuxPaths = append(mux.rmuxPaths, nmux.Path)
r := &Route{
Method: "",
Path: p,
Handle: nil,
Handler: nmux,
}
r.matcher = &UrlParamMatcher{
Params: []string{},
Reg: nil,
}
sort.Sort(mux.routes)
} }
func NewRestMux(path string) *RestMux { func NewRestMux(path string) *RestMux {
return &RestMux{ ret := &RestMux{
Path: path, Path: path,
imux: http.NewServeMux(), routes: Routes{},
rmuxPaths: make([]string, 0), middlewares: []Middleware{},
} }
return ret
} }