Skip to content

Commit 9e3eb1e

Browse files
committed
fix(cli): Missing HTTP headers
1 parent ac94050 commit 9e3eb1e

File tree

3 files changed

+28
-34
lines changed

3 files changed

+28
-34
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
maudit-cli: patch
3+
---
4+
5+
Fixes missing HTTP headers on HTML responses

crates/maudit-cli/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ tokio = { version = "1", features = [
1919
"signal",
2020
"process",
2121
] }
22-
axum = { version = "0.8.1", features = ["ws"] }
22+
axum = { version = "0.8.6", features = ["ws"] }
2323
futures = "0.3"
24-
tower-http = { version = "0.6.2", features = ["fs", "trace"] }
24+
tower-http = { version = "0.6.6", features = ["fs", "trace"] }
2525
tracing = "0.1"
2626
tracing-subscriber = { version = "=0.3.19", features = [
2727
"env-filter",

crates/maudit-cli/src/dev/server.rs

Lines changed: 21 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use axum::{
55
Request, State,
66
ws::{Message, WebSocket, WebSocketUpgrade},
77
},
8-
http::{HeaderValue, StatusCode, Uri},
8+
http::{HeaderValue, StatusCode, header::CONTENT_LENGTH},
99
middleware::{self, Next},
1010
response::{IntoResponse, Response},
1111
routing::get,
@@ -17,7 +17,7 @@ use tokio::{
1717
signal,
1818
sync::{RwLock, broadcast},
1919
};
20-
use tracing::{Level, debug, warn};
20+
use tracing::{Level, debug};
2121

2222
use std::net::{IpAddr, SocketAddr};
2323
use std::sync::Arc;
@@ -69,12 +69,9 @@ struct AppState {
6969
current_status: Arc<RwLock<Option<PersistentStatus>>>,
7070
}
7171

72-
fn inject_live_reload_script(
73-
uri: &Uri,
74-
html_content: &str,
75-
socket_addr: SocketAddr,
76-
host: bool,
77-
) -> String {
72+
fn inject_live_reload_script(html_content: &str, socket_addr: SocketAddr, host: bool) -> String {
73+
let mut content = html_content.to_string();
74+
7875
let script_content = include_str!(concat!(env!("OUT_DIR"), "/js/client.js")).replace(
7976
"{SERVER_ADDRESS}",
8077
&format!(
@@ -88,19 +85,8 @@ fn inject_live_reload_script(
8885
),
8986
);
9087

91-
// Only inject script if content looks like proper HTML
92-
if html_content.trim_start().starts_with("<!DOCTYPE")
93-
|| html_content.trim_start().starts_with("<html")
94-
{
95-
format!("{}<script>{}</script>", html_content, script_content)
96-
} else {
97-
warn!(
98-
"{} matched an HTML response, but it does not look like proper HTML, live-reload won't work. Make sure your HTML has a proper <!DOCTYPE> or <html> tag.",
99-
uri
100-
);
101-
// Not proper HTML, return content unchanged
102-
html_content.to_string()
103-
}
88+
content.push_str(&format!("\n\n<script>{script_content}</script>"));
89+
content
10490
}
10591

10692
pub async fn start_dev_web_server(
@@ -124,12 +110,7 @@ pub async fn start_dev_web_server(
124110
});
125111
}
126112

127-
async fn handle_404(
128-
uri: Uri,
129-
socket_addr: SocketAddr,
130-
host: bool,
131-
dist_dir: &str,
132-
) -> impl IntoResponse {
113+
async fn handle_404(socket_addr: SocketAddr, host: bool, dist_dir: &str) -> impl IntoResponse {
133114
let content = match fs::read_to_string(format!("{}/404.html", dist_dir)).await {
134115
Ok(custom_content) => custom_content,
135116
Err(_) => include_str!("./404.html").to_string(),
@@ -138,7 +119,7 @@ pub async fn start_dev_web_server(
138119
(
139120
StatusCode::NOT_FOUND,
140121
[(header::CONTENT_TYPE, "text/html; charset=utf-8")],
141-
inject_live_reload_script(&uri, &content, socket_addr, host),
122+
inject_live_reload_script(&content, socket_addr, host),
142123
)
143124
.into_response()
144125
}
@@ -162,8 +143,8 @@ pub async fn start_dev_web_server(
162143
debug!("listening on {}", listener.local_addr().unwrap());
163144

164145
let serve_dir =
165-
ServeDir::new(dist_dir).not_found_service(axum::routing::any(move |uri: Uri| async move {
166-
handle_404(uri, socket_addr, host, dist_dir).await
146+
ServeDir::new(dist_dir).not_found_service(axum::routing::any(move || async move {
147+
handle_404(socket_addr, host, dist_dir).await
167148
}));
168149

169150
// TODO: Return a `.well-known/appspecific/com.chrome.devtools.json` for Chrome
@@ -254,16 +235,24 @@ async fn add_dev_client_script(
254235
if res.headers().get(axum::http::header::CONTENT_TYPE)
255236
== Some(&HeaderValue::from_static("text/html"))
256237
{
238+
let original_headers = res.headers().clone();
257239
let body = res.into_body();
258240
let bytes = to_bytes(body, usize::MAX).await.unwrap();
259241

260242
let body = String::from_utf8_lossy(&bytes).into_owned();
261243

262-
let body_with_script = inject_live_reload_script(&uri, &body, socket_addr, host);
244+
let body_with_script = inject_live_reload_script(&body, socket_addr, host);
245+
let new_body_length = body_with_script.len();
263246

264247
// Copy the headers from the original response
265248
let mut res = Response::new(body_with_script.into());
266-
*res.headers_mut() = res.headers().clone();
249+
*res.headers_mut() = original_headers;
250+
251+
// Update Content-Length header to match new body size
252+
res.headers_mut().insert(
253+
CONTENT_LENGTH,
254+
HeaderValue::from_str(&new_body_length.to_string()).unwrap(),
255+
);
267256

268257
res.extensions_mut().insert(uri);
269258

0 commit comments

Comments
 (0)