···88 "net/http"
99 "strings"
1010 "time"
1111+ "unicode"
11121213 "git.j3s.sh/cascade/lib"
1313- "git.j3s.sh/cascade/lib/cleanhttp"
1414)
15151616// MethodNotAllowedError should be returned by a handler when the HTTP method is not allowed.
···118118 }
119119120120 // This handler bans URLs with non-printable characters
121121- h := cleanhttp.PrintablePathCheckHandler(mux, nil)
121121+ h := printablePathCheckHandler(mux, nil)
122122 return h
123123+}
124124+125125+type HandlerInput struct {
126126+ ErrStatus int
127127+}
128128+129129+func printablePathCheckHandler(next http.Handler, input *HandlerInput) http.Handler {
130130+ // Nil-check on input to make it optional
131131+ if input == nil {
132132+ input = &HandlerInput{
133133+ ErrStatus: http.StatusBadRequest,
134134+ }
135135+ }
136136+137137+ // Default to http.StatusBadRequest on error
138138+ if input.ErrStatus == 0 {
139139+ input.ErrStatus = http.StatusBadRequest
140140+ }
141141+142142+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
143143+ if r != nil {
144144+ // Check URL path for non-printable characters
145145+ idx := strings.IndexFunc(r.URL.Path, func(c rune) bool {
146146+ return !unicode.IsPrint(c)
147147+ })
148148+149149+ if idx != -1 {
150150+ w.WriteHeader(input.ErrStatus)
151151+ return
152152+ }
153153+154154+ if next != nil {
155155+ next.ServeHTTP(w, r)
156156+ }
157157+ }
158158+159159+ return
160160+ })
123161}
124162125163// wrap is used to wrap functions to make them more convenient
+8
agent/service.go
···11+package agent
22+33+import "net"
44+55+type Service struct {
66+ Name string
77+ Addr *net.TCPAddr
88+}
+16-22
api/api.go
···1010 "net"
1111 "net/http"
1212 "net/url"
1313+ "runtime"
1314 "strconv"
1415 "strings"
1516 "sync"
1617 "time"
1717-1818- "git.j3s.sh/cascade/lib/cleanhttp"
1918)
20192120// Config is used to configure the creation of a client
···3938}
40394140// DefaultConfig returns a default configuration for the client. By default this
4242-// will pool and reuse idle connections to cascade. If you have a long-lived
4343-// client object, this is the desired behavior and should make the most efficient
4444-// use of the connections to cascade. If you don't reuse a client object, which
4545-// is not recommended, then you may notice idle connections building up over
4646-// time. To avoid this, use the DefaultNonPooledConfig() instead.
4141+// will pool and reuse idle connections to cascade.
4742func DefaultConfig() *Config {
4848- return defaultConfig(cleanhttp.DefaultPooledTransport)
4949-}
5050-5151-// DefaultNonPooledConfig returns a default configuration for the client which
5252-// does not pool connections. This isn't a recommended configuration because it
5353-// will reconnect to cascade on every request, but this is useful to avoid the
5454-// accumulation of idle connections if you make many client objects during the
5555-// lifetime of your application.
5656-func DefaultNonPooledConfig() *Config {
5757- return defaultConfig(cleanhttp.DefaultTransport)
5858-}
4343+ transport := &http.Transport{
4444+ Proxy: http.ProxyFromEnvironment,
4545+ DialContext: (&net.Dialer{
4646+ Timeout: 30 * time.Second,
4747+ KeepAlive: 30 * time.Second,
4848+ DualStack: true,
4949+ }).DialContext,
5050+ MaxIdleConns: 100,
5151+ IdleConnTimeout: 90 * time.Second,
5252+ ExpectContinueTimeout: 1 * time.Second,
5353+ ForceAttemptHTTP2: true,
5454+ MaxIdleConnsPerHost: runtime.GOMAXPROCS(0) + 1,
5555+ }
59566060-// defaultConfig returns the default configuration for the client, using the
6161-// given function to make the transport.
6262-func defaultConfig(transportFn func() *http.Transport) *Config {
6357 config := &Config{
6458 Address: "127.0.0.1:8500",
6559 Scheme: "http",
6666- Transport: transportFn(),
6060+ Transport: transport,
6761 }
68626963 return config
···11-// Copyright (c) HashiCorp, Inc.
22-// SPDX-License-Identifier: MPL-2.0
33-44-package cleanhttp
55-66-import (
77- "net"
88- "net/http"
99- "runtime"
1010- "time"
1111-)
1212-1313-// DefaultTransport returns a new http.Transport with similar default values to
1414-// http.DefaultTransport, but with idle connections and keepalives disabled.
1515-func DefaultTransport() *http.Transport {
1616- transport := DefaultPooledTransport()
1717- transport.DisableKeepAlives = true
1818- transport.MaxIdleConnsPerHost = -1
1919- return transport
2020-}
2121-2222-// DefaultPooledTransport returns a new http.Transport with similar default
2323-// values to http.DefaultTransport. Do not use this for transient transports as
2424-// it can leak file descriptors over time. Only use this for transports that
2525-// will be re-used for the same host(s).
2626-func DefaultPooledTransport() *http.Transport {
2727- transport := &http.Transport{
2828- Proxy: http.ProxyFromEnvironment,
2929- DialContext: (&net.Dialer{
3030- Timeout: 30 * time.Second,
3131- KeepAlive: 30 * time.Second,
3232- DualStack: true,
3333- }).DialContext,
3434- MaxIdleConns: 100,
3535- IdleConnTimeout: 90 * time.Second,
3636- ExpectContinueTimeout: 1 * time.Second,
3737- ForceAttemptHTTP2: true,
3838- MaxIdleConnsPerHost: runtime.GOMAXPROCS(0) + 1,
3939- }
4040- return transport
4141-}
4242-4343-// DefaultClient returns a new http.Client with similar default values to
4444-// http.Client, but with a non-shared Transport, idle connections disabled, and
4545-// keepalives disabled.
4646-func DefaultClient() *http.Client {
4747- return &http.Client{
4848- Transport: DefaultTransport(),
4949- }
5050-}
5151-5252-// DefaultPooledClient returns a new http.Client with similar default values to
5353-// http.Client, but with a shared Transport. Do not use this function for
5454-// transient clients as it can leak file descriptors over time. Only use this
5555-// for clients that will be re-used for the same host(s).
5656-func DefaultPooledClient() *http.Client {
5757- return &http.Client{
5858- Transport: DefaultPooledTransport(),
5959- }
6060-}
-48
lib/cleanhttp/handlers.go
···11-package cleanhttp
22-33-import (
44- "net/http"
55- "strings"
66- "unicode"
77-)
88-99-// HandlerInput provides input options to cleanhttp's handlers
1010-type HandlerInput struct {
1111- ErrStatus int
1212-}
1313-1414-// PrintablePathCheckHandler is a middleware that ensures the request path
1515-// contains only printable runes.
1616-func PrintablePathCheckHandler(next http.Handler, input *HandlerInput) http.Handler {
1717- // Nil-check on input to make it optional
1818- if input == nil {
1919- input = &HandlerInput{
2020- ErrStatus: http.StatusBadRequest,
2121- }
2222- }
2323-2424- // Default to http.StatusBadRequest on error
2525- if input.ErrStatus == 0 {
2626- input.ErrStatus = http.StatusBadRequest
2727- }
2828-2929- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
3030- if r != nil {
3131- // Check URL path for non-printable characters
3232- idx := strings.IndexFunc(r.URL.Path, func(c rune) bool {
3333- return !unicode.IsPrint(c)
3434- })
3535-3636- if idx != -1 {
3737- w.WriteHeader(input.ErrStatus)
3838- return
3939- }
4040-4141- if next != nil {
4242- next.ServeHTTP(w, r)
4343- }
4444- }
4545-4646- return
4747- })
4848-}