1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
use reqwest::Url;
pub mod history;
pub mod prompt;
pub mod upload;
pub mod view;
pub mod websocket;
pub use history::*;
pub use prompt::*;
pub use upload::*;
pub use view::*;
pub use websocket::*;
/// Errors that can occur opening API endpoints.
#[derive(thiserror::Error, Debug)]
#[non_exhaustive]
pub enum ApiError {
/// Error parsing endpoint URL
#[error("Failed to parse endpoint URL")]
ParseError(#[from] url::ParseError),
/// Error creating Prompt API
#[error("Failed create prompt API")]
CreatePromptApiFailed(#[from] PromptApiError),
/// Error creating History API
#[error("Failed create history API")]
CreateHistoryApiFailed(#[from] HistoryApiError),
/// Error creating Upload API
#[error("Failed create upload API")]
CreateUploadApiFailed(#[from] UploadApiError),
/// Error creating View API
#[error("Failed create view API")]
CreateViewApiFailed(#[from] ViewApiError),
/// Error parsing WebSocket endpoint API
#[error("Failed parse websocket endpoint URL")]
ParseWebSocketEndpointError(#[source] url::ParseError),
/// Error setting WebSocket scheme
#[error("Failed to set scheme: ws://{url}")]
SetWebSocketSchemeFailed { url: url::Url },
}
type Result<T> = std::result::Result<T, ApiError>;
/// Struct representing a connection to a ComfyUI API.
#[derive(Clone, Debug)]
pub struct Api {
client: reqwest::Client,
url: Url,
client_id: uuid::Uuid,
}
impl Default for Api {
fn default() -> Self {
Self::new().expect("Failed to parse default URL")
}
}
impl Api {
/// Returns a new `Api` instance with default settings.
pub fn new() -> Result<Self> {
Ok(Self {
client: reqwest::Client::new(),
url: Url::parse("http://localhost:8188")?,
client_id: uuid::Uuid::new_v4(),
})
}
/// Returns a new `Api` instance with the given URL as a string value.
///
/// # Arguments
///
/// * `url` - A string that specifies the ComfyUI API URL endpoint.
///
/// # Errors
///
/// If the URL fails to parse, an error will be returned.
pub fn new_with_url<S>(url: S) -> Result<Self>
where
S: AsRef<str>,
{
Ok(Self {
url: Url::parse(url.as_ref())?,
..Default::default()
})
}
/// Returns a new `Api` instance with the given `reqwest::Client` and URL as a string value.
///
/// # Arguments
///
/// * `client` - An instance of `reqwest::Client`.
/// * `url` - A string that specifies the ComfyUI API URL endpoint.
///
/// # Errors
///
/// If the URL fails to parse, an error will be returned.
pub fn new_with_client_and_url<S>(client: reqwest::Client, url: S) -> Result<Self>
where
S: AsRef<str>,
{
Ok(Self {
client,
url: Url::parse(url.as_ref())?,
..Default::default()
})
}
/// Returns a new instance of `PromptApi` with the API's cloned
/// `reqwest::Client` and the URL for the `prompt` endpoint.
///
/// # Errors
///
/// If the URL fails to parse, an error will be returned.
pub fn prompt(&self) -> Result<PromptApi> {
self.prompt_with_client(self.client_id)
}
/// Returns a new instance of `PromptApi` with the API's cloned
/// `reqwest::Client` and the URL for the `prompt` endpoint and the
/// specified client id.
///
/// # Arguments
///
/// * `client_id` - A `uuid::Uuid` representing the client id to use for the request.
///
/// # Errors
///
/// If the URL fails to parse, an error will be returned.
pub fn prompt_with_client(&self, client_id: uuid::Uuid) -> Result<PromptApi> {
Ok(PromptApi::new_with_url(
self.client.clone(),
self.url.join("prompt")?,
client_id,
))
}
/// Returns a new instance of `HistoryApi` with the API's cloned
/// `reqwest::Client` and the URL for the `history` endpoint.
///
/// # Errors
///
/// If the URL fails to parse, an error will be returned.
pub fn history(&self) -> Result<HistoryApi> {
Ok(HistoryApi::new_with_url(
self.client.clone(),
self.url.join("history/")?,
))
}
/// Returns a new instance of `UploadApi` with the API's cloned
/// `reqwest::Client` and the URL for the `view` endpoint.
///
/// # Errors
///
/// If the URL fails to parse, an error will be returned.
pub fn upload(&self) -> Result<UploadApi> {
Ok(UploadApi::new_with_url(
self.client.clone(),
self.url.join("upload/")?,
))
}
/// Returns a new instance of `ViewApi` with the API's cloned
/// `reqwest::Client` and the URL for the `view` endpoint.
///
/// # Errors
///
/// If the URL fails to parse, an error will be returned.
pub fn view(&self) -> Result<ViewApi> {
Ok(ViewApi::new_with_url(
self.client.clone(),
self.url.join("view")?,
))
}
/// Returns a new instance of `WebsocketApi` with the API's cloned
/// `reqwest::Client` and the URL for the `ws` endpoint.
///
/// # Errors
///
/// * If the URL fails to parse, an error will be returned.
/// * On failure to set the `ws://` scheme on the URL, an error will be returned.
pub fn websocket(&self) -> Result<WebsocketApi> {
self.websocket_with_client(self.client_id)
}
/// Returns a new instance of `WebsocketApi` with the API's cloned
/// `reqwest::Client` and the URL for the `ws` endpoint and the specified
/// client id.
///
/// # Arguments
///
/// * `client_id` - A `uuid::Uuid` representing the client id to use for the request.
///
/// # Errors
///
/// * If the URL fails to parse, an error will be returned.
/// * On failure to set the `ws://` scheme on the URL, an error will be returned.
pub fn websocket_with_client(&self, client_id: uuid::Uuid) -> Result<WebsocketApi> {
let mut url = self
.url
.clone()
.join("ws")
.map_err(ApiError::ParseWebSocketEndpointError)?;
url.set_scheme("ws")
.map_err(|_| ApiError::SetWebSocketSchemeFailed { url: url.clone() })?;
url.set_query(Some(format!("clientId={}", client_id).as_str()));
Ok(WebsocketApi::new_with_url(url))
}
}