refactor route
This commit is contained in:
parent
d6752cd324
commit
18e319b407
|
@ -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
|
||||||
|
|
134
server/server.go
134
server/server.go
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue