Skip to content

Commit

Permalink
vertigo-cli: Don't panic when missing root html element
Browse files Browse the repository at this point in the history
  • Loading branch information
sfisol committed Feb 27, 2024
1 parent 2a84a32 commit c68a009
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 27 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
### Fixed

* vertigo-cli: Don't html-escape styles embedded during SSR
* vertigo-cli: Don't panic when missing root html element

## 0.4.2 - 2024-02-06

Expand Down
1 change: 1 addition & 0 deletions crates/vertigo-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ sha2 = "0.10"
tokio = { version = "1.25", features = ["full"] }
tokio-stream = "0.1"
tower-http = { version = "0.4", features = ["fs"] }
tokio-retry = "0.3"
wasmtime = "14.0"
6 changes: 1 addition & 5 deletions crates/vertigo-cli/src/serve/html/element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,11 +151,7 @@ impl AllElements {

fn get_response_one_elements(&self, node_id: u64, with_id: bool) -> HtmlNode {
let Some(node) = self.all.get(&node_id) else {
if node_id == 1 {
panic!("Can't find root <html> element");
} else {
unreachable!();
}
return HtmlNode::Comment("No <html> element".to_string())
};

match node {
Expand Down
12 changes: 8 additions & 4 deletions crates/vertigo-cli/src/serve/html/html_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,20 +83,24 @@ impl HtmlResponse {

if let HtmlNode::Element(html) = &mut root_html {
if html.name != "html" {
return (StatusCode::INTERNAL_SERVER_ERROR, "root: the html element was expected".into());
// Not really possible
return (
StatusCode::INTERNAL_SERVER_ERROR,
format!("Missing <html> element, found {} instead", html.name)
);
}

for (env_name, env_value) in &self.env {
html.add_attr(format!("data-env-{env_name}"), env_value);
}
} else {
return (StatusCode::INTERNAL_SERVER_ERROR, "root: the html element was expected".into());
return (StatusCode::INTERNAL_SERVER_ERROR, "Missing <html> element".into());
}

let head_exists = root_html.modify(&[("head", 0)], move |_head| {});

if !head_exists {
let message = "The 'head' element was expected in the response".into();
let message = "Missing <head> element".into();
return (StatusCode::INTERNAL_SERVER_ERROR, message);
}

Expand All @@ -117,7 +121,7 @@ impl HtmlResponse {
let document = HtmlDocument::new(root_html);
(StatusCode::OK, document.convert_to_string(true))
} else {
let message = "The 'body' element was expected in the response".into();
let message = "Missing <body> element".into();
(StatusCode::INTERNAL_SERVER_ERROR, message)
}
}
Expand Down
14 changes: 10 additions & 4 deletions crates/vertigo-cli/src/serve/serve_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,16 @@ async fn handler(url: Uri, RawQuery(query): RawQuery, State(state): State<Arc<Rw
log::info!("Response for request: {status} {}ms {url}", time.as_millis());
}

if status == StatusCode::OK {
if let Some(port_watch) = state.port_watch {
response = add_watch_script(response, port_watch);
}
match status {
StatusCode::OK => {
if let Some(port_watch) = state.port_watch {
response = add_watch_script(response, port_watch);
}
},
status => {
log::error!("WASM status: {status}");
log::error!("WASM response: {response}");
},
}

Response::builder()
Expand Down
33 changes: 27 additions & 6 deletions crates/vertigo-cli/src/watch/is_http_server_listening.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,42 @@
pub async fn is_http_server_listening(port: u16) -> bool {
pub async fn is_http_server_listening(port: u16) -> Result<(), ()> {
use tokio::net::TcpStream;
use tokio::io::AsyncWriteExt;
use tokio::io::AsyncReadExt;

match TcpStream::connect(("127.0.0.1", port)).await {
Ok(mut stream) => {
// Send a HEAD request to the HTTP server
if stream.write_all(b"HEAD / HTTP/1.0\r\n\r\n").await.is_err() {
return false;
match stream.write_all(b"HEAD / HTTP/1.0\r\n\r\n").await {
Ok(_) => {},
Err(err) => {
// Network error while sending request
println!("Error = {err}");
return Err(());
}
}

// Wait for a response
let mut buf = [0; 1024];
match stream.read(&mut buf).await {
Ok(n) if n > 0 => true, // If we received a response, the HTTP server is running
_ => false, // Otherwise, the HTTP server is not running
Ok(n) if n > 0 => {
// If we received a response, the HTTP server is running
Ok(())
},
Ok(_) => {
// HTTP server is running but probably failed to configure properly
Err(())
},
Err(err) => {
// Network error while reading response
println!("Error = {err}");
Err(())
},
}
},
Err(_) => false, // Connection error means that the HTTP server is not running
Err(err) => {
// Http server has not opened the socket yet
println!("Error = {err}");
Err(())
},
}
}
13 changes: 5 additions & 8 deletions crates/vertigo-cli/src/watch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use notify::RecursiveMode;
use poem::http::Method;
use poem::middleware::Cors;
use poem::{Route, get, Server, listener::TcpListener, EndpointExt};
use tokio_retry::{Retry, strategy::FibonacciBackoff};
use tokio::sync::Notify;
use tokio::time::sleep;
use std::sync::Arc;
Expand Down Expand Up @@ -201,14 +202,10 @@ fn build_and_watch(version: u32, tx: Arc<Sender<Status>>, opts: &WatchOpts, ws:
log::info!("build run ok");

let check_spawn = SpawnOwner::new(async move {
loop {
let is_open = is_http_server_listening(opts.port).await;
if is_open {
break;
}

sleep(Duration::from_millis(100)).await;
}
let _ = Retry::spawn(
FibonacciBackoff::from_millis(100).max_delay(Duration::from_secs(4)),
|| is_http_server_listening(opts.port)
).await;

let Ok(()) = tx.send(Status::Version(version)) else {
unreachable!();
Expand Down

0 comments on commit c68a009

Please sign in to comment.