feat: add support for image file in checkout

Signed-off-by: Pakin <pakin.t@forth.co.th>
This commit is contained in:
Pakin 2026-02-17 15:17:04 +07:00
parent a2da030a99
commit 6fe3357efe
3 changed files with 651 additions and 12 deletions

View file

@ -3,8 +3,9 @@ use std::{collections::HashMap, io::Cursor, sync::Arc, time::Duration};
use async_compression::tokio::bufread::BrotliEncoder;
use axum::{
Json, Router,
body::Body,
extract::{Query, State},
response::IntoResponse,
response::{IntoResponse, Response},
routing::{get, post},
};
use axum_macros::debug_handler;
@ -12,8 +13,10 @@ use bb8::Pool;
use bb8_redis::RedisConnectionManager;
use git2::{Cred, FetchOptions, PushOptions, RemoteCallbacks, Repository};
use image::load_from_memory;
use log::{error, info, warn};
use redis::{AsyncTypedCommands, TypedCommands, aio::MultiplexedConnection};
use reqwest::header;
use serde::Deserialize;
use serde_json::{Value, json};
use tokio::{
@ -71,6 +74,14 @@ impl AppState {
}
}
const SUPPORTED_IMAGES: [&str; 6] = ["jpg", "jpeg", "png", "gif", "bmp", "webp"];
fn is_supported_image_file_type(name: String) -> bool {
let ext = name.split(".").last().unwrap_or("");
SUPPORTED_IMAGES.contains(&ext)
}
#[derive(Deserialize, Debug)]
struct CheckoutParams {
path: String,
@ -99,7 +110,7 @@ async fn checkout_handler(
if let Ok(res) = conn.get(param.path.clone().as_str().to_string()).await {
if let Some(res) = res {
response.insert("result".to_string(), json!(res));
return (axum::http::StatusCode::OK, Json(json!(response)));
return (axum::http::StatusCode::OK, Json(json!(response))).into_response();
}
}
}
@ -113,7 +124,8 @@ async fn checkout_handler(
return (
axum::http::StatusCode::INTERNAL_SERVER_ERROR,
Json(json!(response)),
);
)
.into_response();
}
let legit_path = param.path.as_str();
@ -138,7 +150,8 @@ async fn checkout_handler(
return (
axum::http::StatusCode::INTERNAL_SERVER_ERROR,
Json(json!(response)),
);
)
.into_response();
}
};
@ -159,15 +172,45 @@ async fn checkout_handler(
return (
axum::http::StatusCode::INTERNAL_SERVER_ERROR,
Json(json!(response)),
);
)
.into_response();
}
};
if let Some(blob) = obj.as_blob() {
let content = unsafe { str::from_utf8_unchecked(blob.content()) };
response.insert("result".to_string(), json!(content.to_string()));
// image
if is_supported_image_file_type(fpath.clone()) {
let fc = fpath.clone();
let ext = fc.split(".").last().unwrap_or("");
let content: &[u8] = blob.content();
let img = match load_from_memory(content) {
Ok(img) => img,
Err(err) => {
//.map_err(|err| format!("Failed tp load image from memory: {err}"))
return (
axum::http::StatusCode::INTERNAL_SERVER_ERROR,
Json(json!(format!("Failed tp load image from memory: {err}"))),
)
.into_response();
}
};
return (axum::http::StatusCode::OK, Json(json!(content)));
let mut image_buffer = Vec::new();
img.write_to(
&mut Cursor::new(&mut image_buffer),
image::ImageFormat::from_extension(ext).unwrap_or(image::ImageFormat::Png),
)
.unwrap();
return Response::builder()
.header(header::CONTENT_TYPE, format!("image/{ext}"))
.body(Body::from(image_buffer))
.unwrap();
}
let content = unsafe { str::from_utf8_unchecked(blob.content()) };
return (axum::http::StatusCode::OK, Json(json!(content))).into_response();
// if let Ok(mut conn) = state.redis.get().await {
// let _ = conn.set(legit_path.to_string(), content.to_string()).await;
@ -180,7 +223,7 @@ async fn checkout_handler(
.collect::<Vec<String>>();
response.insert("result".to_string(), json!(dir_list));
return (axum::http::StatusCode::OK, Json(json!(dir_list)));
return (axum::http::StatusCode::OK, Json(json!(dir_list))).into_response();
// if let Ok(mut conn) = state.redis.get().await {
// let _ = conn.set(legit_path.to_string(), dir_list.join(",")).await;
@ -190,7 +233,7 @@ async fn checkout_handler(
let error_log = "not obj nor tree";
error!("{error_log}");
response.insert("error".to_string(), json!(error_log));
return (axum::http::StatusCode::BAD_REQUEST, Json(json!(response)));
return (axum::http::StatusCode::BAD_REQUEST, Json(json!(response))).into_response();
}
// println!("checkout response: {response:?}");