78 lines
2.3 KiB
Rust
78 lines
2.3 KiB
Rust
use poem::{
|
|
error::ResponseError,
|
|
handler,
|
|
http::{header, StatusCode},
|
|
web::{Data, Redirect},
|
|
IntoResponse, Request, Response, Result,
|
|
};
|
|
|
|
use crate::{storage::StorageError, util, Talon};
|
|
|
|
#[derive(thiserror::Error, Debug)]
|
|
pub enum PageError {
|
|
#[error("invalid subdomain")]
|
|
InvalidSubdomain,
|
|
#[error("website does not have any version")]
|
|
NoVersion,
|
|
}
|
|
|
|
impl ResponseError for PageError {
|
|
fn status(&self) -> StatusCode {
|
|
StatusCode::NOT_FOUND
|
|
}
|
|
}
|
|
|
|
#[handler]
|
|
pub async fn page(request: &Request, talon: Data<&Talon>) -> Result<Response> {
|
|
let host = request
|
|
.header(header::HOST)
|
|
.ok_or(PageError::InvalidSubdomain)?;
|
|
let (subdomain, vid) =
|
|
util::parse_host(host, &talon.cfg.server.root_domain).ok_or(PageError::InvalidSubdomain)?;
|
|
|
|
let vid = match vid {
|
|
Some(vid) => vid,
|
|
None => {
|
|
let ws = talon.db.get_website(subdomain)?;
|
|
ws.latest_version.ok_or(PageError::NoVersion)?
|
|
}
|
|
};
|
|
|
|
let (file, ok) =
|
|
match talon
|
|
.storage
|
|
.get_file(subdomain, vid, request.uri().path(), request.headers())
|
|
{
|
|
Ok(file) => (file, true),
|
|
Err(StorageError::NotFound(f)) => {
|
|
let version = talon.db.get_version(subdomain, vid)?;
|
|
if let Some(fallback) = &version.fallback {
|
|
(
|
|
talon
|
|
.storage
|
|
.get_file(subdomain, vid, fallback, request.headers())?,
|
|
version.spa,
|
|
)
|
|
} else if version.spa {
|
|
(
|
|
talon
|
|
.storage
|
|
.get_file(subdomain, vid, "", request.headers())?,
|
|
true,
|
|
)
|
|
} else {
|
|
return Err(StorageError::NotFound(f).into());
|
|
}
|
|
}
|
|
Err(e) => return Err(e.into()),
|
|
};
|
|
|
|
Ok(match file.rd_path {
|
|
Some(rd_path) => Redirect::moved_permanent(rd_path).into_response(),
|
|
None => talon
|
|
.storage
|
|
.file_to_response(file, request.headers(), ok)
|
|
.await?
|
|
.into_response(),
|
|
})
|
|
}
|