Skip to content

Commit eb15f83

Browse files
committed
fix(caddy): use PUT to insert routes at specific index
Caddy's API uses PUT for inserting at array indices, not POST. POST appends to the end, while PUT to /routes/N inserts at position N. This ensures deployed routes are inserted before the catch-all 404 route.
1 parent 5b74928 commit eb15f83

1 file changed

Lines changed: 49 additions & 23 deletions

File tree

src/worker/deploy/caddy.rs

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -34,30 +34,11 @@ pub async fn configure_caddy_route(
3434
// First, try to delete any existing route with this ID
3535
let _ = remove_caddy_route(http_client, caddy_admin_api, site_id).await;
3636

37-
// Find the position to insert (before any catch-all route without match rules)
37+
// Find the position to insert (before any catch-all route)
3838
let insert_index = find_catch_all_index(http_client, caddy_admin_api).await?;
3939

40-
// Add the new route at the correct position (before catch-all)
41-
let url = match insert_index {
42-
Some(idx) => format!(
43-
"{}/config/apps/http/servers/main/routes/{}",
44-
caddy_admin_api, idx
45-
),
46-
None => format!("{}/config/apps/http/servers/main/routes", caddy_admin_api),
47-
};
48-
49-
let response = http_client
50-
.post(&url)
51-
.json(&route)
52-
.send()
53-
.await
54-
.context("Failed to add Caddy route")?;
55-
56-
if !response.status().is_success() {
57-
let status = response.status();
58-
let body = response.text().await.unwrap_or_default();
59-
anyhow::bail!("Caddy API error {}: {}", status, body);
60-
}
40+
// Add the route (PUT to insert at index, or POST to append)
41+
add_caddy_route(http_client, caddy_admin_api, &route, insert_index).await?;
6142

6243
tracing::info!(
6344
site_id = site_id,
@@ -85,7 +66,6 @@ async fn find_catch_all_index(
8566
.context("Failed to get Caddy routes")?;
8667

8768
if !response.status().is_success() {
88-
// If we can't get routes, just append to end
8969
return Ok(None);
9070
}
9171

@@ -105,6 +85,52 @@ async fn find_catch_all_index(
10585
Ok(None)
10686
}
10787

88+
/// Add a route to Caddy, inserting before catch-all if one exists
89+
///
90+
/// Uses PUT to insert at a specific index (Caddy API: PUT to /routes/N inserts at N)
91+
/// or POST to append if no catch-all exists.
92+
async fn add_caddy_route(
93+
http_client: &reqwest::Client,
94+
caddy_admin_api: &str,
95+
route: &CaddyRoute,
96+
insert_index: Option<usize>,
97+
) -> Result<()> {
98+
let (method, url) = match insert_index {
99+
Some(idx) => (
100+
reqwest::Method::PUT,
101+
format!(
102+
"{}/config/apps/http/servers/main/routes/{}",
103+
caddy_admin_api, idx
104+
),
105+
),
106+
None => (
107+
reqwest::Method::POST,
108+
format!("{}/config/apps/http/servers/main/routes", caddy_admin_api),
109+
),
110+
};
111+
112+
let response = http_client
113+
.request(method.clone(), &url)
114+
.json(route)
115+
.send()
116+
.await
117+
.context("Failed to add Caddy route")?;
118+
119+
if !response.status().is_success() {
120+
let status = response.status();
121+
let body = response.text().await.unwrap_or_default();
122+
anyhow::bail!("Caddy API error {}: {}", status, body);
123+
}
124+
125+
tracing::info!(
126+
method = %method,
127+
insert_index = ?insert_index,
128+
"Added route to Caddy"
129+
);
130+
131+
Ok(())
132+
}
133+
108134
/// Remove a Caddy route by ID
109135
///
110136
/// Uses Caddy's /id/ endpoint which allows direct access to objects by their @id field.

0 commit comments

Comments
 (0)