//! 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, ) -> 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, ) -> web::Either { 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())), ) }, ) }