HttpError

Enum HttpError 

Source
pub enum HttpError {
    ClientCreation {
        reason: String,
    },
    RequestFailed {
        url: String,
        reason: String,
    },
    Timeout {
        url: String,
        seconds: u64,
    },
    RateLimited {
        retry_after_seconds: u64,
    },
    InvalidResponse {
        expected: String,
        actual: String,
    },
}
Expand description

HTTP-related errors with detailed context for network operations.

This enum provides comprehensive error classification for HTTP operations throughout the application, including Azure API calls, authentication requests, and other network operations. Each error variant includes relevant context to aid in debugging and error handling.

§Error Categories

§Client Configuration Errors

§Request Execution Errors

§Rate Limiting and Service Errors

  • RateLimited - Rate limiting with retry timing information

§Examples

§Basic Error Handling

use quetty_server::common::errors::HttpError;

async fn handle_http_error(error: HttpError) {
    match error {
        HttpError::Timeout { url, seconds } => {
            eprintln!("Request to {} timed out after {}s", url, seconds);
            // Implement retry with longer timeout
        }
        HttpError::RateLimited { retry_after_seconds } => {
            println!("Rate limited. Retrying after {}s", retry_after_seconds);
            // Wait and retry
        }
        HttpError::RequestFailed { url, reason } => {
            eprintln!("Request to {} failed: {}", url, reason);
            // Log and handle specific failure
        }
        HttpError::ClientCreation { reason } => {
            eprintln!("Failed to create HTTP client: {}", reason);
            // Reinitialize client with different configuration
        }
        HttpError::InvalidResponse { expected, actual } => {
            eprintln!("Invalid response: expected {}, got {}", expected, actual);
            // Handle unexpected response format
        }
    }
}

§Retry Logic Implementation

use quetty_server::common::errors::HttpError;
use std::time::Duration;
use tokio::time::sleep;

async fn http_request_with_retry<T>(
    request_fn: impl Fn() -> Result<T, HttpError>
) -> Result<T, HttpError> {
    let mut attempts = 0;
    let max_attempts = 3;

    loop {
        attempts += 1;

        match request_fn() {
            Ok(result) => return Ok(result),
            Err(HttpError::RateLimited { retry_after_seconds }) => {
                if attempts < max_attempts {
                    sleep(Duration::from_secs(retry_after_seconds)).await;
                    continue;
                }
                return Err(HttpError::RateLimited { retry_after_seconds });
            }
            Err(HttpError::Timeout { url, seconds }) => {
                if attempts < max_attempts {
                    // Exponential backoff for timeouts
                    sleep(Duration::from_secs(2_u64.pow(attempts))).await;
                    continue;
                }
                return Err(HttpError::Timeout { url, seconds });
            }
            Err(other) => return Err(other), // Don't retry client errors
        }
    }
}

§Azure API Error Handling

use quetty_server::common::errors::HttpError;

async fn call_azure_api(endpoint: &str) -> Result<String, HttpError> {
    // Simulated Azure API call
    match make_request(endpoint).await {
        Ok(response) => Ok(response),
        Err(e) => {
            // Convert to structured HttpError
            Err(HttpError::RequestFailed {
                url: endpoint.to_string(),
                reason: e.to_string(),
            })
        }
    }
}

// Usage with error context
let result = call_azure_api("https://management.azure.com/subscriptions").await;
match result {
    Ok(data) => println!("API call successful: {}", data),
    Err(HttpError::RequestFailed { url, reason }) => {
        if reason.contains("401") {
            // Handle authentication error
            println!("Authentication required for {}", url);
        } else if reason.contains("404") {
            // Handle resource not found
            println!("Resource not found: {}", url);
        } else {
            // Handle other errors
            println!("Request failed: {} - {}", url, reason);
        }
    }
    Err(other) => {
        println!("HTTP error: {}", other);
    }
}

§Integration Patterns

§Error Conversion

This error type is designed to be easily converted to higher-level error types:

use quetty_server::common::errors::HttpError;
use quetty_server::service_bus_manager::ServiceBusError;

impl From<HttpError> for ServiceBusError {
    fn from(http_error: HttpError) -> Self {
        match http_error {
            HttpError::Timeout { .. } => ServiceBusError::OperationTimeout(http_error.to_string()),
            HttpError::RateLimited { .. } => ServiceBusError::OperationTimeout(http_error.to_string()),
            _ => ServiceBusError::ConnectionFailed(http_error.to_string()),
        }
    }
}

§Logging Integration

use quetty_server::common::errors::HttpError;

fn log_http_error(error: &HttpError) {
    match error {
        HttpError::RequestFailed { url, reason } => {
            log::error!("HTTP request failed: url={}, reason={}", url, reason);
        }
        HttpError::Timeout { url, seconds } => {
            log::warn!("HTTP request timeout: url={}, duration={}s", url, seconds);
        }
        HttpError::RateLimited { retry_after_seconds } => {
            log::info!("HTTP rate limited: retry_after={}s", retry_after_seconds);
        }
        _ => {
            log::error!("HTTP error: {}", error);
        }
    }
}

Variants§

§

ClientCreation

HTTP client initialization failed.

This error occurs when creating or configuring the HTTP client fails, typically due to invalid configuration, SSL/TLS setup issues, or system resource constraints.

§Fields

  • reason: Detailed description of the client creation failure

§Recovery

  • Validate HTTP client configuration
  • Check system resources and network settings
  • Retry with alternative client configuration

Fields

§reason: String
§

RequestFailed

HTTP request execution failed.

This is a general request failure that can occur due to various reasons including network issues, server errors, authentication problems, or malformed requests.

§Fields

  • url: The URL that was being requested
  • reason: Detailed description of the failure

§Recovery

  • Check network connectivity
  • Validate request parameters and authentication
  • Implement retry logic for transient failures

Fields

§reason: String
§

Timeout

HTTP request timed out.

This error occurs when a request takes longer than the configured timeout duration. This can happen due to slow network conditions, overloaded servers, or network connectivity issues.

§Fields

  • url: The URL that timed out
  • seconds: The timeout duration that was exceeded

§Recovery

  • Retry with longer timeout
  • Check network connectivity
  • Consider alternative endpoints if available

Fields

§seconds: u64
§

RateLimited

Rate limiting is active for HTTP requests.

This error occurs when the server has rate-limited the client due to too many requests in a short period. The server provides guidance on when to retry.

§Fields

  • retry_after_seconds: Duration to wait before retrying

§Recovery

  • Wait for the specified duration before retrying
  • Implement request throttling to prevent future rate limiting
  • Consider using exponential backoff for subsequent requests

Fields

§retry_after_seconds: u64
§

InvalidResponse

Received response doesn’t match expected format.

This error occurs when the server returns a response that doesn’t match the expected format, content type, or structure. This can indicate API changes, server errors, or client-side parsing issues.

§Fields

  • expected: Description of what was expected
  • actual: Description of what was actually received

§Recovery

  • Validate API endpoint and version compatibility
  • Check response parsing logic
  • Consider graceful degradation for unexpected responses

Fields

§expected: String
§actual: String

Trait Implementations§

Source§

impl Debug for HttpError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for HttpError

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Error for HttpError

1.30.0 · Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl From<HttpError> for ServiceBusError

Source§

fn from(err: HttpError) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T> ToStringFallible for T
where T: Display,

Source§

fn try_to_string(&self) -> Result<String, TryReserveError>

ToString::to_string, but without panic on OOM.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> SendBound for T
where T: Send,