-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathhandle.go
More file actions
171 lines (148 loc) · 5.42 KB
/
handle.go
File metadata and controls
171 lines (148 loc) · 5.42 KB
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package ming
import (
"fmt"
"strings"
"github.com/valyala/fasthttp"
)
// Handle registers a new request handler with the given path and method.
//
// For GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS, TRACE and CONNECT requests,
// the respective shortcut methods can be used.
//
// This function is intended for bulk loading and to allow the usage of less
// frequently used, non-standardized or custom methods (e.g. for internal
// communication with a proxy).
func (r *Router) Handle(method, path string, handler fasthttp.RequestHandler) {
if !strings.HasPrefix(path, "/") {
panic("path must begin with \"/\" in \"" + path + "\"")
}
if r.trees == nil {
r.trees = make(map[string]*Tree)
}
tree := r.trees[method]
if tree == nil {
tree = NewTree(method)
r.trees[method] = tree
}
tree.addRoute(path, handler)
}
// Handler handles all requests for the router.
// It implements the fasthttp.RequestHandler interface.
func (r *Router) Handler(ctx *fasthttp.RequestCtx) {
if r.PanicHandler != nil {
defer r.recv(ctx)
}
path := string(ctx.Path())
method := GetMethod(ctx)
if tree := r.trees[method]; tree != nil {
if handler, params, tsr := tree.getValue(path, method); handler != nil {
// Set parameters in context
for _, param := range params {
ctx.SetUserValue(param.Key, param.Value)
}
handler(ctx)
return
} else if tsr && method != fasthttp.MethodConnect {
// Handle trailing slash redirect
var redirectPath string
if len(path) > 1 && path[len(path)-1] == '/' {
redirectPath = path[:len(path)-1]
} else {
redirectPath = path + "/"
}
ctx.Response.Header.Set("Location", redirectPath)
ctx.SetStatusCode(fasthttp.StatusMovedPermanently)
return
}
}
// Try ALL method as fallback
if tree := r.trees["ALL"]; tree != nil {
if handler, params, _ := tree.getValue(path, "ALL"); handler != nil {
// Set parameters in context
for _, param := range params {
ctx.SetUserValue(param.Key, param.Value)
}
handler(ctx)
return
}
}
// Check if method is allowed for this path
allowed := make([]string, 0, len(r.trees))
for m, tree := range r.trees {
if m == method || m == "ALL" {
continue
}
if handler, _, _ := tree.getValue(path, m); handler != nil {
allowed = append(allowed, m)
}
}
if len(allowed) > 0 {
allowHeader := strings.Join(allowed, ", ")
if r.MethodNotAllowed != nil {
ctx.Response.Header.Set("Allow", allowHeader)
r.MethodNotAllowed(ctx)
} else {
ctx.Error("Method Not Allowed", fasthttp.StatusMethodNotAllowed)
ctx.Response.Header.Set("Allow", allowHeader)
}
return
}
// Not found
if r.NotFound != nil {
r.NotFound(ctx)
} else {
ctx.Error(fmt.Sprintf("%s %s not found", method, path), fasthttp.StatusNotFound)
}
}
// Get registers a route for GET requests to the specified path with the provided handler.
func (r *Router) Get(path string, handler fasthttp.RequestHandler) {
r.Handle(fasthttp.MethodGet, path, handler)
}
// Head registers a route for HEAD requests to the specified path with the provided handler.
func (r *Router) Head(path string, handler fasthttp.RequestHandler) {
r.Handle(fasthttp.MethodHead, path, handler)
}
// Post registers a route for POST requests to the specified path with the provided handler.
func (r *Router) Post(path string, handler fasthttp.RequestHandler) {
r.Handle(fasthttp.MethodPost, path, handler)
}
// Put registers a route for PUT requests to the specified path with the provided handler.
func (r *Router) Put(path string, handler fasthttp.RequestHandler) {
r.Handle(fasthttp.MethodPut, path, handler)
}
// Patch registers a route for PATCH requests to the specified path with the provided handler.
func (r *Router) Patch(path string, handler fasthttp.RequestHandler) {
r.Handle(fasthttp.MethodPatch, path, handler)
}
// Delete registers a route for DELETE requests to the specified path with the provided handler.
func (r *Router) Delete(path string, handler fasthttp.RequestHandler) {
r.Handle(fasthttp.MethodDelete, path, handler)
}
// Connect registers a route for CONNECT requests to the specified path with the provided handler.
func (r *Router) Connect(path string, handler fasthttp.RequestHandler) {
r.Handle(fasthttp.MethodConnect, path, handler)
}
// Options registers a route for OPTIONS requests to the specified path with the provided handler.
func (r *Router) Options(path string, handler fasthttp.RequestHandler) {
r.Handle(fasthttp.MethodOptions, path, handler)
}
// Trace registers a route for TRACE requests to the specified path with the provided handler.
func (r *Router) Trace(path string, handler fasthttp.RequestHandler) {
r.Handle(fasthttp.MethodTrace, path, handler)
}
// All registers a route that matches all HTTP methods for the specified path with the provided handler.
// This is useful for routes that need to respond to multiple HTTP methods with the same logic.
func (r *Router) All(path string, handler fasthttp.RequestHandler) {
r.Handle("ALL", path, handler)
}
// Static configures the router to serve static files from the specified directory.
// The rootPath parameter specifies the root directory from which to serve files.
// When IsIndexPage is true, directory listings will be generated for directories that don't have an index file.
func (r *Router) Static(rootPath string, IsIndexPage bool) {
fs := &fasthttp.FS{
Root: rootPath,
IndexNames: []string{"index.html"},
GenerateIndexPages: IsIndexPage,
}
r.NotFound = fs.NewRequestHandler()
}