Skip to content

Commit

Permalink
caddyhttp: support unix sockets in caddy respond command (#6010)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
networkException committed Jan 1, 2024
1 parent 8f9ffc5 commit b568a10
Showing 1 changed file with 66 additions and 46 deletions.
112 changes: 66 additions & 46 deletions modules/caddyhttp/staticresp.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down Expand Up @@ -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)
if err != nil {
return caddy.ExitCodeFailedStartup, err

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
}
buf := new(bytes.Buffer)
err = tpl.Execute(buf, tplCtx)
} else {
server, err := buildHTTPServer(0, 0, listen, statusCode, hdr, body, accessLog)
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
Expand Down

0 comments on commit b568a10

Please sign in to comment.