This commit is contained in:
Muhammad Hamza 2022-05-08 18:53:35 +05:00 committed by GitHub
parent 333af62e20
commit 3760c5f8b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 20 deletions

View File

@ -16,7 +16,9 @@ wasm-logger = "0.2"
[target.'cfg(not(target_arch = "wasm32"))'.dependencies] [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
tokio = { version = "1.15.0", features = ["full"] } tokio = { version = "1.15.0", features = ["full"] }
warp = "0.3" axum = "0.5"
tower = { version = "0.4", features = ["make"] }
tower-http = { version = "0.3", features = ["fs"] }
env_logger = "0.9" env_logger = "0.9"
num_cpus = "1.13" num_cpus = "1.13"
tokio-util = { version = "0.7", features = ["rt"] } tokio-util = { version = "0.7", features = ["rt"] }

View File

@ -1,11 +1,20 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::path::PathBuf; use std::path::PathBuf;
use axum::body::Body;
use axum::error_handling::HandleError;
use axum::extract::Query;
use axum::handler::Handler;
use axum::http::{Request, StatusCode};
use axum::response::Html;
use axum::routing::get;
use axum::{Extension, Router};
use clap::Parser; use clap::Parser;
use function_router::{ServerApp, ServerAppProps}; use function_router::{ServerApp, ServerAppProps};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use tokio_util::task::LocalPoolHandle; use tokio_util::task::LocalPoolHandle;
use warp::Filter; use tower::ServiceExt;
use tower_http::services::ServeDir;
// We spawn a local pool that is as big as the number of cpu threads. // We spawn a local pool that is as big as the number of cpu threads.
static LOCAL_POOL: Lazy<LocalPoolHandle> = Lazy::new(|| LocalPoolHandle::new(num_cpus::get())); static LOCAL_POOL: Lazy<LocalPoolHandle> = Lazy::new(|| LocalPoolHandle::new(num_cpus::get()));
@ -14,12 +23,16 @@ static LOCAL_POOL: Lazy<LocalPoolHandle> = Lazy::new(|| LocalPoolHandle::new(num
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
struct Opt { struct Opt {
/// the "dist" created by trunk directory to be served for hydration. /// the "dist" created by trunk directory to be served for hydration.
#[structopt(short, long, parse(from_os_str))] #[clap(short, long, parse(from_os_str))]
dir: PathBuf, dir: PathBuf,
} }
async fn render(index_html_s: &str, url: &str, queries: HashMap<String, String>) -> String { async fn render(
let url = url.to_string(); Extension(index_html_s): Extension<String>,
url: Request<Body>,
Query(queries): Query<HashMap<String, String>>,
) -> Html<String> {
let url = url.uri().to_string();
let content = LOCAL_POOL let content = LOCAL_POOL
.spawn_pinned(move || async move { .spawn_pinned(move || async move {
@ -37,7 +50,7 @@ async fn render(index_html_s: &str, url: &str, queries: HashMap<String, String>)
// Good enough for an example, but developers should avoid the replace and extra allocation // Good enough for an example, but developers should avoid the replace and extra allocation
// here in an actual app. // here in an actual app.
index_html_s.replace("<body>", &format!("<body>{}", content)) Html(index_html_s.replace("<body>", &format!("<body>{}", content)))
} }
#[tokio::main] #[tokio::main]
@ -50,23 +63,33 @@ async fn main() {
.await .await
.expect("failed to read index.html"); .expect("failed to read index.html");
let render = move |s: warp::filters::path::FullPath, queries: HashMap<String, String>| { let handle_error = |e| async move {
let index_html_s = index_html_s.clone(); (
StatusCode::INTERNAL_SERVER_ERROR,
async move { warp::reply::html(render(&index_html_s, s.as_str(), queries).await) } format!("error occurred: {}", e),
)
}; };
let html = warp::path::end().and( let app = Router::new()
warp::path::full() .route("/api/test", get(|| async move { "Hello World" }))
.and(warp::filters::query::query()) // needed because https://github.com/tower-rs/tower-http/issues/262
.then(render.clone()), .route("/", get(render))
); .fallback(HandleError::new(
ServeDir::new(opts.dir)
let routes = html.or(warp::fs::dir(opts.dir)).or(warp::path::full() .append_index_html_on_directories(false)
.and(warp::filters::query::query()) .fallback(
.then(render)); render
.layer(Extension(index_html_s))
.into_service()
.map_err(|err| -> std::io::Error { match err {} }),
),
handle_error,
));
println!("You can view the website at: http://localhost:8080/"); println!("You can view the website at: http://localhost:8080/");
warp::serve(routes).run(([127, 0, 0, 1], 8080)).await; axum::Server::bind(&"0.0.0.0:8080".parse().unwrap())
.serve(app.into_make_service())
.await
.unwrap();
} }