-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathmux_router.go
161 lines (133 loc) · 6.09 KB
/
mux_router.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
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
// Copyright 2021-2024 Nokia
// Licensed under the BSD 3-Clause License.
// SPDX-License-Identifier: BSD-3-Clause
package restful
import (
"net/http"
"github.com/gorilla/mux"
)
var (
// OwnTLSCert is the own TLS certificate used by server on StartTLS. Default is "/etc/own-tls/tls.crt".
OwnTLSCert string = "/etc/own-tls/tls.crt"
// OwnTLSKey is the own TLS private key used by servert on StartTLS. Default is "/etc/own-tls/tls.key".
OwnTLSKey string = "/etc/own-tls/tls.key"
// ClientCAs is a path of client certificate authorities, to be verified by the server on StartTLS on mTLS. Default is "/etc/clientcas".
ClientCAs string = "/etc/clientcas"
// AddrHTTP is the listening address / port of HTTP for Start / StartTLS. Default is ":8080"
AddrHTTP = ":8080"
// AddrHTTPS is the listening address / port of HTTPS for StartTLS. Default is ":8443"
AddrHTTPS = ":8443"
)
// Router routes requests to lambda functions.
type Router struct {
router *mux.Router
monitors monitors
}
// NewRouter creates new Router instance.
func NewRouter() *Router {
return &Router{router: mux.NewRouter()}
}
// Monitor wraps handler function, creating a middleware in a safe and convenient fashion.
// It adds pre and post functions to be called on serving a request.
func (r *Router) Monitor(pre MonitorFuncPre, post MonitorFuncPost) *Router {
r.monitors.append(pre, post)
return r
}
// HandleFunc assigns an HTTP path to a function.
// The function can be compatible with type http.HandlerFunc or a restful's Lambda.
// E.g. r.HandleFunc("/users/{id:[0-9]+}", myFunc)
func (r *Router) HandleFunc(path string, f any) *Route {
return r.Handle(path, LambdaWrap(f))
}
// Handle adds traditional http.Handler to route.
// Cannot use Lambda here.
func (r *Router) Handle(path string, handler http.Handler) *Route {
wrapped := r.monitors.wrap(handler)
return newRoute(r.router.Handle(path, wrapped), nil)
}
// Get returns the route registered with the given name, or nil.
func (r *Router) Get(name string) *Route {
return newRoute(r.router.Get(name), r.monitors)
}
// Host registers a new route with a matcher for the URL host regex.
// E.g. r.Host("{subdomain:[a-z]+}.example.com")
func (r *Router) Host(hostRegex string) *Route {
return newRoute(r.router.Host(hostRegex), r.monitors)
}
// Methods registers a new route with a matcher for HTTP methods.
// E.g. r.Methods(http.MethodPost, http.MethodPut)
func (r *Router) Methods(methods ...string) *Route {
return newRoute(r.router.Methods(methods...), r.monitors)
}
// Name registers a new route with a name.
// That name can be used to query route.
func (r *Router) Name(name string) *Route {
return newRoute(r.router.Name(name), r.monitors)
}
// Path registers a new route with a matcher for the URL path template.
// E.g. r.Path("/users/{id:[0-9]+}")
func (r *Router) Path(pathTemplate string) *Route {
return newRoute(r.router.Path(pathTemplate), r.monitors)
}
// PathPrefix registers a new route with a matcher for the URL path template prefix.
func (r *Router) PathPrefix(pathTemplate string) *Route {
return newRoute(r.router.PathPrefix(pathTemplate), r.monitors)
}
// Queries registers a new route with a matcher for URL query values.
//
// router.Queries("id", "{id:[0-9]+}")
//
// The odd (1st, 3rd, etc) string is the query parameter.
// The even (2nd, 4th, etc) string is the variable name and optional regex pattern.
func (r *Router) Queries(pairs ...string) *Route {
return newRoute(r.router.Queries(pairs...), r.monitors)
}
// Schemes registers a new route with a matcher for URL schemes.
func (r *Router) Schemes(schemes ...string) *Route {
return newRoute(r.router.Schemes(schemes...), r.monitors)
}
// Start starts router on port 8080 (AddrHTTP).
// Logs, except for automatically served LivenessProbePath and HealthCheckPath.
// Handles connections gracefully on TERM/INT signals.
func (r *Router) Start() error {
return NewServer().Addr(AddrHTTP).Handler(r).Graceful(0).ListenAndServe()
}
// StartTLS starts router for TLS on port 8443 (AddrHTTPS) and for cleartext on port 8080 (AddrHTTP), if allowed.
// TLS cert must be at OwnTLSCert and key at OwnTLSKey.
// If mutualTLS=true, then client certs must be provided; see variable ClientCAs.
// If loadSystemCerts is true, clients with CA from system CA pool are accepted, too.
// As the role of mTLS is to authorize certain clients to connect, enable system CAs only if those are reasonable for auth.
// Logs, except for automatically served LivenessProbePath and HealthCheckPath.
// Handles connections gracefully on TERM/INT signals.
func (r *Router) StartTLS(cleartext, mutualTLS bool, loadSystemCerts bool) error {
if cleartext {
go r.Start()
}
s := NewServer().Addr(AddrHTTPS).Handler(r).Graceful(0).TLSServerCert(OwnTLSCert, OwnTLSKey)
if mutualTLS {
s = s.TLSClientCert(ClientCAs, loadSystemCerts)
}
return s.ListenAndServe()
}
// ListenAndServe starts router listening on given address.
// Logs, except for automatically served LivenessProbePath and HealthCheckPath.
func (r *Router) ListenAndServe(addr string) error {
return ListenAndServe(addr, r)
}
// ListenAndServeTLS starts router listening on given address.
// Logs, except for automatically served LivenessProbePath and HealthCheckPath.
func (r *Router) ListenAndServeTLS(addr, certFile, keyFile string) error {
return ListenAndServeTLS(addr, certFile, keyFile, r)
}
// ListenAndServeMTLS starts router listening on given address.
// Parameter clientCerts is a PEM cert file or a directory of PEM cert files case insensitively matching *.pem or *.crt.
// If loadSystemCerts is true, clients with CA from system CA pool are accepted, too.
// As the role of mTLS is to authorize certain clients to connect, enable system CAs only if those are reasonable for auth.
// Logs, except for automatically served LivenessProbePath and HealthCheckPath.
func (r *Router) ListenAndServeMTLS(addr, certFile, keyFile, clientCerts string, loadSystemCerts bool) error {
return ListenAndServeMTLS(addr, certFile, keyFile, clientCerts, loadSystemCerts, r)
}
// ServeHTTP serves HTTP request with matching handler.
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
r.router.ServeHTTP(w, req)
}