Skip to content

Commit

Permalink
Move service logics to services
Browse files Browse the repository at this point in the history
  • Loading branch information
marshallku committed Sep 2, 2024
1 parent 01371fd commit 3c8a01d
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 55 deletions.
61 changes: 6 additions & 55 deletions src/controllers/images.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,68 +2,19 @@ use axum::{
extract::{Path, State},
response::IntoResponse,
};
use reqwest::StatusCode;

use std::path::PathBuf;
use tracing::error;

use crate::{
constants::CDN_ROOT,
env::state::AppState,
utils::{
fetch::fetch_and_cache,
http::{response_error, response_file},
img::{save_image_to_webp, save_resized_image},
path::{get_original_path, get_resize_width_from_path},
},
constants::CDN_ROOT, env::state::AppState, services::image::process_image_request,
utils::http::response_error,
};

pub async fn get(State(state): State<AppState>, Path(path): Path<String>) -> impl IntoResponse {
let file_path = PathBuf::from(format!("{}/images/{}", CDN_ROOT, path));

if file_path.exists() {
error!("File exists but respond with Rust: {:?}", file_path);
return response_file(&file_path).await;
}

let resize_width = get_resize_width_from_path(&path);
let convert_to_webp = path.ends_with(".webp");
let original_path = get_original_path(&path, resize_width.is_some());
let original_file_path = PathBuf::from(format!("{}/images/{}", CDN_ROOT, original_path));

if !original_file_path.exists() {
if let Err(_) = fetch_and_cache(state.host, &original_file_path, &original_path).await {
return response_error(StatusCode::NOT_FOUND);
}
}

if resize_width.is_none() && !convert_to_webp {
return response_file(&file_path).await;
}

let image = match image::open(&original_file_path) {
Ok(image) => image,
Err(_) => {
return response_error(StatusCode::INTERNAL_SERVER_ERROR);
}
};

if !convert_to_webp {
return save_resized_image(image, resize_width, &original_file_path, &file_path).await;
match process_image_request(&state, &path, &file_path).await {
Ok(response) => response,
Err(status) => response_error(status),
}

let path_with_webp = format!("{}.webp", original_path);
let file_path_with_webp = PathBuf::from(format!("{}/images/{}", CDN_ROOT, path_with_webp));

if let Err(_) = save_image_to_webp(&image, &file_path_with_webp) {
return response_error(StatusCode::INTERNAL_SERVER_ERROR);
}

let image_webp = match image::open(&file_path_with_webp) {
Ok(image) => image,
Err(_) => {
return response_error(StatusCode::INTERNAL_SERVER_ERROR);
}
};

save_resized_image(image_webp, resize_width, &file_path_with_webp, &file_path).await
}
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod constants;
mod controllers;
mod env;
mod services;
mod utils;

use controllers::app::app;
Expand Down
87 changes: 87 additions & 0 deletions src/services/image.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use axum::response::Response;
use image::DynamicImage;
use reqwest::StatusCode;
use std::path::PathBuf;
use tracing::error;

use crate::{
env::state::AppState,
utils::{
fetch::fetch_and_cache,
http::response_file,
img::{save_image_to_webp, save_resized_image},
path::{get_original_path, get_resize_width_from_path},
},
};

pub async fn process_image_request(
state: &AppState,
path: &str,
file_path: &PathBuf,
) -> Result<Response, StatusCode> {
if file_path.exists() {
error!("File exists but respond with Rust: {:?}", file_path);
return Ok(response_file(&file_path).await);
}

let resize_width = get_resize_width_from_path(path);
let convert_to_webp = path.ends_with(".webp");
let original_path = get_original_path(path, resize_width.is_some());
let original_file_path = PathBuf::from(format!(
"{}/images/{}",
crate::constants::CDN_ROOT,
original_path
));

ensure_original_file_exists(state, &original_file_path, &original_path).await?;

if resize_width.is_none() && !convert_to_webp {
return Ok(response_file(&file_path).await);
}

let image = open_image(&original_file_path)?;

if !convert_to_webp {
return Ok(save_resized_image(image, resize_width, &original_file_path, &file_path).await);
}

process_webp_image(image, resize_width, path, file_path).await
}

async fn ensure_original_file_exists(
state: &AppState,
original_file_path: &PathBuf,
original_path: &str,
) -> Result<(), StatusCode> {
if !original_file_path.exists() {
fetch_and_cache(state.host.clone(), original_file_path, original_path)
.await
.map_err(|_| StatusCode::NOT_FOUND)?;
}
Ok(())
}

fn open_image(file_path: &PathBuf) -> Result<DynamicImage, StatusCode> {
image::open(file_path).map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
}

async fn process_webp_image(
image: DynamicImage,
resize_width: Option<u32>,
path: &str,
file_path: &PathBuf,
) -> Result<Response, StatusCode> {
let path_with_webp = format!("{}.webp", path);
let file_path_with_webp = PathBuf::from(format!(
"{}/images/{}",
crate::constants::CDN_ROOT,
path_with_webp
));

save_image_to_webp(&image, &file_path_with_webp)
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

let image_webp = open_image(&file_path_with_webp)?;

Ok(save_resized_image(image_webp, resize_width, &file_path_with_webp, file_path).await)
}
1 change: 1 addition & 0 deletions src/services/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod image;

0 comments on commit 3c8a01d

Please sign in to comment.