The smokesignal.events web application
at main 52 lines 1.7 kB view raw
1use anyhow::Result; 2use axum::{ 3 body::Body, 4 extract::{Path, State}, 5 response::{IntoResponse, Response}, 6}; 7use http::{StatusCode, header}; 8 9use crate::http::{context::WebContext, errors::WebError}; 10 11/// GET /content/{cid} - Handle content requests. 12/// Gets content from content storage and returns it as a response. 13pub(crate) async fn handle_content( 14 State(web_context): State<WebContext>, 15 Path(cid): Path<String>, 16) -> Result<impl IntoResponse, WebError> { 17 tracing::info!(?cid, "cid"); 18 let exists = match web_context.content_storage.content_exists(&cid).await { 19 Ok(exists) => exists, 20 Err(_) => return Ok((StatusCode::INTERNAL_SERVER_ERROR).into_response()), 21 }; 22 23 tracing::info!(?exists, "exists"); 24 25 if !exists { 26 return Ok((StatusCode::NOT_FOUND).into_response()); 27 } 28 29 // Read the content data 30 let content_data = match web_context.content_storage.read_content(&cid).await { 31 Ok(data) => data, 32 Err(_) => return Ok((StatusCode::INTERNAL_SERVER_ERROR).into_response()), 33 }; 34 35 // Detect content type from the original path extension 36 let content_type = if cid.ends_with(".png") { 37 "image/png" 38 } else if cid.ends_with(".jpg") || cid.ends_with(".jpeg") { 39 "image/jpeg" 40 } else { 41 "application/octet-stream" 42 }; 43 44 // Return the content with appropriate headers 45 Ok(Response::builder() 46 .status(StatusCode::OK) 47 .header(header::CONTENT_TYPE, content_type) 48 .header(header::CACHE_CONTROL, "public, max-age=86400") // Cache for 1 day 49 .body(Body::from(content_data)) 50 .unwrap() 51 .into_response()) 52}