Skip to content

Commit dcf4bf8

Browse files
committed
fix: verify route via GET after Caddy restart to handle connection reset
1 parent 9039bef commit dcf4bf8

1 file changed

Lines changed: 24 additions & 6 deletions

File tree

‎internal/caddy/client.go‎

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,29 +81,47 @@ func (c *Client) postRoute(route Route) error {
8181
}
8282

8383
cmd := fmt.Sprintf(
84-
`docker exec caddy curl -s -w '%%{http_code}' -o /tmp/cr.txt -X POST http://localhost:2019/config/apps/http/servers/srv0/routes -H 'Content-Type: application/json' -d '%s'; echo; docker exec caddy cat /tmp/cr.txt`,
84+
`docker exec caddy curl -s -w '%%{http_code}' -o /tmp/cr.txt -X POST http://localhost:2019/config/apps/http/servers/srv0/routes -H 'Content-Type: application/json' -d '%s'; echo; docker exec caddy cat /tmp/cr.txt 2>/dev/null`,
8585
escapeShell(string(body)),
8686
)
8787
out, err := c.ssh.Exec(cmd)
8888
if err != nil {
89+
// Caddy may restart admin endpoint after config change, breaking the TCP connection.
90+
// The route is likely added. Verify via GET before treating as error.
91+
verifyCmd := fmt.Sprintf(
92+
`docker exec caddy curl -s -o /dev/null -w '%%{http_code}' http://localhost:2019/id/%s`,
93+
route.ID,
94+
)
95+
vOut, vErr := c.ssh.Exec(verifyCmd)
96+
if vErr == nil && strings.TrimSpace(vOut) == "200" {
97+
return nil // route was actually added
98+
}
8999
return fmt.Errorf("caddy add route: %w (output: %s)", err, strings.TrimSpace(out))
90100
}
91101
lines := strings.SplitN(out, "\n", 2)
92102
code := strings.TrimSpace(lines[0])
93103
if code != "200" {
94-
body := ""
95-
if len(lines) > 1 {
96-
body = strings.TrimSpace(lines[1])
104+
if len(lines) > 1 && strings.TrimSpace(lines[1]) != "" {
105+
return fmt.Errorf("caddy returned HTTP %s (body: %s)", code, strings.TrimSpace(lines[1]))
106+
}
107+
// Same verification fallback
108+
verifyCmd := fmt.Sprintf(
109+
`docker exec caddy curl -s -o /dev/null -w '%%{http_code}' http://localhost:2019/id/%s`,
110+
route.ID,
111+
)
112+
vOut, vErr := c.ssh.Exec(verifyCmd)
113+
if vErr == nil && strings.TrimSpace(vOut) == "200" {
114+
return nil
97115
}
98-
return fmt.Errorf("caddy returned HTTP %s (body: %s)", code, body)
116+
return fmt.Errorf("caddy returned HTTP %s", code)
99117
}
100118
return nil
101119
}
102120

103121
func (c *Client) RemoveRoute(domain string) error {
104122
id := sanitizeID(domain)
105123
cmd := fmt.Sprintf(
106-
`docker exec caddy curl -s -w '%%{http_code}' -o /tmp/cr.txt -X DELETE http://localhost:2019/id/%s; echo; docker exec caddy cat /tmp/cr.txt`,
124+
`docker exec caddy curl -s -w '%%{http_code}' -o /tmp/cr.txt -X DELETE http://localhost:2019/id/%s; echo; docker exec caddy cat /tmp/cr.txt 2>/dev/null`,
107125
id,
108126
)
109127
out, err := c.ssh.Exec(cmd)

0 commit comments

Comments
 (0)