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}