Skip to content

Commit ddc797f

Browse files
committed
feat: added support for static aliases in the warp integration
None of this has been tested yet, so there will likely be bugs. We now depend on my fork of Warp until [this](seanmonstar/warp#924) is merged.
1 parent 8afedef commit ddc797f

File tree

3 files changed

+70
-5
lines changed

3 files changed

+70
-5
lines changed

packages/perseus-warp/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@ categories = ["wasm", "web-programming::http-server", "development-tools", "asyn
1616
[dependencies]
1717
perseus = { path = "../perseus", version = "0.3.0-beta.18" }
1818
tokio = { version = "1", features = [ "full" ] } # TODO Select only some features on Tokio
19-
warp = "0.3"
19+
warp = { version = "0.3", git = "https://github.com/arctic-hen7/warp", branch = "master" } # Temporary until Warp #171 is resolved
2020
urlencoding = "2.1"
2121
serde = "1"
2222
serde_json = "1"
2323
thiserror = "1"
2424
fmterr = "0.1"
2525
futures = "0.3"
2626
sycamore = { version = "0.6", features = ["ssr"] }
27+
async-stream = "0.3"
28+
bytes = "1"

packages/perseus-warp/src/perseus_routes.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use crate::initial_load::initial_load_handler;
22
use crate::page_data::page_handler;
33
use crate::{
4-
conv_req::get_http_req, page_data::PageDataReq, static_content::static_aliases_filter,
4+
conv_req::get_http_req,
5+
page_data::PageDataReq,
6+
static_content::{serve_file, static_aliases_filter},
57
translations::translations_handler,
68
};
79
use perseus::internal::serve::{get_render_cfg, ServerOptions};
@@ -51,7 +53,9 @@ pub async fn perseus_routes<M: MutableStore + 'static, T: TranslationsManager +
5153
.untuple_one() // We need this to avoid a ((), File) (which makes the return type fail)
5254
.and(warp::fs::dir(opts.static_dir.clone().unwrap()));
5355
// Handle static aliases
54-
let static_aliases = warp::any().and(static_aliases_filter(opts.static_aliases.clone()));
56+
let static_aliases = warp::any()
57+
.and(static_aliases_filter(opts.static_aliases.clone()))
58+
.and_then(serve_file);
5559

5660
// Define some filters to handle all the data we want to pass through
5761
let opts = Arc::new(opts);

packages/perseus-warp/src/static_content.rs

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::collections::HashMap;
2-
2+
use std::sync::Arc;
3+
use warp::fs::{file_reply, ArcPath, Conditionals, File};
34
use warp::{path::FullPath, Filter, Rejection};
45

56
/// A filter for static aliases that determines which file to serve.
@@ -23,9 +24,67 @@ pub fn static_aliases_filter(
2324
if file_to_serve.is_empty() {
2425
Err(warp::reject::not_found())
2526
} else {
26-
// TODO Return the actual file (see Warp internals for this)
2727
Ok(file_to_serve)
2828
}
2929
},
3030
)
3131
}
32+
33+
/// Serves the file provided through the filter.
34+
pub async fn serve_file(path: String) -> Result<File, Rejection> {
35+
let arc_path = ArcPath(Arc::new(path.into()));
36+
let conds = Conditionals::default();
37+
file_reply(arc_path, conds).await
38+
}
39+
40+
// /// Serves the file provided through the filter. This returns an error because we assume that the file is supposed to exist at this point (this is used for static
41+
// /// aliases).
42+
// pub async fn serve_file(path: String) -> Result<Response, Rejection> {
43+
// match TkFile::open(path).await {
44+
// Ok(file) => {
45+
// let metadata = file.metadata().await.map_err(|e| warp::reject::not_found())?;
46+
// let stream = file_stream(file, metadata);
47+
// let res = Response::new(Body::wrap_stream(stream));
48+
49+
// Ok(res)
50+
// },
51+
// // If a static alias can't be found, we'll act as if it doesn't exist and proceed to the next handler
52+
// Err(_) => Err(warp::reject::not_found())
53+
// }
54+
// }
55+
56+
// // The default chunk size for streaming a file (taken from Warp's internals)
57+
// const DFLT_BUF_SIZE: usize = 8_192;
58+
// #[cfg(unix)]
59+
// fn get_buf_size(metadata: Metadata) -> usize {
60+
// use std::os::unix::prelude::MetadataExt;
61+
62+
// std::cmp::max(metadata.blksize() as usize, DFLT_BUF_SIZE)
63+
// }
64+
// #[cfg(not(unix))]
65+
// fn get_buf_size(_metadata: Metadata) -> usize {
66+
// DFLT_BUF_SIZE // On Windows, we don't have a blocksize function based on the metadata
67+
// }
68+
69+
// /// Reserves more space in a buffer if needed
70+
// fn reserve_if_needed(buf: &mut BytesMut, cap: usize) {
71+
// if buf.capacity() - buf.len() < cap {
72+
// buf.reserve(cap);
73+
// }
74+
// }
75+
76+
// fn file_stream(mut file: TkFile, metadata: Metadata) -> impl Stream<Item = Result<Bytes, std::io::Error>> + Send {
77+
// let buf_size = get_buf_size(metadata);
78+
// let stream = file.seek(SeekFrom::Start(0));
79+
80+
// let mut buf = BytesMut::new();
81+
// reserve_if_needed(&mut buf, buf_size);
82+
83+
// try_stream! {
84+
// for i in 0u8..3 {
85+
// reserve_if_needed(&mut buf, buf_size);
86+
// let n = file.read(&mut buf).await?;
87+
// yield Bytes::from(buf[..n]);
88+
// }
89+
// }
90+
// }

0 commit comments

Comments
 (0)