diff --git a/agent/http.go b/agent/http.go index dce70ee..9a1ba5a 100644 --- a/agent/http.go +++ b/agent/http.go @@ -8,9 +8,9 @@ import ( "net/http" "strings" "time" + "unicode" "git.j3s.sh/cascade/lib" - "git.j3s.sh/cascade/lib/cleanhttp" ) // MethodNotAllowedError should be returned by a handler when the HTTP method is not allowed. @@ -118,10 +118,48 @@ func (s *HTTPHandlers) handler() http.Handler { } // This handler bans URLs with non-printable characters - h := cleanhttp.PrintablePathCheckHandler(mux, nil) + h := printablePathCheckHandler(mux, nil) return h } +type HandlerInput struct { + ErrStatus int +} + +func printablePathCheckHandler(next http.Handler, input *HandlerInput) http.Handler { + // Nil-check on input to make it optional + if input == nil { + input = &HandlerInput{ + ErrStatus: http.StatusBadRequest, + } + } + + // Default to http.StatusBadRequest on error + if input.ErrStatus == 0 { + input.ErrStatus = http.StatusBadRequest + } + + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r != nil { + // Check URL path for non-printable characters + idx := strings.IndexFunc(r.URL.Path, func(c rune) bool { + return !unicode.IsPrint(c) + }) + + if idx != -1 { + w.WriteHeader(input.ErrStatus) + return + } + + if next != nil { + next.ServeHTTP(w, r) + } + } + + return + }) +} + // wrap is used to wrap functions to make them more convenient // func (s *HTTPHandlers) wrap(handler http.HandlerFunc) http.HandlerFunc { // httpLogger := s.agent.logger diff --git a/agent/service.go b/agent/service.go new file mode 100644 index 0000000..454e03e --- /dev/null +++ b/agent/service.go @@ -0,0 +1,8 @@ +package agent + +import "net" + +type Service struct { + Name string + Addr *net.TCPAddr +} diff --git a/api/api.go b/api/api.go index 9ade3d4..72c7e18 100644 --- a/api/api.go +++ b/api/api.go @@ -10,12 +10,11 @@ import ( "net" "net/http" "net/url" + "runtime" "strconv" "strings" "sync" "time" - - "git.j3s.sh/cascade/lib/cleanhttp" ) // Config is used to configure the creation of a client @@ -39,31 +38,26 @@ type Config struct { } // DefaultConfig returns a default configuration for the client. By default this -// will pool and reuse idle connections to cascade. If you have a long-lived -// client object, this is the desired behavior and should make the most efficient -// use of the connections to cascade. If you don't reuse a client object, which -// is not recommended, then you may notice idle connections building up over -// time. To avoid this, use the DefaultNonPooledConfig() instead. +// will pool and reuse idle connections to cascade. func DefaultConfig() *Config { - return defaultConfig(cleanhttp.DefaultPooledTransport) -} - -// DefaultNonPooledConfig returns a default configuration for the client which -// does not pool connections. This isn't a recommended configuration because it -// will reconnect to cascade on every request, but this is useful to avoid the -// accumulation of idle connections if you make many client objects during the -// lifetime of your application. -func DefaultNonPooledConfig() *Config { - return defaultConfig(cleanhttp.DefaultTransport) -} + transport := &http.Transport{ + Proxy: http.ProxyFromEnvironment, + DialContext: (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + DualStack: true, + }).DialContext, + MaxIdleConns: 100, + IdleConnTimeout: 90 * time.Second, + ExpectContinueTimeout: 1 * time.Second, + ForceAttemptHTTP2: true, + MaxIdleConnsPerHost: runtime.GOMAXPROCS(0) + 1, + } -// defaultConfig returns the default configuration for the client, using the -// given function to make the transport. -func defaultConfig(transportFn func() *http.Transport) *Config { config := &Config{ Address: "127.0.0.1:8500", Scheme: "http", - Transport: transportFn(), + Transport: transport, } return config diff --git a/command/ls/members/members.go b/command/ls/members/members.go index e34ede8..c193d7d 100644 --- a/command/ls/members/members.go +++ b/command/ls/members/members.go @@ -40,7 +40,7 @@ func Run(args []string) { flags.BoolVar(&membersFlags.details, "details", false, "") flags.Parse(args) - cfg := api.DefaultNonPooledConfig() + cfg := api.DefaultConfig() client, err := api.NewClient(cfg) if err != nil { fmt.Println(err) diff --git a/lib/cleanhttp/cleanhttp.go b/lib/cleanhttp/cleanhttp.go deleted file mode 100644 index f24ff45..0000000 --- a/lib/cleanhttp/cleanhttp.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package cleanhttp - -import ( - "net" - "net/http" - "runtime" - "time" -) - -// DefaultTransport returns a new http.Transport with similar default values to -// http.DefaultTransport, but with idle connections and keepalives disabled. -func DefaultTransport() *http.Transport { - transport := DefaultPooledTransport() - transport.DisableKeepAlives = true - transport.MaxIdleConnsPerHost = -1 - return transport -} - -// DefaultPooledTransport returns a new http.Transport with similar default -// values to http.DefaultTransport. Do not use this for transient transports as -// it can leak file descriptors over time. Only use this for transports that -// will be re-used for the same host(s). -func DefaultPooledTransport() *http.Transport { - transport := &http.Transport{ - Proxy: http.ProxyFromEnvironment, - DialContext: (&net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - DualStack: true, - }).DialContext, - MaxIdleConns: 100, - IdleConnTimeout: 90 * time.Second, - ExpectContinueTimeout: 1 * time.Second, - ForceAttemptHTTP2: true, - MaxIdleConnsPerHost: runtime.GOMAXPROCS(0) + 1, - } - return transport -} - -// DefaultClient returns a new http.Client with similar default values to -// http.Client, but with a non-shared Transport, idle connections disabled, and -// keepalives disabled. -func DefaultClient() *http.Client { - return &http.Client{ - Transport: DefaultTransport(), - } -} - -// DefaultPooledClient returns a new http.Client with similar default values to -// http.Client, but with a shared Transport. Do not use this function for -// transient clients as it can leak file descriptors over time. Only use this -// for clients that will be re-used for the same host(s). -func DefaultPooledClient() *http.Client { - return &http.Client{ - Transport: DefaultPooledTransport(), - } -} diff --git a/lib/cleanhttp/handlers.go b/lib/cleanhttp/handlers.go deleted file mode 100644 index 3c845dc..0000000 --- a/lib/cleanhttp/handlers.go +++ /dev/null @@ -1,48 +0,0 @@ -package cleanhttp - -import ( - "net/http" - "strings" - "unicode" -) - -// HandlerInput provides input options to cleanhttp's handlers -type HandlerInput struct { - ErrStatus int -} - -// PrintablePathCheckHandler is a middleware that ensures the request path -// contains only printable runes. -func PrintablePathCheckHandler(next http.Handler, input *HandlerInput) http.Handler { - // Nil-check on input to make it optional - if input == nil { - input = &HandlerInput{ - ErrStatus: http.StatusBadRequest, - } - } - - // Default to http.StatusBadRequest on error - if input.ErrStatus == 0 { - input.ErrStatus = http.StatusBadRequest - } - - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r != nil { - // Check URL path for non-printable characters - idx := strings.IndexFunc(r.URL.Path, func(c rune) bool { - return !unicode.IsPrint(c) - }) - - if idx != -1 { - w.WriteHeader(input.ErrStatus) - return - } - - if next != nil { - next.ServeHTTP(w, r) - } - } - - return - }) -}