nyquest_interface/async/
backend.rs

1//! Core async client interface traits.
2//!
3//! This module provides the core trait definitions that backend implementations
4//! must implement to provide asynchronous HTTP functionality.
5//!
6//! Backend developers need to implement the `AsyncBackend` and `AsyncClient` traits,
7//! along with a custom `AsyncResponse` type.
8
9use std::fmt;
10use std::future::Future;
11use std::pin::Pin;
12
13use super::Request as AsyncRequest;
14use crate::client::ClientOptions;
15use crate::Result;
16
17/// Trait for asynchronous HTTP clients.
18///
19/// Backend implementations must provide a concrete type that implements this trait
20/// to handle asynchronous HTTP requests.
21pub trait AsyncClient: Clone + Send + Sync + 'static {
22    /// The type of response returned by this client.
23    type Response: AsyncResponse + Send;
24
25    /// Provides a textual description of this client.
26    fn describe(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27        write!(f, "AsyncClient")
28    }
29
30    /// Sends an HTTP request and returns a future that resolves to the response.
31    fn request(&self, req: AsyncRequest) -> impl Future<Output = Result<Self::Response>> + Send;
32    // TODO: fn request_with_progress
33    // TODO: fn request_file
34}
35
36/// Trait for asynchronous HTTP backend implementations.
37///
38/// This trait represents a backend implementation that can create async HTTP clients.
39pub trait AsyncBackend: Send + Sync + 'static {
40    /// The type of client this backend creates.
41    type AsyncClient: AsyncClient;
42
43    /// Creates a new async client with the given options.
44    fn create_async_client(
45        &self,
46        options: ClientOptions,
47    ) -> impl Future<Output = Result<Self::AsyncClient>> + Send;
48}
49
50/// Trait for asynchronous HTTP responses.
51///
52/// This trait provides methods for accessing the data in an HTTP response.
53///
54/// ## Response Method Receivers
55///
56/// Note that the `AsyncResponse` trait uses `&mut self` receivers for content reading methods
57/// (`text()`, `bytes()`, etc.) to ensure object safety and dyn compatibility.
58/// This differs from the main nyquest crate which uses consuming `self` receivers.
59///
60/// Backend implementors should design their implementations with the understanding that
61/// these methods may be called only once per response instance, even though the signature allows
62/// multiple calls. The nyquest facade enforces this by consuming the response.
63pub trait AsyncResponse: futures_io::AsyncRead + Send + Sync + 'static {
64    /// Provides a textual description of this response.
65    fn describe(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66        write!(f, "AsyncResponse")
67    }
68
69    /// Returns the HTTP status code of this response.
70    fn status(&self) -> u16;
71
72    /// Returns the content-length of the response body, if known.
73    fn content_length(&self) -> Option<u64>;
74
75    /// Gets all values for the specified header.
76    fn get_header(&self, header: &str) -> Result<Vec<String>>;
77
78    /// Reads the response body as text.
79    fn text(self: Pin<&mut Self>) -> impl Future<Output = Result<String>> + Send;
80
81    /// Reads the response body as bytes.
82    fn bytes(self: Pin<&mut Self>) -> impl Future<Output = Result<Vec<u8>>> + Send;
83}