Skip to content

Commit 81772e7

Browse files
committed
feat(api): 添加根据请求头解析图片基础URL功能
- 在 `upload` 和 `list` 函数中,增加了对 `HeaderMap` 的接收,并调用 `resolve_image_base_url` 函数来解析图片的基础URL。 - 添加了 `resolve_image_base_url` 函数,该函数根据请求头中的 `HOST` 字段解析图片的基础URL,若请求头中没有 `HOST` 字段,则使用配置中的 `cdn_base_url`。 - 修改了 `ImageService::upload` 和 `ImageService::list` 函数的调用,增加了 `base_url` 参数,以便在生成 `ImageInfo` 时使用解析后的基础URL。
1 parent 9e07e79 commit 81772e7

2 files changed

Lines changed: 26 additions & 3 deletions

File tree

crates/api/src/images.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,11 @@ pub fn public_routes() -> Router<AppState> {
3434
async fn upload(
3535
State(state): State<AppState>,
3636
auth: AuthUser,
37+
headers: HeaderMap,
3738
mut multipart: Multipart,
3839
) -> Result<ApiResponse<ImageInfo>, AppError> {
40+
let base_url = resolve_image_base_url(&headers, &state.config.image.cdn_base_url);
41+
3942
let mut file_name = None;
4043
let mut content_type = None;
4144
let mut data = None;
@@ -71,6 +74,7 @@ async fn upload(
7174
&content_type,
7275
data,
7376
&state.config.image,
77+
&base_url,
7478
)
7579
.await?;
7680

@@ -86,12 +90,14 @@ struct ListQuery {
8690
async fn list(
8791
State(state): State<AppState>,
8892
auth: AuthUser,
93+
headers: HeaderMap,
8994
Query(query): Query<ListQuery>,
9095
) -> Result<ApiResponse<Vec<ImageInfo>>, AppError> {
96+
let base_url = resolve_image_base_url(&headers, &state.config.image.cdn_base_url);
9197
let page = query.page.unwrap_or(1);
9298
let per_page = query.per_page.unwrap_or(20);
9399
let (items, total) =
94-
ImageService::list(&state.db, auth.user_id, &state.config.image.cdn_base_url, page, per_page)
100+
ImageService::list(&state.db, auth.user_id, &base_url, page, per_page)
95101
.await?;
96102
Ok(ApiResponse::paginated(items, page, per_page, total))
97103
}
@@ -161,6 +167,22 @@ async fn serve_thumb(
161167
Ok((StatusCode::OK, headers, data))
162168
}
163169

170+
fn resolve_image_base_url(headers: &HeaderMap, cdn_base_url: &str) -> String {
171+
if !cdn_base_url.is_empty() {
172+
return cdn_base_url.to_string();
173+
}
174+
if let Some(host) = headers.get(header::HOST).and_then(|v| v.to_str().ok()) {
175+
let scheme = if host.starts_with("localhost") || host.starts_with("127.0.0.1") {
176+
"http"
177+
} else {
178+
"https"
179+
};
180+
format!("{scheme}://{host}/img")
181+
} else {
182+
String::new()
183+
}
184+
}
185+
164186
fn check_referer(headers: &HeaderMap, allowed: &[String]) -> Result<(), AppError> {
165187
if allowed.is_empty() {
166188
return Ok(());

crates/core/src/image.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ impl ImageService {
7373
content_type: &str,
7474
data: Vec<u8>,
7575
config: &ImageConfig,
76+
base_url: &str,
7677
) -> Result<ImageInfo, AppError> {
7778
// 1. Validate format
7879
if !ALLOWED_TYPES.contains(&content_type) {
@@ -100,7 +101,7 @@ impl ImageService {
100101
.await?;
101102

102103
if let Some(existing) = existing {
103-
return Ok(ImageInfo::from_model(existing, &config.cdn_base_url));
104+
return Ok(ImageInfo::from_model(existing, base_url));
104105
}
105106

106107
// 5. Decode image
@@ -169,7 +170,7 @@ impl ImageService {
169170
};
170171

171172
let model = record.insert(db).await?;
172-
Ok(ImageInfo::from_model(model, &config.cdn_base_url))
173+
Ok(ImageInfo::from_model(model, base_url))
173174
}
174175

175176
pub async fn list(

0 commit comments

Comments
 (0)