Update web to serve embedded static files
This commit is contained in:
parent
9ab794a75a
commit
07d43ff6b5
93
Cargo.lock
generated
93
Cargo.lock
generated
@ -1141,6 +1141,41 @@ dependencies = [
|
|||||||
"uncased",
|
"uncased",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rust-embed"
|
||||||
|
version = "6.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cb133b9a38b5543fad3807fb2028ea47c5f2b566f4f5e28a11902f1a358348b6"
|
||||||
|
dependencies = [
|
||||||
|
"rocket",
|
||||||
|
"rust-embed-impl",
|
||||||
|
"rust-embed-utils",
|
||||||
|
"walkdir",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rust-embed-impl"
|
||||||
|
version = "6.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4d4e0f0ced47ded9a68374ac145edd65a6c1fa13a96447b873660b2a568a0fd7"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"rust-embed-utils",
|
||||||
|
"syn",
|
||||||
|
"walkdir",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rust-embed-utils"
|
||||||
|
version = "7.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "512b0ab6853f7e14e3c8754acb43d6f748bb9ced66aa5915a6553ac8213f7731"
|
||||||
|
dependencies = [
|
||||||
|
"sha2",
|
||||||
|
"walkdir",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustversion"
|
name = "rustversion"
|
||||||
version = "1.0.11"
|
version = "1.0.11"
|
||||||
@ -1165,6 +1200,15 @@ dependencies = [
|
|||||||
"libm",
|
"libm",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "same-file"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scoped-tls"
|
name = "scoped-tls"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
@ -1533,6 +1577,33 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ufmt"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a64846ec02b57e9108d6469d98d1648782ad6bb150a95a9baac26900bbeab9d"
|
||||||
|
dependencies = [
|
||||||
|
"ufmt-macros",
|
||||||
|
"ufmt-write",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ufmt-macros"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d337d3be617449165cb4633c8dece429afd83f84051024079f97ad32a9663716"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ufmt-write"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e87a2ed6b42ec5e28cc3b94c09982969e9227600b2e3dcbc1db927a84c06bd69"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uncased"
|
name = "uncased"
|
||||||
version = "0.9.7"
|
version = "0.9.7"
|
||||||
@ -1577,6 +1648,17 @@ version = "0.9.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "walkdir"
|
||||||
|
version = "2.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
|
||||||
|
dependencies = [
|
||||||
|
"same-file",
|
||||||
|
"winapi",
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "want"
|
name = "want"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
@ -1652,8 +1734,10 @@ name = "web"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rocket",
|
"rocket",
|
||||||
|
"rust-embed",
|
||||||
"serde",
|
"serde",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"ufmt",
|
||||||
"xpin",
|
"xpin",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1673,6 +1757,15 @@ version = "0.4.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-util"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-x86_64-pc-windows-gnu"
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
@ -10,3 +10,5 @@ rocket = {version="0.5.0-rc.2", features=["json"]}
|
|||||||
tokio = {version="1"}
|
tokio = {version="1"}
|
||||||
xpin={path=".."}
|
xpin={path=".."}
|
||||||
serde = {version="1", features=["derive"]}
|
serde = {version="1", features=["derive"]}
|
||||||
|
rust-embed = { version = "6.6.0", features = ["rocket"] }
|
||||||
|
ufmt = "0.2.0"
|
||||||
|
65
web/src/api.rs
Normal file
65
web/src/api.rs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use rocket::{get, serde::json::Json, Responder};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use xpin::Address;
|
||||||
|
|
||||||
|
#[get("/address?<lat>&<lon>")]
|
||||||
|
pub(crate) fn get_address(lat: Option<String>, lon: Option<String>) -> Result<String, ApiError> {
|
||||||
|
let (lat, lon) = lat.zip(lon).ok_or(ApiError::InvalidRequest(
|
||||||
|
"lat and lon parameters are required",
|
||||||
|
))?;
|
||||||
|
let lat = lat
|
||||||
|
.parse::<f64>()
|
||||||
|
.map_err(|_| ApiError::InvalidRequest("Invalid lat parameter"))?;
|
||||||
|
let lon = lon
|
||||||
|
.parse::<f64>()
|
||||||
|
.map_err(|_| ApiError::InvalidRequest("Invalid lon parameter"))?;
|
||||||
|
|
||||||
|
Ok(Address::from_lat_lon(lat, lon)?.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/coords?<address>")]
|
||||||
|
pub(crate) fn get_coords(address: Option<String>) -> Result<Json<Coords>, ApiError> {
|
||||||
|
let address = address.ok_or(ApiError::InvalidRequest("address parameter required"))?;
|
||||||
|
|
||||||
|
Address::from_str(&address)
|
||||||
|
.as_ref()
|
||||||
|
.map_err(Into::into)
|
||||||
|
.map(Address::as_lat_lon)
|
||||||
|
.map(Coords::from)
|
||||||
|
.map(Json)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub(crate) struct Coords {
|
||||||
|
lat: f64,
|
||||||
|
lon: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<(f64, f64)> for Coords {
|
||||||
|
fn from((lat, lon): (f64, f64)) -> Self {
|
||||||
|
Self { lat, lon }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Responder)]
|
||||||
|
#[response(status = 400)]
|
||||||
|
pub(crate) enum ApiError {
|
||||||
|
#[response(status = 400)]
|
||||||
|
AlgorithmError(String),
|
||||||
|
#[response(status = 400)]
|
||||||
|
InvalidRequest(&'static str),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&xpin::Error> for ApiError {
|
||||||
|
fn from(e: &xpin::Error) -> Self {
|
||||||
|
Self::AlgorithmError(e.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<xpin::Error> for ApiError {
|
||||||
|
fn from(e: xpin::Error) -> Self {
|
||||||
|
Self::from(&e)
|
||||||
|
}
|
||||||
|
}
|
@ -1,78 +1,17 @@
|
|||||||
use std::str::FromStr;
|
mod api;
|
||||||
|
mod static_assets;
|
||||||
|
|
||||||
use rocket::{get, routes, serde::json::Json, Responder};
|
use rocket::routes;
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use xpin::Address;
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let _r = rocket::build()
|
let _r = rocket::build()
|
||||||
// Add the API
|
// Add the API
|
||||||
.mount("/api/v1", routes![get_address, get_coords])
|
.mount("/api/v1", routes![api::get_address, api::get_coords])
|
||||||
// Add the webui frontend
|
// Add the webui frontend
|
||||||
// TODO: ./mount("/", routes![webui])
|
.mount("/", routes![static_assets::dist])
|
||||||
.launch()
|
.launch()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/address?<lat>&<lon>")]
|
|
||||||
async fn get_address(lat: Option<String>, lon: Option<String>) -> Result<String, ApiError> {
|
|
||||||
let (lat, lon) = lat.zip(lon).ok_or(ApiError::InvalidRequest(
|
|
||||||
"lat and lon parameters are required",
|
|
||||||
))?;
|
|
||||||
let lat = lat
|
|
||||||
.parse::<f64>()
|
|
||||||
.map_err(|_| ApiError::InvalidRequest("Invalid lat parameter"))?;
|
|
||||||
let lon = lon
|
|
||||||
.parse::<f64>()
|
|
||||||
.map_err(|_| ApiError::InvalidRequest("Invalid lon parameter"))?;
|
|
||||||
|
|
||||||
Ok(Address::from_lat_lon(lat, lon)?.to_string())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[get("/coords?<address>")]
|
|
||||||
async fn get_coords(address: Option<String>) -> Result<Json<Coords>, ApiError> {
|
|
||||||
let address = address.ok_or(ApiError::InvalidRequest("address parameter required"))?;
|
|
||||||
|
|
||||||
Address::from_str(&address)
|
|
||||||
.as_ref()
|
|
||||||
.map_err(Into::into)
|
|
||||||
.map(Address::as_lat_lon)
|
|
||||||
.map(Coords::from)
|
|
||||||
.map(Json)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
struct Coords {
|
|
||||||
lat: f64,
|
|
||||||
lon: f64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<(f64, f64)> for Coords {
|
|
||||||
fn from((lat, lon): (f64, f64)) -> Self {
|
|
||||||
Self { lat, lon }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Responder)]
|
|
||||||
#[response(status = 400)]
|
|
||||||
enum ApiError {
|
|
||||||
#[response(status = 400)]
|
|
||||||
AlgorithmError(String),
|
|
||||||
#[response(status = 400)]
|
|
||||||
InvalidRequest(&'static str),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&xpin::Error> for ApiError {
|
|
||||||
fn from(e: &xpin::Error) -> Self {
|
|
||||||
Self::AlgorithmError(e.to_string())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<xpin::Error> for ApiError {
|
|
||||||
fn from(e: xpin::Error) -> Self {
|
|
||||||
Self::from(&e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
30
web/src/static_assets.rs
Normal file
30
web/src/static_assets.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
use rocket::get;
|
||||||
|
use rocket::http::ContentType;
|
||||||
|
use rust_embed::RustEmbed;
|
||||||
|
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use std::ffi::OsStr;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
#[derive(RustEmbed)]
|
||||||
|
#[folder = "../build/"]
|
||||||
|
struct Asset;
|
||||||
|
|
||||||
|
#[get("/<file..>")]
|
||||||
|
pub(crate) fn dist(file: PathBuf) -> Option<(ContentType, Cow<'static, [u8]>)> {
|
||||||
|
if let Some(a) = Asset::get(&format!("{}", file.display().to_string())) {
|
||||||
|
let content_type = file
|
||||||
|
.extension()
|
||||||
|
.and_then(OsStr::to_str)
|
||||||
|
.and_then(ContentType::from_extension)
|
||||||
|
.unwrap_or(ContentType::Bytes);
|
||||||
|
|
||||||
|
return Some((content_type, a.data));
|
||||||
|
}
|
||||||
|
|
||||||
|
[".html", "index.html"].iter().find_map(|ext| {
|
||||||
|
let p = format!("{}{}", file.display().to_string(), ext);
|
||||||
|
|
||||||
|
Asset::get(&p).map(|a| (ContentType::HTML, a.data))
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user