-
Notifications
You must be signed in to change notification settings - Fork 0
/
mux.go
87 lines (77 loc) · 2.62 KB
/
mux.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
package multiplexer
import (
"net/http"
"reflect"
"regexp"
"strings"
)
// reGo122 is a compiled regular expression used to match and extract two groups from a string pattern.
var reGo122 = regexp.MustCompile(`^(\S*)\s+(.*)$`)
// Router represents a multiplexer that routes incoming HTTP requests.
type Router struct {
mux *http.ServeMux
path string
NotFound http.Handler
MethodNotAllowed http.Handler
}
// New creates a new instance of the Router struct.
// It initializes the mux field with a new instance of http.ServeMux.
// Returns a pointer to the newly created Router.
func New(mux *http.ServeMux, basePath string) *Router {
return &Router{
mux: mux,
path: basePath,
}
}
// ServeHTTP implements the http.Handler interface.
// It calls the ServeHTTP method of the underlying http.ServeMux.
// It also handles the custom NotFound and MethodNotAllowed handlers.
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
path := req.URL.Path
if strings.HasSuffix(path, "/") {
req.URL.Path = path[:len(path)-1]
}
h, p := r.mux.Handler(req)
if p == "" {
if r.NotFound != nil && isDefaultNotFoundHandler(h) {
r.NotFound.ServeHTTP(w, req)
return
}
if r.MethodNotAllowed != nil && !isDefaultNotFoundHandler(h) {
r.MethodNotAllowed.ServeHTTP(w, req)
return
}
}
r.mux.ServeHTTP(w, req)
}
// Registers a route with the router, prepending base path for named capture groups.
// pattern (string): URL pattern with optional named capture groups (e.g., `/users/:id`).
// handler (http.HandlerFunc): Function to handle requests matching the pattern.
func (r *Router) register(pattern string, handler http.HandlerFunc) {
match := reGo122.FindStringSubmatch(pattern)
if len(match) > 2 {
pattern = match[1] + " " + r.path + match[2]
} else {
pattern = r.path + pattern
}
r.mux.HandleFunc(pattern, handler)
}
// HandleFunc adds a new route with the given pattern and handler function.
func (r *Router) HandleFunc(pattern string, handler http.HandlerFunc) {
r.register(pattern, handler)
}
// Handle adds a new route with the given pattern and handler.
func (r *Router) Handle(pattern string, handler http.Handler) {
r.register(pattern, handler.ServeHTTP)
}
// Group creates a new sub-router with the given path appended to the base path of the parent router.
func (r *Router) Group(subPath string) *Router {
return &Router{
mux: r.mux,
path: r.path + subPath,
}
}
// Returns true if the provided handler is the default NotFoundHandler.
func isDefaultNotFoundHandler(h http.Handler) bool {
return reflect.ValueOf(h).Pointer() == reflect.ValueOf(http.NotFoundHandler()).Pointer()
}