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