复用原始图片编辑 HTTP 客户端
Project CI / Repository checks (pull_request) Failing after 12s
Project CI / Backend tests (pull_request) Failing after 13s
Project CI / Frontend tests (pull_request) Successful in 3m12s
Project CI / Native shell tests (pull_request) Failing after 4m20s

让 raw edit 接收 api-server 构造的 VectorEngine reqwest 客户端。

通过 request builder 保留有效请求超时,不修改现有连接池策略。

移除不再使用的客户端构造错误分支并同步技术方案。
This commit is contained in:
2026-09-12 16:33:33 +08:00
parent c7fe531b16
commit f05f6e49ab
3 changed files with 8 additions and 26 deletions
@@ -90,7 +90,7 @@ provider 响应只提取并透传 `data[].b64_json` 字符串,不在服务端
## 代码拆分
- `server-rs/crates/api-server/src/raw_image.rs`:独立路由 handler、multipart 字段解析、请求/响应 DTO、PNG 输入校验、预检查和 raw billing 编排。
- `server-rs/crates/platform-image/src/vector_engine/raw_edit.rs`:raw 编辑选项、严格尺寸校验、独立 provider 请求映射和 `b64_json` 响应透传;不复用现有 editor 图片编辑 client 或其 multipart transport
- `server-rs/crates/platform-image/src/vector_engine/raw_edit.rs`:raw 编辑选项、严格尺寸校验、独立 provider 请求映射和 `b64_json` 响应透传;由 api-server 按现有图片 API 传统构造并传入共享的 VectorEngine `reqwest::Client`,不在每个 raw 调用内部重复构造 client。每次请求仍用 `effective_request_timeout_ms` 通过 request builder 设置剩余 deadline;不修改统一 transport builder 的连接池策略
raw-edit 的图片输入使用独立的 `RawImageEditImage``bytes::Bytes`),由 reqwest `Part::stream(Body::from(Bytes))` 直接接管 multipart 请求体,避免整图和掩码在 `Part::bytes``Cow<[u8]>` 转换中再次复制。既有 `ReferenceImage``DownloadedImage` 及 curl/编辑器链路继续保持 `Vec<u8>` 契约,不因 raw-edit 引入全局字节类型迁移。
+4 -2
View File
@@ -22,8 +22,8 @@ use crate::{
auth::AuthenticatedAccessToken,
http_error::AppError,
openai_image_generation::{
map_platform_image_error, record_openai_image_failure_if_configured,
require_openai_image_settings,
build_openai_image_http_client, map_platform_image_error,
record_openai_image_failure_if_configured, require_openai_image_settings,
},
request_context::RequestContext,
state::{AppState, RAW_IMAGE_DECODE_MAX_CONCURRENCY},
@@ -119,6 +119,7 @@ pub(crate) async fn edit_raw_image(
None,
);
let provider_settings = settings.provider_settings();
let http_client = build_openai_image_http_client(&settings)?;
let user_id = authenticated.claims().user_id().to_string();
let request_id = request_context.request_id().to_string();
let points_cost = raw_image_edit_price(&state, prepared.width, prepared.height).await?;
@@ -136,6 +137,7 @@ pub(crate) async fn edit_raw_image(
let started_at_micros = (OffsetDateTime::now_utc().unix_timestamp_nanos() / 1_000) as i64;
let operation = async move {
let generated = match create_vector_engine_raw_image_edit(
&http_client,
&provider_settings,
prepared.prompt.as_str(),
prepared.image,
@@ -118,6 +118,7 @@ pub fn validate_raw_image_edit_dimensions(
/// Independent raw GPT Image 2 proxy; it does not call the editor image-edit client.
pub async fn create_vector_engine_raw_image_edit(
http_client: &reqwest::Client,
settings: &VectorEngineImageSettings,
prompt: &str,
image: RawImageEditImage,
@@ -181,13 +182,9 @@ pub async fn create_vector_engine_raw_image_edit(
);
}
let client = reqwest::Client::builder()
.timeout(Duration::from_millis(request_timeout_ms))
.http1_only()
.build()
.map_err(|error| invalid_config(failure_context, error.to_string()))?;
let response = client
let response = http_client
.post(url.as_str())
.timeout(Duration::from_millis(request_timeout_ms))
.bearer_auth(settings.api_key.as_str())
.multipart(form)
.send()
@@ -333,13 +330,6 @@ fn invalid_input(context: &str, message: String) -> PlatformImageError {
}
}
fn invalid_config(context: &str, message: String) -> PlatformImageError {
PlatformImageError::InvalidConfig {
provider: VECTOR_ENGINE_PROVIDER,
message: format!("{context}:构造请求客户端失败:{message}"),
}
}
fn request_error(
url: &str,
context: &str,
@@ -477,16 +467,6 @@ mod tests {
assert_eq!(error.to_string(), "raw_image_edit:请求参数无效:尺寸无效");
}
#[test]
fn invalid_config_error_keeps_operation_context() {
let error = invalid_config("raw_image_edit", "builder failed".to_string());
assert_eq!(
error.to_string(),
"raw_image_edit:构造请求客户端失败:builder failed"
);
}
#[test]
fn raw_edit_image_owns_shared_bytes_without_conversion() {
let bytes = bytes::Bytes::from_static(b"raw-image");