gohttp/server/server.go

104 lines
2.6 KiB
Go
Raw Normal View History

2023-12-07 22:42:27 +08:00
package server
import (
2023-12-11 23:46:40 +08:00
"context"
2023-12-07 22:42:27 +08:00
"net/http"
"strings"
"github.com/samber/lo"
)
2023-12-11 23:46:40 +08:00
type RequestCtxKey string
2023-12-07 22:42:27 +08:00
// 可以嵌套的Rest http server mux
type RestMux struct {
2023-12-11 18:15:29 +08:00
Path string
imux *http.ServeMux
rmuxPaths []string
middlewares []Middleware
2023-12-07 22:42:27 +08:00
}
2023-12-11 18:15:29 +08:00
func (mux *RestMux) Use(m Middleware) {
mux.middlewares = append(mux.middlewares, m)
}
2023-12-07 22:42:27 +08:00
func (mux *RestMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
2023-12-11 18:15:29 +08:00
canContinue := false
2023-12-11 23:46:40 +08:00
c := r.Context()
data := map[string]interface{}{}
cn := context.WithValue(c, RequestCtxKey("data"), data)
newRequest := r.WithContext(cn)
2023-12-11 18:15:29 +08:00
if len(mux.middlewares) > 0 {
for _, m := range mux.middlewares {
canContinue = false
2023-12-11 23:46:40 +08:00
m(w, newRequest, func() { canContinue = true })
2023-12-11 18:15:29 +08:00
if !canContinue {
return
}
}
}
2023-12-08 22:02:36 +08:00
_, has := lo.Find(mux.rmuxPaths, func(s string) bool {
2023-12-11 23:46:40 +08:00
return strings.HasPrefix(newRequest.URL.Path, s)
2023-12-07 22:42:27 +08:00
})
if has {
2023-12-11 23:46:40 +08:00
mux.imux.ServeHTTP(w, newRequest)
2023-12-07 22:42:27 +08:00
return
}
2023-12-11 23:46:40 +08:00
newRequest.URL.Path = "/" + strings.ToLower(newRequest.Method) + newRequest.URL.Path
newRequest.RequestURI = "/" + strings.ToLower(newRequest.Method) + newRequest.RequestURI
h, _ := mux.imux.Handler(newRequest)
2023-12-07 22:42:27 +08:00
2023-12-11 23:46:40 +08:00
h.ServeHTTP(w, newRequest)
2023-12-07 22:42:27 +08:00
}
func (mux *RestMux) HandleFunc(method string, path string, f func(http.ResponseWriter, *http.Request)) {
m := path
if !strings.HasPrefix(path, "/") {
m = "/" + path
}
mux.imux.HandleFunc("/"+strings.ToLower(method)+m, f)
}
func (mux *RestMux) Get(path string, f func(http.ResponseWriter, *http.Request)) {
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) Put(path string, f func(http.ResponseWriter, *http.Request)) {
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) Patch(path string, f func(http.ResponseWriter, *http.Request)) {
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) Option(path string, f func(http.ResponseWriter, *http.Request)) {
mux.HandleFunc("OPTION", path, f)
}
func (mux *RestMux) HandleMux(nmux *RestMux) {
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)
}
func NewRestMux(path string) *RestMux {
return &RestMux{
Path: path,
imux: http.NewServeMux(),
rmuxPaths: make([]string, 0),
}
}