gohttp/server/server.go

331 lines
8.9 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-13 09:22:05 +08:00
"fmt"
2023-12-07 22:42:27 +08:00
"net/http"
2023-12-12 00:42:21 +08:00
"sort"
2023-12-07 22:42:27 +08:00
"strings"
2023-12-13 09:22:05 +08:00
2023-12-17 10:33:29 +08:00
handler "git.pyer.club/kingecg/gohttpd/handler"
"git.pyer.club/kingecg/gohttpd/model"
logger "git.pyer.club/kingecg/gologger"
2023-12-07 22:42:27 +08:00
)
2023-12-11 23:46:40 +08:00
type RequestCtxKey string
2023-12-12 00:42:21 +08:00
type Route struct {
Method string
Path string
Handler http.Handler
matcher *UrlParamMatcher
2023-12-12 21:44:35 +08:00
middles *MiddlewareLink
2025-02-18 00:54:50 +08:00
wrapped bool
2023-12-12 00:42:21 +08:00
}
func (route *Route) ServeHTTP(w http.ResponseWriter, r *http.Request) {
2025-02-18 00:54:50 +08:00
if route.wrapped == false {
route.Handler = route.middles.WrapHandler(route.Handler)
route.wrapped = true
2023-12-12 00:42:21 +08:00
}
2023-12-12 21:44:35 +08:00
route.Handler.ServeHTTP(w, r)
2023-12-12 00:42:21 +08:00
}
func (route *Route) Match(r *http.Request) bool {
2023-12-17 10:33:29 +08:00
l := logger.GetLogger("Route")
2023-12-13 09:22:05 +08:00
l.Debug(fmt.Sprintf("match route: %s %s", r.Method, r.URL.Path))
2023-12-12 00:42:21 +08:00
if route.Method != "" && route.Method != r.Method {
2023-12-13 09:22:05 +08:00
l.Debug("method not match")
2023-12-12 00:42:21 +08:00
return false
}
2023-12-13 09:22:05 +08:00
if route.matcher != nil && route.matcher.Reg != nil {
2023-12-12 00:42:21 +08:00
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
}
2023-12-13 09:22:05 +08:00
l.Debug("Not match matcher reg")
2023-12-12 00:42:21 +08:00
return false
}
if route.Path == "" {
return true
}
return strings.HasPrefix(r.URL.Path, route.Path)
}
2023-12-12 21:44:35 +08:00
func (route *Route) Add(m Middleware) {
route.middles.Add(m)
}
2023-12-12 22:58:30 +08:00
// NewRoute 返回一个新的Route实例
// 参数:
// - method: 请求方法
// - path: 请求路径
// - handleFn: http.Handler处理函数
// 返回值:
// - *Route: 一个指向Route的指针
2023-12-12 21:44:35 +08:00
func NewRoute(method string, path string, handleFn http.Handler) *Route {
ret := &Route{
Method: method,
Path: path,
middles: NewMiddlewareLink(),
2025-02-18 00:54:50 +08:00
wrapped: false,
2023-12-12 21:44:35 +08:00
}
p := ParseUrl(path)
2023-12-12 22:58:30 +08:00
// 使用handleFn构建handler
2023-12-12 21:44:35 +08:00
ret.Handler = handleFn
ret.matcher = &p
return ret
}
2023-12-12 00:42:21 +08:00
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]
}
2023-12-07 22:42:27 +08:00
// 可以嵌套的Rest http server mux
type RestMux struct {
2025-02-18 00:54:50 +08:00
Path string
routes Routes
middlewares *MiddlewareLink
wrapperHandler http.Handler
2023-12-07 22:42:27 +08:00
}
2023-12-11 18:15:29 +08:00
func (mux *RestMux) Use(m Middleware) {
2023-12-12 21:44:35 +08:00
mux.middlewares.Add(m)
2023-12-11 18:15:29 +08:00
}
2023-12-07 22:42:27 +08:00
func (mux *RestMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
2025-02-18 00:54:50 +08:00
if mux.wrapperHandler == nil {
mux.wrapperHandler = mux.middlewares.WrapHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
for _, route := range mux.routes {
if route.Match(r) {
route.ServeHTTP(w, r)
return
}
}
2023-12-12 21:44:35 +08:00
2025-02-18 00:54:50 +08:00
http.NotFound(w, r)
}))
2023-12-12 21:44:35 +08:00
return
2023-12-11 18:15:29 +08:00
}
2025-02-18 00:54:50 +08:00
mux.wrapperHandler.ServeHTTP(w, r)
// c := r.Context()
// newRequest := r
// if t := c.Value("data"); t == nil {
// data := map[string]interface{}{}
// cn := context.WithValue(c, RequestCtxKey("data"), data)
// newRequest = r.WithContext(cn)
// }
// if mux.middlewares.Len() > 0 && !mux.middlewares.ServeHTTP(w, newRequest) {
// return
// }
2023-12-11 18:15:29 +08:00
2023-12-12 00:42:21 +08:00
// 根据r 从routes中找到匹配的路由
2023-12-07 22:42:27 +08:00
}
2023-12-12 21:44:35 +08:00
func (mux *RestMux) HandleFunc(method string, path string, f func(http.ResponseWriter, *http.Request)) *Route {
r := NewRoute(method, path, http.HandlerFunc(f))
2023-12-12 00:42:21 +08:00
mux.routes = append(mux.routes, r)
sort.Sort(mux.routes)
2023-12-12 21:44:35 +08:00
return r
2023-12-07 22:42:27 +08:00
}
2023-12-12 21:44:35 +08:00
func (mux *RestMux) Get(path string, f func(http.ResponseWriter, *http.Request)) *Route {
return mux.HandleFunc("GET", path, f)
2023-12-07 22:42:27 +08:00
}
2023-12-12 21:44:35 +08:00
func (mux *RestMux) Post(path string, f func(http.ResponseWriter, *http.Request)) *Route {
return mux.HandleFunc("POST", path, f)
2023-12-07 22:42:27 +08:00
}
2023-12-12 21:44:35 +08:00
func (mux *RestMux) Put(path string, f func(http.ResponseWriter, *http.Request)) *Route {
return mux.HandleFunc("PUT", path, f)
2023-12-07 22:42:27 +08:00
}
2023-12-12 21:44:35 +08:00
func (mux *RestMux) Delete(path string, f func(http.ResponseWriter, *http.Request)) *Route {
return mux.HandleFunc("DELETE", path, f)
2023-12-07 22:42:27 +08:00
}
2023-12-12 21:44:35 +08:00
func (mux *RestMux) Patch(path string, f func(http.ResponseWriter, *http.Request)) *Route {
return mux.HandleFunc("PATCH", path, f)
2023-12-07 22:42:27 +08:00
}
2023-12-12 21:44:35 +08:00
func (mux *RestMux) Head(path string, f func(http.ResponseWriter, *http.Request)) *Route {
return mux.HandleFunc("HEAD", path, f)
2023-12-07 22:42:27 +08:00
}
2023-12-12 21:44:35 +08:00
func (mux *RestMux) Option(path string, f func(http.ResponseWriter, *http.Request)) *Route {
return mux.HandleFunc("OPTION", path, f)
2023-12-07 22:42:27 +08:00
}
2023-12-12 21:44:35 +08:00
func (mux *RestMux) HandleMux(nmux *RestMux) *Route {
2023-12-07 22:42:27 +08:00
p := nmux.Path
if !strings.HasSuffix(p, "/") {
p = p + "/"
}
2023-12-12 21:44:35 +08:00
r := NewRoute("", p, nmux)
mux.routes = append(mux.routes, r)
2023-12-12 00:42:21 +08:00
sort.Sort(mux.routes)
2023-12-12 21:44:35 +08:00
return r
2023-12-07 22:42:27 +08:00
}
func NewRestMux(path string) *RestMux {
2023-12-12 00:42:21 +08:00
ret := &RestMux{
Path: path,
routes: Routes{},
2023-12-12 21:44:35 +08:00
middlewares: NewMiddlewareLink(),
2023-12-07 22:42:27 +08:00
}
2023-12-12 00:42:21 +08:00
return ret
2023-12-07 22:42:27 +08:00
}
type ServerMux struct {
http.Handler
directiveHandlers *MiddlewareLink
handlers map[string]http.Handler
paths []string
2023-12-21 18:36:51 +08:00
wrappedHandler map[string]http.Handler
}
func (s *ServerMux) Handle(pattern string, handler http.Handler) {
if s.handlers == nil {
s.handlers = make(map[string]http.Handler)
}
2025-02-18 00:54:50 +08:00
s.handlers[pattern] = s.directiveHandlers.WrapHandler(handler)
s.paths = append(s.paths, pattern)
// 自定义比较函数排序s.paths
sort.Slice(s.paths, func(i, j int) bool {
return len(s.paths[i]) > len(s.paths[j]) || s.paths[i] > s.paths[j]
})
}
func (s *ServerMux) AddDirective(directiveStr string) {
2023-12-15 21:45:04 +08:00
l := logger.GetLogger("ServerMux")
strs := strings.Split(directiveStr, " ")
directiveName := strs[0]
params := strs[1:]
directive, ok := DirectiveMap[directiveName]
if ok {
2023-12-15 21:45:04 +08:00
l.Debug(fmt.Sprintf("add directive: %s", directiveName))
s.directiveHandlers.Add(directive(params...))
2023-12-15 21:45:04 +08:00
} else {
l.Error(fmt.Sprintf("directive not found: %s", directiveName))
}
}
func (s *ServerMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
2023-12-20 17:49:02 +08:00
l := logger.GetLogger("Access")
2023-12-21 18:36:51 +08:00
data := map[string]interface{}{}
c := r.Context()
cn := context.WithValue(c, RequestCtxKey("data"), data)
newRequest := r.WithContext(cn)
2023-12-20 17:49:02 +08:00
l.Info(fmt.Sprintf("From %s-%s %s", r.RemoteAddr, r.Method, r.URL.Path))
for _, p := range s.paths {
if strings.HasPrefix(r.URL.Path, p) {
2023-12-15 21:45:04 +08:00
l.Info(fmt.Sprintf("match path: %s", p))
2025-02-18 00:54:50 +08:00
s.handlers[p].ServeHTTP(w, newRequest)
// s.directiveHandlers.ServeHTTP(w, newRequest)
// ctx := newRequest.Context()
// m := ctx.Value(RequestCtxKey("data")).(map[string]interface{})
// _, ok := m["Tg"]
// if ok {
// wrappedHandler := s.wrappedHandler[p]
// if wrappedHandler == nil {
// s.wrappedHandler[p] = gzip.DefaultHandler().WrapHandler(s.handlers[p])
// wrappedHandler = s.wrappedHandler[p]
// }
// wrappedHandler.ServeHTTP(w, newRequest)
// } else {
// s.handlers[p].ServeHTTP(w, newRequest)
// }
2023-12-21 18:36:51 +08:00
return
}
}
2023-12-20 17:49:02 +08:00
l.Error(fmt.Sprintf("404: %s", r.URL.Path))
2023-12-21 18:36:51 +08:00
http.NotFound(w, newRequest)
}
2025-02-18 00:54:50 +08:00
// NewServeMux 根据提供的 HTTP 服务器配置创建并返回一个新的 ServerMux 实例。
// 参数:
// - c: 指向 model.HttpServerConfig 结构体的指针,包含服务器的配置信息。
// 返回值:
// - *ServerMux: 一个指向 ServerMux 的指针,用于处理 HTTP 请求。
func NewServeMux(c *model.HttpServerConfig) *ServerMux {
2025-02-18 00:54:50 +08:00
// 获取名为 "ServerMux" 的日志记录器实例
l := logger.GetLogger("ServerMux")
2025-02-18 00:54:50 +08:00
// 记录创建 ServerMux 的调试信息
l.Debug("NewServeMux")
2025-02-18 00:54:50 +08:00
// 初始化一个新的 ServerMux 实例
s := &ServerMux{
2025-02-18 00:54:50 +08:00
// 初始化指令处理中间件链
directiveHandlers: NewMiddlewareLink(),
2025-02-18 00:54:50 +08:00
// 初始化处理程序映射
handlers: make(map[string]http.Handler),
// 初始化路径列表
paths: []string{},
// 初始化包装处理程序映射
wrappedHandler: make(map[string]http.Handler),
}
2025-02-18 00:54:50 +08:00
s.AddDirective("Record-Access")
// 遍历配置中的所有指令
for _, directive := range c.Directives {
2025-02-18 00:54:50 +08:00
// 将指令添加到 ServerMux 的指令处理中间件链中
s.AddDirective(string(directive))
}
2025-02-18 00:54:50 +08:00
// 遍历配置中的所有 HTTP 路径
for _, httpPath := range c.Paths {
2025-02-18 00:54:50 +08:00
// 检查路径配置中是否指定了根目录
if httpPath.Root != "" {
2025-02-18 00:54:50 +08:00
// 创建一个新的文件处理程序
fileHandler := handler.NewFileHandler(handler.FileHandler{
2025-02-18 00:54:50 +08:00
// 设置文件处理程序的根目录
Root: httpPath.Root,
// 设置文件处理程序的默认文件
Default: httpPath.Default,
})
2025-02-18 00:54:50 +08:00
// 将文件处理程序注册到 ServerMux 中
s.Handle(httpPath.Path, fileHandler)
2025-02-18 00:54:50 +08:00
// 检查路径配置中是否指定了上游服务器
} else if len(httpPath.Upstreams) != 0 {
2025-02-18 00:54:50 +08:00
// 创建一个新的代理处理程序
proxyHandler := handler.NewProxyHandler(&httpPath)
2025-02-18 00:54:50 +08:00
// 将代理处理程序注册到 ServerMux 中
s.Handle(httpPath.Path, proxyHandler)
2025-02-18 00:54:50 +08:00
// 如果既没有指定根目录也没有指定上游服务器
} else {
2025-02-18 00:54:50 +08:00
// 记录不支持的路径类型错误信息
l.Error("Not supportted server path type :", httpPath.Path)
}
}
2025-02-18 00:54:50 +08:00
// 返回初始化好的 ServerMux 实例
return s
}