124 lines
3.7 KiB
Rust
124 lines
3.7 KiB
Rust
use build_html::Html;
|
|
use http::{Error, StatusCode};
|
|
use std::collections::HashMap;
|
|
use warp::http::Response;
|
|
|
|
use crate::{pages, App, AuthToken, FileId, FileInfo, ReadFileError, SessionToken};
|
|
|
|
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"))),
|
|
}
|
|
}
|
|
|
|
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![]),
|
|
},
|
|
}
|
|
}
|