diff --git a/crates/lib/api_clients/runwayml_client/src/error/api_error.rs b/crates/lib/api_clients/runwayml_client/src/error/api_error.rs index 4c37d04c8e..c00de9249b 100644 --- a/crates/lib/api_clients/runwayml_client/src/error/api_error.rs +++ b/crates/lib/api_clients/runwayml_client/src/error/api_error.rs @@ -1,4 +1,5 @@ use jwt_light::error::JwtError; +use reqwest::StatusCode; use std::error::Error; use std::fmt::{Display, Formatter}; @@ -6,12 +7,25 @@ use std::fmt::{Display, Formatter}; pub enum ApiError { /// Inability to parse JWT. JwtError(JwtError), + + /// An error that occurred as or after the request was sent. + ReqwestError(reqwest::Error), + + /// Some other failure response. + UncategorizedBadResponse{ + status_code: StatusCode, + message : String, + } } impl Display for ApiError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { ApiError::JwtError(err) => write!(f, "JwtError: {}", err), + ApiError::ReqwestError(err) => write!(f, "ReqwestError: {}", err), + ApiError::UncategorizedBadResponse { status_code, message } => { + write!(f, "UncategorizedBadResponse: {:?} : {}", status_code, message) + } } } } diff --git a/crates/lib/api_clients/runwayml_client/src/error/classify_http_error_response.rs b/crates/lib/api_clients/runwayml_client/src/error/classify_http_error_response.rs new file mode 100644 index 0000000000..92fa7b002d --- /dev/null +++ b/crates/lib/api_clients/runwayml_client/src/error/classify_http_error_response.rs @@ -0,0 +1,17 @@ +use crate::error::api_error::ApiError; +use crate::error::runwayml_error::RunwayMlError; + +/// This assumes the request failed and returned a non-200. +/// The caller should check. +pub async fn classify_http_error_response(response: reqwest::Response) -> RunwayMlError { + let status = response.status(); + let message = match response.text().await { + Ok(text) => text, + Err(err) => return RunwayMlError::Api(ApiError::ReqwestError(err)), + }; + + // TODO: Handle various error messages from the API. + + //anyhow::anyhow!("Upload failed with status {}: {}", status, message)) + RunwayMlError::Api(ApiError::UncategorizedBadResponse { status_code: status, message }) +} diff --git a/crates/lib/api_clients/runwayml_client/src/error/client_error.rs b/crates/lib/api_clients/runwayml_client/src/error/client_error.rs index 37e905aeb7..0aa9ee6f36 100644 --- a/crates/lib/api_clients/runwayml_client/src/error/client_error.rs +++ b/crates/lib/api_clients/runwayml_client/src/error/client_error.rs @@ -4,13 +4,17 @@ use std::fmt::{Display, Formatter}; #[derive(Debug)] pub enum ClientError { /// No JWT bearer token in the credentials - NoJwtBearerToken + NoJwtBearerToken, + + /// An error that occurred clientside before the request was sent. + ReqwestError(reqwest::Error), } impl Display for ClientError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { ClientError::NoJwtBearerToken => write!(f, "No JWT bearer token in the credentials"), + ClientError::ReqwestError(err) => write!(f, "Reqwest error: {}", err), } } } diff --git a/crates/lib/api_clients/runwayml_client/src/error/mod.rs b/crates/lib/api_clients/runwayml_client/src/error/mod.rs index 971c344288..5adf827d77 100644 --- a/crates/lib/api_clients/runwayml_client/src/error/mod.rs +++ b/crates/lib/api_clients/runwayml_client/src/error/mod.rs @@ -1,3 +1,4 @@ -pub mod client_error; pub mod api_error; +pub mod classify_http_error_response; +pub mod client_error; pub mod runwayml_error; \ No newline at end of file diff --git a/crates/lib/api_clients/runwayml_client/src/requests/gen4_image_to_video.rs b/crates/lib/api_clients/runwayml_client/src/requests/gen4_image_to_video.rs index 38d33f2176..8df701f7fc 100644 --- a/crates/lib/api_clients/runwayml_client/src/requests/gen4_image_to_video.rs +++ b/crates/lib/api_clients/runwayml_client/src/requests/gen4_image_to_video.rs @@ -1,8 +1,10 @@ -use log::{debug, error}; -use reqwest::Client; use crate::creds::credentials::Credentials; +use crate::error::api_error::ApiError; +use crate::error::classify_http_error_response::classify_http_error_response; use crate::error::client_error::ClientError; use crate::error::runwayml_error::RunwayMlError; +use log::{debug, error}; +use reqwest::Client; const GENERATE_URL: &str = "https://api.runwayml.com/v1/tasks"; @@ -20,9 +22,13 @@ pub async fn gen4_image_to_video( let client = Client::builder() .gzip(true) - .build()?; + .build() + .map_err(|err| { + error!("Failed to create HTTP client: {}", err); + RunwayMlError::Client(ClientError::ReqwestError(err)) + })?; - let response = client.get(GENERATE_URL) + let response = client.post(GENERATE_URL) .header("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:137.0) Gecko/20100101 Firefox/137.0") .header("Accept", "application/json") .header("Accept-Encoding", "gzip, deflate, br") @@ -30,32 +36,37 @@ pub async fn gen4_image_to_video( .header("Content-Type", "application/json") .header("Authorization", jwt.to_authorization_header_value()) .send() - .await?; + .await + .map_err(|err| { + error!("Failed to send request: {}", err); + RunwayMlError::Api(ApiError::ReqwestError(err)) + })?; if !response.status().is_success() { - error!("Failed to generate bearer token: {}", response.status()); - let error = classify_general_http_error(response).await; + error!("Image to video request failed: {}", response.status()); + let error = classify_http_error_response(response).await; return Err(error); } - debug!("Bearer token generation response was 200."); + debug!("Enqueue returned a 200."); - let response_body = response.text().await?; + let response_body = response + .text() + .await + .map_err(|err| { + RunwayMlError::Api(ApiError::ReqwestError(err)) + })?; debug!("Auth Response: {}", response_body); - if &response_body == "null" { - error!("Failed to generate bearer token. Response was `null`."); - return Err(SoraError::FailedToGenerateBearer) - } + //if &response_body == "null" { + // error!("Failed to generate bearer token. Response was `null`."); + // return Err(SoraError::FailedToGenerateBearer) + //} let auth_response: SoraAuthResponse = serde_json::from_str(&response_body)?; Ok(auth_response.access_token) - - - - Ok(()) } #[cfg(test)] @@ -65,8 +76,6 @@ mod tests { #[tokio::test] #[ignore] async fn send_test_request() -> AnyhowResult<()> { - - Ok(()) } } \ No newline at end of file