monorepo/file-service/src/handlers.rs

124 lines
3.7 KiB
Rust
Raw Normal View History

2023-10-03 15:10:37 +00:00
use build_html::Html;
use http::{Error, StatusCode};
2023-10-03 20:18:19 +00:00
use std::collections::HashMap;
2023-10-03 15:10:37 +00:00
use warp::http::Response;
2023-10-03 20:18:19 +00:00
use crate::{pages, App, AuthToken, FileId, FileInfo, ReadFileError, SessionToken};
2023-10-03 15:10:37 +00:00
pub async fn handle_index(
app: App,
token: Option<SessionToken>,
) -> Result<Response<String>, Error> {
match token {
Some(token) => match app.auth_session(token).await {
Ok(_) => render_gallery_page(app).await,
Err(err) => render_auth_page(Some(format!("authentication refused: {:?}", err))),
},
None => render_auth_page(None),
}
}
pub fn render_auth_page(message: Option<String>) -> Result<Response<String>, Error> {
Response::builder()
.status(StatusCode::OK)
.body(pages::auth(message).to_html_string())
}
pub async fn render_gallery_page(app: App) -> Result<Response<String>, Error> {
match app.list_files().await {
Ok(ids) => {
let mut files = vec![];
for id in ids.into_iter() {
let file = app.get_file(&id).await;
files.push(file);
}
Response::builder()
.header("content-type", "text/html")
.status(StatusCode::OK)
.body(pages::gallery(files).to_html_string())
}
Err(_) => Response::builder()
.header("content-type", "text/html")
.status(StatusCode::INTERNAL_SERVER_ERROR)
.body("".to_owned()),
}
}
pub async fn thumbnail(
app: App,
id: String,
old_etags: Option<String>,
) -> Result<Response<Vec<u8>>, Error> {
match app.get_file(&FileId::from(id)).await {
Ok(file) => serve_file(file.info.clone(), || file.thumbnail(), old_etags),
Err(_err) => Response::builder()
.status(StatusCode::NOT_FOUND)
.body(vec![]),
}
}
pub async fn file(
app: App,
id: String,
old_etags: Option<String>,
) -> Result<Response<Vec<u8>>, Error> {
match app.get_file(&FileId::from(id)).await {
Ok(file) => serve_file(file.info.clone(), || file.thumbnail(), old_etags),
Err(_err) => Response::builder()
.status(StatusCode::NOT_FOUND)
.body(vec![]),
}
}
pub async fn handle_auth(
app: App,
form: HashMap<String, String>,
) -> Result<http::Response<String>, Error> {
match form.get("token") {
Some(token) => match app
.auth_token(AuthToken::from(AuthToken::from(token.clone())))
.await
{
Ok(_session_token) => render_gallery_page(app).await,
Err(_) => render_auth_page(Some(format!("invalid auth token"))),
},
None => render_auth_page(Some(format!("no token available"))),
}
2023-10-03 15:10:37 +00:00
}
pub async fn handle_upload(
_app: App,
_token: SessionToken,
) -> Result<http::Response<String>, Error> {
println!("handle_upload");
Response::builder()
.status(StatusCode::NOT_IMPLEMENTED)
.body("".to_owned())
}
fn serve_file<F>(
info: FileInfo,
file: F,
old_etags: Option<String>,
) -> http::Result<http::Response<Vec<u8>>>
where
F: FnOnce() -> Result<Vec<u8>, ReadFileError>,
{
match old_etags {
Some(old_etags) if old_etags != info.hash => Response::builder()
.header("content-type", info.file_type)
.status(StatusCode::NOT_MODIFIED)
.body(vec![]),
_ => match file() {
Ok(content) => Response::builder()
.header("content-type", info.file_type)
.header("etag", info.hash)
.status(StatusCode::OK)
.body(content),
Err(_) => Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.body(vec![]),
},
}
}