Skip to content

Commit

Permalink
http_{server,proxy}: support multiple ports binding
Browse files Browse the repository at this point in the history
Fixes #629
  • Loading branch information
Choraden committed Jan 18, 2024
1 parent 9b907a0 commit f74a23c
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 13 deletions.
5 changes: 3 additions & 2 deletions bind/flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,9 +239,10 @@ func HTTPServerConfig(fs *pflag.FlagSet, cfg *forwarder.HTTPServerConfig, prefix
namePrefix += "-"
}

fs.StringVarP(&cfg.Addr,
namePrefix+"address", "", cfg.Addr, "<host:port>"+
fs.VarP(anyflag.NewValue[forwarder.MultiplePortsAddr](cfg.Addr, &cfg.Addr, forwarder.ParseMultiplePortsAddr),
namePrefix+"address", "", "[host]:<port,...>"+
"The server address to listen on. "+
"Multiple ports can be specified separated by commas. "+
"If the host is empty, the server will listen on all available interfaces. ")

if schemes == nil {
Expand Down
7 changes: 5 additions & 2 deletions command/run/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ func (c *command) runE(cmd *cobra.Command, _ []string) (cmdErr error) {
}
}

if c.apiServerConfig.Addr != "" {
if !c.apiServerConfig.Addr.IsZero() {
if err := c.registerProcMetrics(); err != nil {
return fmt.Errorf("register process metrics: %w", err)
}
Expand Down Expand Up @@ -317,7 +317,10 @@ func Command() *cobra.Command {
}
c.httpProxyConfig.PromRegistry = c.promReg
c.httpProxyConfig.PromNamespace = promNs
c.apiServerConfig.Addr = "localhost:10000"
c.apiServerConfig.Addr = forwarder.MultiplePortsAddr{
Host: "localhost",
Ports: []string{"10000"},
}

cmd := &cobra.Command{
Use: "run [--address <host:port>] [--pac <path or url>] [--credentials <username:password@host:port>]...",
Expand Down
5 changes: 4 additions & 1 deletion command/test/httpbin/httpbin.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,10 @@ func Command() *cobra.Command {
apiServerConfig: forwarder.DefaultHTTPServerConfig(),
logConfig: log.DefaultConfig(),
}
c.apiServerConfig.Addr = "localhost:10000"
c.apiServerConfig.Addr = forwarder.MultiplePortsAddr{
Host: "localhost",
Ports: []string{"10000"},
}

cmd := &cobra.Command{
Use: "httpbin [--protocol <http|https|h2>] [--address <host:port>] [flags]",
Expand Down
13 changes: 10 additions & 3 deletions http_proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,10 @@ type HTTPProxyConfig struct {
func DefaultHTTPProxyConfig() *HTTPProxyConfig {
return &HTTPProxyConfig{
HTTPServerConfig: HTTPServerConfig{
Protocol: HTTPScheme,
Addr: ":3128",
Protocol: HTTPScheme,
Addr: MultiplePortsAddr{
Ports: []string{"3128"},
},
ReadHeaderTimeout: 1 * time.Minute,
TLSServerConfig: TLSServerConfig{
HandshakeTimeout: 10 * time.Second,
Expand Down Expand Up @@ -609,8 +611,13 @@ func (hp *HTTPProxy) listen() (net.Listener, error) {
return nil, fmt.Errorf("invalid protocol %q", hp.config.Protocol)
}

addrs := make([]string, 0, len(hp.config.Addr.Ports))
for _, port := range hp.config.Addr.Ports {
addrs = append(addrs, net.JoinHostPort(hp.config.Addr.Host, port))
}

l := Listener{
Addresses: []string{hp.config.Addr},
Addresses: addrs,
Log: hp.log,
TLSConfig: hp.tlsConfig,
TLSHandshakeTimeout: hp.config.TLSServerConfig.HandshakeTimeout,
Expand Down
38 changes: 33 additions & 5 deletions http_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"net"
"net/http"
"net/url"
"strings"
"sync"
"time"

Expand Down Expand Up @@ -73,9 +74,30 @@ func h2TLSConfigTemplate() *tls.Config {
}
}

type MultiplePortsAddr struct {
Host string
Ports []string
}

func ParseMultiplePortsAddr(val string) (MultiplePortsAddr, error) {
i := strings.LastIndex(val, ":")
if i == -1 || i == len(val)-1 {
return MultiplePortsAddr{}, fmt.Errorf("invalid address %q", val)
}

return MultiplePortsAddr{
Host: val[:i],
Ports: strings.Split(val[i+1:], ","),
}, nil
}

func (m MultiplePortsAddr) IsZero() bool {
return m.Host == "" && len(m.Ports) == 0
}

type HTTPServerConfig struct {
Protocol Scheme
Addr string
Addr MultiplePortsAddr
TLSServerConfig
IdleTimeout time.Duration
ReadTimeout time.Duration
Expand All @@ -90,8 +112,10 @@ type HTTPServerConfig struct {

func DefaultHTTPServerConfig() *HTTPServerConfig {
return &HTTPServerConfig{
Protocol: HTTPScheme,
Addr: ":8080",
Protocol: HTTPScheme,
Addr: MultiplePortsAddr{
Ports: []string{"8080"},
},
ReadHeaderTimeout: 1 * time.Minute,
}
}
Expand Down Expand Up @@ -121,7 +145,6 @@ func NewHTTPServer(cfg *HTTPServerConfig, h http.Handler, log log.Logger) (*HTTP
config: *cfg,
log: log,
srv: &http.Server{
Addr: cfg.Addr,
Handler: withMiddleware(cfg, log, h),
IdleTimeout: cfg.IdleTimeout,
ReadTimeout: cfg.ReadTimeout,
Expand Down Expand Up @@ -230,8 +253,13 @@ func (hs *HTTPServer) Run(ctx context.Context) error {
}

func (hs *HTTPServer) listen() (net.Listener, error) {
addrs := make([]string, 0, len(hs.config.Addr.Ports))
for _, port := range hs.config.Addr.Ports {
addrs = append(addrs, net.JoinHostPort(hs.config.Addr.Host, port))
}

l := Listener{
Addresses: []string{hs.config.Addr},
Addresses: addrs,
Log: hs.log,
TLSConfig: hs.srv.TLSConfig,
TLSHandshakeTimeout: hs.config.HandshakeTimeout,
Expand Down

0 comments on commit f74a23c

Please sign in to comment.