use aws_smithy_runtime_api::client::connector_metadata::ConnectorMetadata;
use aws_smithy_runtime_api::client::http::{
HttpClient, HttpConnector, HttpConnectorFuture, HttpConnectorSettings, SharedHttpConnector,
};
use aws_smithy_runtime_api::client::orchestrator::HttpRequest;
use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents;
use aws_smithy_runtime_api::shared::IntoShared;
use aws_smithy_types::body::SdkBody;
use std::fmt::Debug;
use std::sync::{Arc, Mutex};
use tokio::sync::oneshot;
#[derive(Debug)]
struct Inner {
response: Option<http_02x::Response<SdkBody>>,
sender: Option<oneshot::Sender<HttpRequest>>,
}
#[derive(Debug, Clone)]
pub struct CaptureRequestHandler(Arc<Mutex<Inner>>);
impl HttpConnector for CaptureRequestHandler {
fn call(&self, request: HttpRequest) -> HttpConnectorFuture {
let mut inner = self.0.lock().unwrap();
if let Err(_e) = inner.sender.take().expect("already sent").send(request) {
tracing::trace!("The receiver was already dropped");
}
HttpConnectorFuture::ready(Ok(inner
.response
.take()
.expect("could not handle second request")
.try_into()
.unwrap()))
}
}
impl HttpClient for CaptureRequestHandler {
fn http_connector(
&self,
_: &HttpConnectorSettings,
_: &RuntimeComponents,
) -> SharedHttpConnector {
self.clone().into_shared()
}
fn connector_metadata(&self) -> Option<ConnectorMetadata> {
Some(ConnectorMetadata::new("capture-request-handler", None))
}
}
#[derive(Debug)]
pub struct CaptureRequestReceiver {
receiver: oneshot::Receiver<HttpRequest>,
}
impl CaptureRequestReceiver {
#[track_caller]
pub fn expect_request(mut self) -> HttpRequest {
self.receiver.try_recv().expect("no request was received")
}
#[track_caller]
pub fn expect_no_request(mut self) {
self.receiver
.try_recv()
.expect_err("expected no request to be received!");
}
}
pub fn capture_request(
response: Option<http_02x::Response<SdkBody>>,
) -> (CaptureRequestHandler, CaptureRequestReceiver) {
let (tx, rx) = oneshot::channel();
(
CaptureRequestHandler(Arc::new(Mutex::new(Inner {
response: Some(response.unwrap_or_else(|| {
http_02x::Response::builder()
.status(200)
.body(SdkBody::empty())
.expect("unreachable")
})),
sender: Some(tx),
}))),
CaptureRequestReceiver { receiver: rx },
)
}