1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
use std::{convert::Infallible, net::SocketAddr, sync::Arc};
use warp::{hyper::StatusCode, Filter, Rejection, Reply};
use crate::{dimension::Dimension, render::Renderer, tiling::Tiler};
pub fn serve_http(dimension: Dimension, bind: SocketAddr) {
tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.unwrap()
.block_on(async move {
let renderer = Renderer::new(dimension);
let tiler = Arc::new(Tiler::new(renderer));
let tiler: _ = warp::any().map(move || tiler.clone());
let tiles = warp::path!("tiles" / isize / isize / isize)
.and(tiler.clone())
.and_then(|z, x, y, tiler: Arc<Tiler>| async move {
Ok::<_, Infallible>(warp::reply::with_header(
tiler.get_tile(z, x, y), // TODO consider using tokio::spawn_blocking so we dont block the event loop
"content-type",
"image/png",
))
});
let viewer_html: _ = warp::path!().and(warp::fs::file("./src/viewer/viewer.html"));
let viewer_js: _ =
warp::path!("viewer.js").and(warp::fs::file("./src/viewer/viewer.js"));
let router: _ = tiles
.or(viewer_html)
.or(viewer_js)
.recover(handle_rejection);
warp::serve(router).run(bind).await;
})
}
async fn handle_rejection(err: Rejection) -> Result<impl Reply, Infallible> {
let code;
let message;
if err.is_not_found() {
code = StatusCode::NOT_FOUND;
message = "Not found";
} else if let Some(_) = err.find::<warp::reject::MethodNotAllowed>() {
code = StatusCode::METHOD_NOT_ALLOWED;
message = "Method not allowed";
} else {
eprintln!("unhandled rejection: {:?}", err);
code = StatusCode::INTERNAL_SERVER_ERROR;
message = "Unhandled rejection :(";
}
Ok(warp::reply::with_status(message, code))
}
|