2021-12-29 18:33:31 +01:00
|
|
|
use axum::{
|
|
|
|
body::Body,
|
|
|
|
extract::{Extension, Path},
|
|
|
|
handler::get,
|
|
|
|
http::HeaderMap,
|
|
|
|
response::IntoResponse,
|
|
|
|
routing::BoxRoute,
|
|
|
|
Router,
|
|
|
|
};
|
2021-12-18 20:04:34 +01:00
|
|
|
use headers::{ContentType, HeaderMapExt};
|
2021-12-29 18:33:31 +01:00
|
|
|
use reqwest::{
|
|
|
|
header::{HeaderName, CONTENT_LENGTH},
|
|
|
|
StatusCode,
|
|
|
|
};
|
|
|
|
use sqlx::MySqlPool;
|
2021-12-18 20:04:34 +01:00
|
|
|
|
|
|
|
use crate::config::ConfVars;
|
|
|
|
|
2021-12-29 18:33:31 +01:00
|
|
|
use self::{
|
2022-01-05 23:46:19 +01:00
|
|
|
error::CDNError,
|
2021-12-29 18:33:31 +01:00
|
|
|
templates::{DirTemplate, HtmlTemplate},
|
|
|
|
};
|
2021-12-18 21:15:06 +01:00
|
|
|
|
2021-12-29 18:33:31 +01:00
|
|
|
mod error;
|
2021-12-18 20:04:34 +01:00
|
|
|
mod sql;
|
2021-12-18 21:15:06 +01:00
|
|
|
mod templates;
|
2021-12-18 20:04:34 +01:00
|
|
|
|
|
|
|
pub fn routes() -> Router<BoxRoute> {
|
|
|
|
Router::new()
|
2021-12-29 18:33:31 +01:00
|
|
|
.route("/", get(users))
|
|
|
|
.route("/:user/", get(memes))
|
|
|
|
.route("/:user/:filename", get(image))
|
|
|
|
.boxed()
|
2021-12-18 20:04:34 +01:00
|
|
|
}
|
|
|
|
|
2021-12-29 18:33:31 +01:00
|
|
|
async fn image(
|
|
|
|
Path((user, filename)): Path<(String, String)>,
|
|
|
|
Extension(db_pool): Extension<MySqlPool>,
|
|
|
|
Extension(vars): Extension<ConfVars>,
|
2022-01-05 23:46:19 +01:00
|
|
|
) -> Result<impl IntoResponse, CDNError> {
|
2021-12-29 18:33:31 +01:00
|
|
|
let filename = urlencoding::decode(&filename)?.into_owned();
|
|
|
|
let cid = sql::get_cid(user, filename.clone(), &db_pool).await?;
|
|
|
|
let ipfs = vars.ipfs_client()?;
|
|
|
|
let res = ipfs.cat(cid).await?;
|
|
|
|
let clength = res
|
|
|
|
.headers()
|
2022-01-05 23:46:19 +01:00
|
|
|
.get(HeaderName::from_static("x-content-length"))
|
|
|
|
.ok_or(CDNError::Internal)?;
|
2021-12-29 18:33:31 +01:00
|
|
|
|
2022-01-05 23:46:19 +01:00
|
|
|
let mut headers = HeaderMap::new();
|
|
|
|
let ctype = ContentType::from(new_mime_guess::from_path(filename).first_or_octet_stream());
|
|
|
|
headers.typed_insert(ctype);
|
|
|
|
headers.insert(CONTENT_LENGTH, clength.clone());
|
|
|
|
|
|
|
|
Ok((
|
|
|
|
StatusCode::OK,
|
|
|
|
headers,
|
|
|
|
Body::wrap_stream(res.bytes_stream()),
|
|
|
|
))
|
2021-12-18 21:15:06 +01:00
|
|
|
}
|
|
|
|
|
2021-12-29 18:33:31 +01:00
|
|
|
async fn users(
|
|
|
|
Extension(db_pool): Extension<MySqlPool>,
|
|
|
|
Extension(vars): Extension<ConfVars>,
|
2022-01-05 23:46:19 +01:00
|
|
|
) -> Result<impl IntoResponse, CDNError> {
|
|
|
|
let users = sql::get_users(&db_pool).await?;
|
|
|
|
Ok(HtmlTemplate(DirTemplate {
|
|
|
|
entries: users,
|
|
|
|
prefix: vars.cdn,
|
|
|
|
suffix: "/".to_string(),
|
|
|
|
}))
|
2021-12-18 21:15:06 +01:00
|
|
|
}
|
|
|
|
|
2021-12-29 18:33:31 +01:00
|
|
|
async fn memes(
|
|
|
|
Path(user): Path<String>,
|
|
|
|
Extension(db_pool): Extension<MySqlPool>,
|
2022-01-05 23:46:19 +01:00
|
|
|
) -> Result<impl IntoResponse, CDNError> {
|
|
|
|
let memes = sql::get_memes(user, &db_pool).await?;
|
|
|
|
Ok(HtmlTemplate(DirTemplate {
|
|
|
|
entries: memes,
|
|
|
|
prefix: ".".to_string(),
|
|
|
|
suffix: "".to_string(),
|
|
|
|
}))
|
2021-12-29 18:33:31 +01:00
|
|
|
}
|