Proxy external template requests
This commit is contained in:
@@ -47,6 +47,8 @@ pub struct ProxyConfig {
|
|||||||
pub first_byte_timeout_secs: u64,
|
pub first_byte_timeout_secs: u64,
|
||||||
pub max_retries: u32,
|
pub max_retries: u32,
|
||||||
pub proxy_log_retention_days: u32,
|
pub proxy_log_retention_days: u32,
|
||||||
|
#[serde(default)]
|
||||||
|
pub template_proxy_url: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ pub mod proxy;
|
|||||||
pub mod routes;
|
pub mod routes;
|
||||||
pub mod services;
|
pub mod services;
|
||||||
pub mod shared;
|
pub mod shared;
|
||||||
|
pub mod template_http;
|
||||||
pub mod transformers;
|
pub mod transformers;
|
||||||
pub mod workflow;
|
pub mod workflow;
|
||||||
|
|
||||||
|
|||||||
@@ -409,6 +409,7 @@ mod tests {
|
|||||||
first_byte_timeout_secs: 30,
|
first_byte_timeout_secs: 30,
|
||||||
max_retries: 3,
|
max_retries: 3,
|
||||||
proxy_log_retention_days: 7,
|
proxy_log_retention_days: 7,
|
||||||
|
template_proxy_url: None,
|
||||||
},
|
},
|
||||||
comfyui: Default::default(),
|
comfyui: Default::default(),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -341,6 +341,7 @@ mod tests {
|
|||||||
first_byte_timeout_secs: 30,
|
first_byte_timeout_secs: 30,
|
||||||
max_retries: 3,
|
max_retries: 3,
|
||||||
proxy_log_retention_days: 7,
|
proxy_log_retention_days: 7,
|
||||||
|
template_proxy_url: None,
|
||||||
},
|
},
|
||||||
comfyui: Default::default(),
|
comfyui: Default::default(),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1235,6 +1235,7 @@ mod tests {
|
|||||||
first_byte_timeout_secs: 30,
|
first_byte_timeout_secs: 30,
|
||||||
max_retries: 3,
|
max_retries: 3,
|
||||||
proxy_log_retention_days: 7,
|
proxy_log_retention_days: 7,
|
||||||
|
template_proxy_url: None,
|
||||||
},
|
},
|
||||||
comfyui: Default::default(),
|
comfyui: Default::default(),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -345,7 +345,10 @@ async fn templates_handler(
|
|||||||
let _auth = resolve_picture_agent_auth(&headers, &state).await?;
|
let _auth = resolve_picture_agent_auth(&headers, &state).await?;
|
||||||
let limit = query.limit.unwrap_or(144).clamp(1, 240);
|
let limit = query.limit.unwrap_or(144).clamp(1, 240);
|
||||||
let mut templates = builtin_picture_templates(limit);
|
let mut templates = builtin_picture_templates(limit);
|
||||||
let remote_status = match fetch_remote_gallery_templates(limit.saturating_sub(templates.len()))
|
let remote_status = match fetch_remote_gallery_templates(
|
||||||
|
&state.config,
|
||||||
|
limit.saturating_sub(templates.len()),
|
||||||
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(mut remote_templates) => {
|
Ok(mut remote_templates) => {
|
||||||
@@ -368,11 +371,14 @@ async fn templates_handler(
|
|||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn fetch_remote_gallery_templates(limit: usize) -> Result<Vec<Value>, String> {
|
async fn fetch_remote_gallery_templates(
|
||||||
|
config: &crate::config::AppConfig,
|
||||||
|
limit: usize,
|
||||||
|
) -> Result<Vec<Value>, String> {
|
||||||
if limit == 0 {
|
if limit == 0 {
|
||||||
return Ok(Vec::new());
|
return Ok(Vec::new());
|
||||||
}
|
}
|
||||||
let items = template_client()
|
let items = crate::template_http::client(config, TEMPLATE_GALLERY_TIMEOUT_SECS)
|
||||||
.get(TEMPLATE_GALLERY_URL)
|
.get(TEMPLATE_GALLERY_URL)
|
||||||
.send()
|
.send()
|
||||||
.await
|
.await
|
||||||
@@ -499,13 +505,6 @@ fn builtin_picture_templates(limit: usize) -> Vec<Value> {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn template_client() -> Client {
|
|
||||||
Client::builder()
|
|
||||||
.timeout(Duration::from_secs(TEMPLATE_GALLERY_TIMEOUT_SECS))
|
|
||||||
.build()
|
|
||||||
.unwrap_or_else(|_| Client::new())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn picture_generation_client() -> Client {
|
fn picture_generation_client() -> Client {
|
||||||
picture_generation_client_with_timeout(PICTURE_GENERATION_TIMEOUT_SECS)
|
picture_generation_client_with_timeout(PICTURE_GENERATION_TIMEOUT_SECS)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1689,6 +1689,7 @@ mod tests {
|
|||||||
first_byte_timeout_secs: 30,
|
first_byte_timeout_secs: 30,
|
||||||
max_retries: 3,
|
max_retries: 3,
|
||||||
proxy_log_retention_days: 7,
|
proxy_log_retention_days: 7,
|
||||||
|
template_proxy_url: None,
|
||||||
},
|
},
|
||||||
comfyui: Default::default(),
|
comfyui: Default::default(),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1582,7 +1582,9 @@ async fn official_workflow_template_asset(
|
|||||||
} else {
|
} else {
|
||||||
format!("{}/{}", OFFICIAL_WORKFLOW_TEMPLATES_BASE, encoded_path)
|
format!("{}/{}", OFFICIAL_WORKFLOW_TEMPLATES_BASE, encoded_path)
|
||||||
};
|
};
|
||||||
let mut request = reqwest::Client::new().get(url);
|
let mut request =
|
||||||
|
crate::template_http::client(&state.config, state.config.proxy.upstream_timeout_secs)
|
||||||
|
.get(url);
|
||||||
if state.config.comfyui.uses_cloud_backend() {
|
if state.config.comfyui.uses_cloud_backend() {
|
||||||
if let Some(api_key) = state
|
if let Some(api_key) = state
|
||||||
.config
|
.config
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
use crate::config::AppConfig;
|
||||||
|
use reqwest::{Client, Proxy};
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
pub fn client(config: &AppConfig, timeout_secs: u64) -> Client {
|
||||||
|
let mut builder = Client::builder().timeout(Duration::from_secs(timeout_secs));
|
||||||
|
if let Some(proxy_url) = template_proxy_url(config) {
|
||||||
|
match Proxy::all(&proxy_url) {
|
||||||
|
Ok(proxy) => {
|
||||||
|
builder = builder.proxy(proxy);
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
tracing::warn!(%err, %proxy_url, "invalid template proxy url; falling back to direct template request");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder.build().unwrap_or_else(|_| Client::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn template_proxy_url(config: &AppConfig) -> Option<String> {
|
||||||
|
config
|
||||||
|
.proxy
|
||||||
|
.template_proxy_url
|
||||||
|
.as_deref()
|
||||||
|
.and_then(non_empty)
|
||||||
|
.map(str::to_string)
|
||||||
|
.or_else(|| std::env::var("BOOSAPI_TEMPLATE_PROXY_URL").ok().and_then(|value| non_empty_owned(value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn non_empty(value: &str) -> Option<&str> {
|
||||||
|
let value = value.trim();
|
||||||
|
(!value.is_empty()).then_some(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn non_empty_owned(value: String) -> Option<String> {
|
||||||
|
let value = value.trim().to_string();
|
||||||
|
(!value.is_empty()).then_some(value)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user