diff --git a/Cargo.lock b/Cargo.lock index 2c635b5373..8d79a37207 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -98,6 +98,12 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "ascii" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" + [[package]] name = "async-compression" version = "0.4.6" @@ -306,6 +312,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "chunked_transfer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4de3bc4ea267985becf712dc6d9eed8b04c953b3fcfb339ebc87acd9804901" + [[package]] name = "clap" version = "4.5.3" @@ -1980,6 +1992,7 @@ dependencies = [ "termcolor", "thiserror", "threadpool", + "tiny_http", "tokio", "toml", "tracing", @@ -2396,6 +2409,19 @@ dependencies = [ "time-core", ] +[[package]] +name = "tiny_http" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0d6ef4e10d23c1efb862eecad25c5054429a71958b4eeef85eb5e7170b477ca" +dependencies = [ + "ascii", + "chunked_transfer", + "log", + "time", + "url", +] + [[package]] name = "tinyvec" version = "1.6.0" diff --git a/Cargo.toml b/Cargo.toml index 14e670333d..dd7e1603a3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,13 +12,13 @@ build = "build.rs" [features] curl-backend = ["download/curl-backend"] + default = [ "curl-backend", "reqwest-backend", "reqwest-default-tls", "reqwest-rustls-tls", ] - reqwest-backend = ["download/reqwest-backend"] vendored-openssl = ['openssl/vendored'] @@ -90,6 +90,7 @@ termcolor.workspace = true thiserror.workspace = true threadpool = "1" tokio = { workspace = true, optional = true } +tiny_http = "0.11" toml = "0.8" tracing-opentelemetry = { workspace = true, optional = true } tracing-subscriber = { workspace = true, optional = true, features = ["env-filter"] } diff --git a/src/cli/rustup_mode.rs b/src/cli/rustup_mode.rs index 9068a102d9..0edba799fc 100644 --- a/src/cli/rustup_mode.rs +++ b/src/cli/rustup_mode.rs @@ -10,6 +10,7 @@ use clap::{ }; use clap_complete::Shell; use itertools::Itertools; +use tiny_http::{Response, Server}; use crate::{ cli::{ @@ -725,6 +726,9 @@ pub(crate) fn cli() -> Command { .value_parser(partial_toolchain_desc_parser), ) .arg(Arg::new("topic").help(TOPIC_ARG_HELP)) + .subcommand( + Command::new("servedoc") + ) .group( ArgGroup::new("page").args( DOCS_DATA @@ -738,7 +742,7 @@ pub(crate) fn cli() -> Command { .iter() .map(|&(name, help_msg, _)| Arg::new(name).long(name).help(help_msg).action(ArgAction::SetTrue)) .collect::>(), - ), + ) ); if cfg!(not(target_os = "windows")) { @@ -1613,6 +1617,44 @@ fn doc(cfg: &Cfg, m: &ArgMatches) -> Result { let doc_path = toolchain.doc_path(doc_url)?; writeln!(process().stdout().lock(), "{}", doc_path.display())?; Ok(utils::ExitCode(0)) + } else if m.subcommand_matches("servedoc").is_some() { + let doc_path_index = toolchain.doc_path(doc_url)?; + let doc_path_base = toolchain.doc_path("")?; + let doc_path_str = doc_path_base.to_string_lossy().into_owned(); + loop { + let server = Server::http("127.0.0.1:0").unwrap(); + println!("Serving documentation at {}", server.server_addr()); + for request in server.incoming_requests() { + //TODO get request path and serve filebased on that + let request_path = request.url().strip_prefix('/'); + match request_path { + Some(mut request_path) => { + println!("doc url: {:?}", &doc_url); + println!("Req file: {:?}", &request_path); + let base_string = doc_path_str.clone(); + if request_path == "" { + request_path = doc_url; + } + //strip search params + if let Some(index) = request_path.find('?') { + request_path = &request_path[..index]; + } + //ignore favicon requests + if request_path == "favicon.ico" { + continue; + } + let path = String::from(base_string + &request_path); + println!("Serving file: {:?}", &path); + let file = std::fs::File::open(path).unwrap(); + request.respond(Response::from_file(file)).unwrap(); + } + None => { + let file = std::fs::File::open(&doc_path_index).unwrap(); + request.respond(Response::from_file(file)).unwrap(); + } + } + } + } } else { toolchain.open_docs(doc_url)?; Ok(utils::ExitCode(0))