From b568a10dd4feedd5539b181e26a5bbafebd4f984 Mon Sep 17 00:00:00 2001 From: networkException Date: Mon, 1 Jan 2024 04:34:00 +0100 Subject: [PATCH] caddyhttp: support unix sockets in `caddy respond` command (#6010) previously the `caddy respond` command would treat the argument passed to --listen as a TCP socket address, iterating over a possible port range. this patch factors the server creation out into a separate function, allowing this to be reused in case the listen address is a unix network address. --- modules/caddyhttp/staticresp.go | 114 +++++++++++++++++++------------- 1 file changed, 67 insertions(+), 47 deletions(-) diff --git a/modules/caddyhttp/staticresp.go b/modules/caddyhttp/staticresp.go index 4fe5910e4..d6befd689 100644 --- a/modules/caddyhttp/staticresp.go +++ b/modules/caddyhttp/staticresp.go @@ -257,6 +257,53 @@ func (s StaticResponse) ServeHTTP(w http.ResponseWriter, r *http.Request, next H return nil } +func buildHTTPServer(i int, port uint, addr string, statusCode int, hdr http.Header, body string, accessLog bool) (*Server, error) { + var handlers []json.RawMessage + + // response body supports a basic template; evaluate it + tplCtx := struct { + N int // server number + Port uint // only the port + Address string // listener address + }{ + N: i, + Port: port, + Address: addr, + } + tpl, err := template.New("body").Parse(body) + if err != nil { + return nil, err + } + buf := new(bytes.Buffer) + err = tpl.Execute(buf, tplCtx) + if err != nil { + return nil, err + } + + // create route with handler + handler := StaticResponse{ + StatusCode: WeakString(fmt.Sprintf("%d", statusCode)), + Headers: hdr, + Body: buf.String(), + } + handlers = append(handlers, caddyconfig.JSONModuleObject(handler, "handler", "static_response", nil)) + route := Route{HandlersRaw: handlers} + + server := &Server{ + Listen: []string{addr}, + ReadHeaderTimeout: caddy.Duration(10 * time.Second), + IdleTimeout: caddy.Duration(30 * time.Second), + MaxHeaderBytes: 1024 * 10, + Routes: RouteList{route}, + AutoHTTPS: &AutoHTTPSConfig{DisableRedir: true}, + } + if accessLog { + server.Logs = new(ServerLogConfig) + } + + return server, nil +} + func cmdRespond(fl caddycmd.Flags) (int, error) { caddy.TrapSignals() @@ -332,65 +379,38 @@ func cmdRespond(fl caddycmd.Flags) (int, error) { hdr.Set(key, val) } + // build each HTTP server + httpApp := App{Servers: make(map[string]*Server)} + // expand listen address, if more than one port listenAddr, err := caddy.ParseNetworkAddress(listen) if err != nil { return caddy.ExitCodeFailedStartup, err } - listenAddrs := make([]string, 0, listenAddr.PortRangeSize()) - for offset := uint(0); offset < listenAddr.PortRangeSize(); offset++ { - listenAddrs = append(listenAddrs, listenAddr.JoinHostPort(offset)) - } - // build each HTTP server - httpApp := App{Servers: make(map[string]*Server)} - - for i, addr := range listenAddrs { - var handlers []json.RawMessage - - // response body supports a basic template; evaluate it - tplCtx := struct { - N int // server number - Port uint // only the port - Address string // listener address - }{ - N: i, - Port: listenAddr.StartPort + uint(i), - Address: addr, + if !listenAddr.IsUnixNetwork() { + listenAddrs := make([]string, 0, listenAddr.PortRangeSize()) + for offset := uint(0); offset < listenAddr.PortRangeSize(); offset++ { + listenAddrs = append(listenAddrs, listenAddr.JoinHostPort(offset)) } - tpl, err := template.New("body").Parse(body) + + for i, addr := range listenAddrs { + server, err := buildHTTPServer(i, listenAddr.StartPort+uint(i), addr, statusCode, hdr, body, accessLog) + if err != nil { + return caddy.ExitCodeFailedStartup, err + } + + // save server + httpApp.Servers[fmt.Sprintf("static%d", i)] = server + } + } else { + server, err := buildHTTPServer(0, 0, listen, statusCode, hdr, body, accessLog) if err != nil { return caddy.ExitCodeFailedStartup, err } - buf := new(bytes.Buffer) - err = tpl.Execute(buf, tplCtx) - if err != nil { - return caddy.ExitCodeFailedStartup, err - } - - // create route with handler - handler := StaticResponse{ - StatusCode: WeakString(fmt.Sprintf("%d", statusCode)), - Headers: hdr, - Body: buf.String(), - } - handlers = append(handlers, caddyconfig.JSONModuleObject(handler, "handler", "static_response", nil)) - route := Route{HandlersRaw: handlers} - - server := &Server{ - Listen: []string{addr}, - ReadHeaderTimeout: caddy.Duration(10 * time.Second), - IdleTimeout: caddy.Duration(30 * time.Second), - MaxHeaderBytes: 1024 * 10, - Routes: RouteList{route}, - AutoHTTPS: &AutoHTTPSConfig{DisableRedir: true}, - } - if accessLog { - server.Logs = new(ServerLogConfig) - } // save server - httpApp.Servers[fmt.Sprintf("static%d", i)] = server + httpApp.Servers[fmt.Sprintf("static%d", 0)] = server } // finish building the config