-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.go
108 lines (92 loc) · 2.71 KB
/
server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package evohttp
import (
"context"
"github.com/ethanvc/evo/base"
"net/http"
)
type Server struct {
*RouterBuilder
noRouteChain HandlerChain
userNoRouteChain HandlerChain
}
func NewServer() *Server {
svr := &Server{
noRouteChain: []Handler{HandlerFunc(defaultNoRouteHandler)},
}
svr.RouterBuilder = NewRouterBuilder()
svr.Use(NewLogHandler(), NewCodecHandler(), NewRecoverHandler())
return svr
}
func (svr *Server) Use(handlers ...Handler) {
svr.RouterBuilder.Use(handlers...)
svr.rebuildNoRouteHandlers()
}
func (svr *Server) UseF(handlers ...HandlerFunc) {
svr.Use(funcToHandlers(handlers)...)
}
func (svr *Server) NoRoute(handler ...Handler) {
svr.userNoRouteChain = append(svr.userNoRouteChain, handler...)
svr.rebuildNoRouteHandlers()
}
func (svr *Server) Run(addr string) {
err := http.ListenAndServe(addr, http.HandlerFunc(svr.ServeHTTP))
if err != nil {
panic(err)
}
}
func (svr *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
params := make(map[string]string)
n := svr.FindRoute(req.Method, req.URL.Path, params)
svr.ServeHTTPRouted(n, params, w, req)
}
func (svr *Server) FindRoute(method, urlPath string, params map[string]string) *RouteNode {
return svr.router.Find(method, urlPath, params)
}
func (svr *Server) ServeHTTPRouted(n *RouteNode, params map[string]string, w http.ResponseWriter, req *http.Request) {
info := NewRequestInfo()
info.Request = req
info.Writer.Reset(w)
info.UrlParams = params
c := context.WithValue(req.Context(), contextKeyRequestInfo{}, info)
var h HandlerChain
if n != nil {
h = n.Handlers
info.PatternPath = n.FullPath
} else {
h = svr.noRouteChain
}
h.Do(c, nil, info)
if info.Writer.GetStatus() == 0 {
info.Writer.WriteHeader(http.StatusInternalServerError)
info.Writer.Write([]byte("internal server error"))
}
}
func (svr *Server) rebuildNoRouteHandlers() {
svr.noRouteChain = nil
svr.noRouteChain = append(svr.noRouteChain, svr.RouterBuilder.handlers...)
if len(svr.userNoRouteChain) == 0 {
svr.noRouteChain = append(svr.noRouteChain, HandlerFunc(defaultNoRouteHandler))
} else {
svr.noRouteChain = append(svr.noRouteChain, svr.userNoRouteChain...)
}
}
func FindGlobalHandler[T Handler](s *Server) T {
for _, v := range s.RouterBuilder.handlers {
vv, ok := v.(T)
if ok {
return vv
}
}
var nilVal T
return nilVal
}
type Handler = base.Interceptor[*RequestInfo]
type HandlerChain = base.Chain[*RequestInfo]
type HandlerFunc = base.InterceptorFunc[*RequestInfo]
func defaultNoRouteHandler(c context.Context, req any, info *RequestInfo, nexter base.Nexter[*RequestInfo]) (resp any, err error) {
resp, err = nexter.Next(c, req, info)
if info.Writer.GetStatus() == 0 {
info.Writer.WriteHeader(http.StatusNotFound)
}
return
}