-
Notifications
You must be signed in to change notification settings - Fork 7
/
option.go
136 lines (116 loc) · 4.6 KB
/
option.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
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
// SPDX-License-Identifier: MIT
package mux
import (
"io"
"log"
"net/http"
"github.com/issue9/source"
"github.com/issue9/mux/v7/internal/options"
"github.com/issue9/mux/v7/internal/syntax"
)
type (
RecoverFunc = options.RecoverFunc
Option = options.Option
)
// Lock 是否加锁
//
// 在调用 [RouterOf.Handle] 等添加路由时,有可能会改变整个路由树的结构,
// 如果需要频繁在运行时添加和删除路由项,那么应当添加此选项。
func Lock(l bool) Option { return func(o *options.Options) { o.Lock = l } }
// URLDomain 为 [RouterOf.URL] 生成的地址带上域名
func URLDomain(prefix string) Option {
return func(o *options.Options) { o.URLDomain = prefix }
}
// Recovery 用于指路由 panic 之后的处理方法
//
// 如果多次指定,则最后一次启作用。
func Recovery(f RecoverFunc) Option {
return func(o *options.Options) { o.RecoverFunc = f }
}
// StatusRecovery 仅向客户端输出 status 状态码
func StatusRecovery(status int) Option {
return Recovery(func(w http.ResponseWriter, msg any) {
http.Error(w, http.StatusText(status), status)
})
}
// WriterRecovery 向 [io.Writer] 输出错误信息
//
// status 表示向客户端输出的状态码;
// out 表示输出通道,比如 [os.Stderr] 等;
func WriterRecovery(status int, out io.Writer) Option {
return Recovery(func(w http.ResponseWriter, msg any) {
http.Error(w, http.StatusText(status), status)
source.DumpStack(out, 4, msg)
})
}
// LogRecovery 将错误信息输出到日志
//
// status 表示向客户端输出的状态码;
// l 为输出的日志;
func LogRecovery(status int, l *log.Logger) Option {
return Recovery(func(w http.ResponseWriter, msg any) {
http.Error(w, http.StatusText(status), status)
l.Println(source.Stack(4, msg))
})
}
type InterceptorFunc = syntax.InterceptorFunc
// Interceptor 针对带参数类型路由的拦截处理
//
// 在解析诸如 /authors/{id:\\d+} 带参数的路由项时,
// 用户可以通过拦截并自定义对参数部分 {id:\\d+} 的解析,
// 从而不需要走正则表达式的那一套解析流程,可以在一定程度上增强性能。
//
// 一旦正则表达式被拦截,则节点类型也将不再是正则表达式,
// 其处理优先级会比正则表达式类型高。 在某些情况下,可能会造成处理结果不相同。比如:
//
// /authors/{id:\\d+} // 1
// /authors/{id:[0-9]+} // 2
//
// 以上两条记录是相同的,但因为表达式不同,也能正常添加,
// 处理流程,会按添加顺序优先比对第一条,所以第二条是永远无法匹配的。
// 但是如果你此时添加了 (InterceptorDigit, "[0-9]+"),
// 使第二个记录的优先级提升,会使第一条永远无法匹配到数据。
//
// 可多次调用,表示同时指定了多个。
func Interceptor(f InterceptorFunc, rule ...string) Option {
return func(o *options.Options) { o.Interceptors.Add(f, rule...) }
}
// AnyInterceptor 任意非空字符的拦截器
func AnyInterceptor(rule string) Option { return Interceptor(syntax.MatchAny, rule) }
// DigitInterceptor 任意数字字符的拦截器
func DigitInterceptor(rule string) Option { return Interceptor(syntax.MatchDigit, rule) }
// WordInterceptor 任意英文单词的拦截器
func WordInterceptor(rule string) Option { return Interceptor(syntax.MatchWord, rule) }
// CORS 自定义[跨域请求]设置项
//
// origin 对应 Origin 报头。如果包含了 *,那么其它的设置将不再启作用。
// 如果此值为空,表示不启用跨域的相关设置;
//
// allowHeaders 对应 Access-Control-Allow-Headers
// 可以包含 *,表示可以是任意值,其它值将不再启作用;
//
// exposedHeaders 对应 Access-Control-Expose-Headers;
//
// maxAge 对应 Access-Control-Max-Age 有以下几种取值:
// - 0 不输出该报头;
// - -1 表示禁用;
// - 其它 >= -1 的值正常输出数值;
//
// allowCredentials 对应 Access-Control-Allow-Credentials;
//
// [跨域请求]: https://developer.mozilla.org/zh-CN/docs/Web/HTTP/cors
func CORS(origin []string, allowHeaders []string, exposedHeaders []string, maxAge int, allowCredentials bool) Option {
return func(o *options.Options) {
o.CORS = &options.CORS{
Origins: origin,
AllowHeaders: allowHeaders,
ExposedHeaders: exposedHeaders,
MaxAge: maxAge,
AllowCredentials: allowCredentials,
}
}
}
// DenyCORS 禁用跨域请求
func DenyCORS() Option { return CORS(nil, nil, nil, 0, false) }
// AllowedCORS 允许跨域请求
func AllowedCORS(maxAge int) Option { return CORS([]string{"*"}, []string{"*"}, nil, maxAge, false) }