feat: todo's, add image cache control

This commit is contained in:
2026-03-20 21:47:48 +01:00
parent 12388a9908
commit 0dbc9dcbc1
8 changed files with 143 additions and 38 deletions

View File

@@ -14,13 +14,12 @@ pub struct AppState {
/// Leaks memory for the sake of not atomic'ing all over.
#[expect(clippy::missing_errors_doc)]
pub async fn start_app(args: crate::args::Args, config: crate::conf::Config) -> io::Result<()> {
use crate::consts::web_scopes as ws;
let config = Box::leak(Box::new(config));
let cache = caches::AppCache::new(
config.unix.magic_paths.clone(),
// ["/usr/share/file/misc/magic"]
// .try_into()
// .expect("To be valid DB paths"),
&config.unix.groups,
);
@@ -38,8 +37,7 @@ pub async fn start_app(args: crate::args::Args, config: crate::conf::Config) ->
HttpServer::new(move || {
App::new()
.app_data(web::Data::new(app))
.service(services::get_image)
// .service(factory)
.service(services::images::make_scope(ws::IMAGES))
})
.bind(&app.config.server.listen)?
.run()

View File

@@ -0,0 +1,60 @@
//! Scope for the image get backend.
//! - `/`: Gives the default image.
//! - `/{username}`: Gives username's pfp or redirects to the default image's path (for better
//! cache control) if there's no image.
//!
//! Must be scoped at [`ws::IMAGES`]
// TODO: etags
use actix_web::{
HttpResponse, get,
http::header,
web::{self, Redirect},
};
use crate::{
consts::{self, web_scopes as ws},
server,
};
#[must_use]
pub fn make_scope(path: &str) -> actix_web::Scope {
web::scope(path)
.service(get_default_image)
.service(get_image)
}
#[get("/")]
async fn get_default_image(
_data: web::Data<&server::AppState>,
_username: web::Path<String>,
) -> HttpResponse {
HttpResponse::Ok()
.insert_header((
header::CACHE_CONTROL,
consts::DEFAULT_USER_PFP_CACHES_HEADER,
))
.content_type(consts::DEFAULT_USER_PFP_MIME)
.body(web::Bytes::from_static(consts::DEFAULT_USER_PFP))
}
#[get("/{username}")]
async fn get_image(
data: web::Data<&server::AppState>,
username: web::Path<String>,
) -> web::Either<Redirect, HttpResponse> {
let cached_pfp = data.cache.get_pfp(username.to_string()).await;
cached_pfp.as_ref().map_or_else(
|| web::Either::Left(web::Redirect::to(ws::IMAGES).temporary()),
|img| {
web::Either::Right(
HttpResponse::Ok()
.insert_header((header::CACHE_CONTROL, consts::USER_CACHES_HEADER))
.content_type(img.mime.as_ref())
.body(web::Bytes::copy_from_slice(img.bytes.as_ref())),
)
},
)
}

View File

@@ -1,30 +1 @@
use actix_web::{HttpResponse, get, web};
use crate::{consts, server};
// TODO: cache control
// TODO: etags
// TODO: canonical redirect for default image and better cache control
#[get("/image/{username}")]
pub async fn get_image(
data: web::Data<&server::AppState>,
username: web::Path<String>,
) -> HttpResponse {
let cached_pfp = data.cache.get_pfp(username.to_string()).await;
let (mime, bytes) = cached_pfp.as_ref().map_or_else(
|| {
(
consts::DEFAULT_USER_PFP_MIME,
web::Bytes::from_static(consts::DEFAULT_USER_PFP),
)
},
|img| {
(
img.mime.as_ref(),
web::Bytes::copy_from_slice(img.bytes.as_ref()),
)
},
);
HttpResponse::Ok().content_type(mime).body(bytes)
}
pub mod images;