feat(comfy-cloud): /view 产出文件透传
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -83,13 +83,39 @@ async fn get_history(
|
||||
Ok(Json(fetch_history(&state.db, &prompt_id).await?))
|
||||
}
|
||||
|
||||
async fn fetch_view(db: &sqlx::SqlitePool, query: Option<&str>) -> AppResult<(String, Vec<u8>)> {
|
||||
let (base_url, api_key) = resolve_comfy_cloud_site(db).await?;
|
||||
let q = query.unwrap_or("");
|
||||
let url = if q.is_empty() { format!("{base_url}/api/view") } else { format!("{base_url}/api/view?{q}") };
|
||||
let resp = client()
|
||||
.get(url)
|
||||
.header("X-API-Key", api_key)
|
||||
.send().await
|
||||
.map_err(|e| AppError::UpstreamError(e.to_string()))?;
|
||||
if !resp.status().is_success() {
|
||||
let st = resp.status();
|
||||
return Err(AppError::UpstreamError(format!("Comfy Cloud view [{st}]")));
|
||||
}
|
||||
let mime = resp
|
||||
.headers()
|
||||
.get(header::CONTENT_TYPE)
|
||||
.and_then(|v| v.to_str().ok())
|
||||
.unwrap_or("application/octet-stream")
|
||||
.to_string();
|
||||
let bytes = resp.bytes().await.map_err(|e| AppError::UpstreamError(e.to_string()))?.to_vec();
|
||||
Ok((mime, bytes))
|
||||
}
|
||||
|
||||
async fn get_view(
|
||||
State(state): State<AppState>,
|
||||
RawQuery(query): RawQuery,
|
||||
) -> AppResult<Response> {
|
||||
let _ = (&state, &query);
|
||||
Ok(Response::builder().status(StatusCode::NOT_IMPLEMENTED).body(Body::empty())
|
||||
.map_err(|e| AppError::Internal(anyhow::anyhow!(e)))?)
|
||||
let (mime, bytes) = fetch_view(&state.db, query.as_deref()).await?;
|
||||
Response::builder()
|
||||
.status(StatusCode::OK)
|
||||
.header(header::CONTENT_TYPE, mime)
|
||||
.body(Body::from(bytes))
|
||||
.map_err(|e| AppError::Internal(anyhow::anyhow!(e)))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -147,4 +173,21 @@ mod tests {
|
||||
assert_eq!(history["p1"]["status"]["completed"], true);
|
||||
assert_eq!(history["p1"]["outputs"]["9"]["images"][0]["filename"], "a.png");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn view_proxies_file_bytes() {
|
||||
let server = MockServer::start().await;
|
||||
Mock::given(method("GET"))
|
||||
.and(path("/api/view"))
|
||||
.and(match_header("X-API-Key", "key-123"))
|
||||
.respond_with(ResponseTemplate::new(200)
|
||||
.insert_header("content-type", "image/png")
|
||||
.set_body_bytes(b"PNGDATA".to_vec()))
|
||||
.mount(&server).await;
|
||||
|
||||
let pool = db_with_site(&server.uri()).await;
|
||||
let (mime, bytes) = fetch_view(&pool, Some("filename=a.png&type=output")).await.unwrap();
|
||||
assert_eq!(mime, "image/png");
|
||||
assert_eq!(bytes, b"PNGDATA");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user