aws_smithy_http_client/test_util/
capture_request.rs1use aws_smithy_runtime_api::client::connector_metadata::ConnectorMetadata;
7use aws_smithy_runtime_api::client::http::{
8 HttpClient, HttpConnector, HttpConnectorFuture, HttpConnectorSettings, SharedHttpConnector,
9};
10use aws_smithy_runtime_api::client::orchestrator::{HttpRequest, HttpResponse};
11use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents;
12use aws_smithy_runtime_api::http::HttpError;
13use aws_smithy_runtime_api::shared::IntoShared;
14use aws_smithy_types::body::SdkBody;
15use std::fmt::Debug;
16use std::sync::{Arc, Mutex};
17use tokio::sync::oneshot;
18
19#[derive(Debug)]
20struct Inner {
21 response: Option<HttpResponse>,
22 sender: Option<oneshot::Sender<HttpRequest>>,
23}
24
25#[derive(Debug, Clone)]
27pub struct CaptureRequestHandler(Arc<Mutex<Inner>>);
28
29impl HttpConnector for CaptureRequestHandler {
30 fn call(&self, request: HttpRequest) -> HttpConnectorFuture {
31 let mut inner = self.0.lock().unwrap();
32 if let Err(_e) = inner.sender.take().expect("already sent").send(request) {
33 tracing::trace!("The receiver was already dropped");
34 }
35 HttpConnectorFuture::ready(Ok(inner
36 .response
37 .take()
38 .expect("could not handle second request")))
39 }
40}
41
42impl HttpClient for CaptureRequestHandler {
43 fn http_connector(
44 &self,
45 _: &HttpConnectorSettings,
46 _: &RuntimeComponents,
47 ) -> SharedHttpConnector {
48 self.clone().into_shared()
49 }
50
51 fn connector_metadata(&self) -> Option<ConnectorMetadata> {
52 Some(ConnectorMetadata::new("capture-request-handler", None))
53 }
54}
55
56#[derive(Debug)]
58pub struct CaptureRequestReceiver {
59 receiver: oneshot::Receiver<HttpRequest>,
60}
61
62impl CaptureRequestReceiver {
63 #[track_caller]
68 pub fn expect_request(mut self) -> HttpRequest {
69 self.receiver.try_recv().expect("no request was received")
70 }
71
72 #[track_caller]
77 pub fn expect_no_request(mut self) {
78 self.receiver
79 .try_recv()
80 .expect_err("expected no request to be received!");
81 }
82}
83
84pub fn capture_request(
103 response: Option<http_1x::Response<SdkBody>>,
104) -> (CaptureRequestHandler, CaptureRequestReceiver) {
105 capture_request_inner(response)
106}
107
108fn capture_request_inner(
109 response: Option<impl TryInto<HttpResponse, Error = HttpError>>,
110) -> (CaptureRequestHandler, CaptureRequestReceiver) {
111 let (tx, rx) = oneshot::channel();
112 let http_resp: HttpResponse = match response {
113 Some(resp) => resp.try_into().expect("valid HttpResponse"),
114 None => http_1x::Response::builder()
115 .status(200)
116 .body(SdkBody::empty())
117 .expect("unreachable")
118 .try_into()
119 .expect("unreachable"),
120 };
121 (
122 CaptureRequestHandler(Arc::new(Mutex::new(Inner {
123 response: Some(http_resp),
124 sender: Some(tx),
125 }))),
126 CaptureRequestReceiver { receiver: rx },
127 )
128}
129
130#[allow(missing_docs)]
131#[cfg(feature = "legacy-test-util")]
132pub fn legacy_capture_request(
133 response: Option<http_02x::Response<SdkBody>>,
134) -> (CaptureRequestHandler, CaptureRequestReceiver) {
135 capture_request_inner(response)
136}
137
138#[cfg(test)]
139mod test {
140 use aws_smithy_runtime_api::client::http::HttpConnector;
141 use aws_smithy_runtime_api::client::orchestrator::HttpRequest;
142 use aws_smithy_types::body::SdkBody;
143
144 #[cfg(feature = "legacy-test-util")]
145 #[tokio::test]
146 async fn test_can_plug_in_http_02x() {
147 use super::legacy_capture_request;
148 let (capture_client, _request) = legacy_capture_request(Some(
149 http_02x::Response::builder()
150 .status(202)
151 .body(SdkBody::empty())
152 .expect("unreachable"),
153 ));
154
155 let resp = capture_client.call(HttpRequest::empty()).await.unwrap();
156 assert_eq!(202, resp.status().as_u16());
157 }
158
159 #[tokio::test]
160 async fn test_can_plug_in_http_1x() {
161 use super::capture_request;
162 let (capture_client, _request) = capture_request(Some(
163 http_1x::Response::builder()
164 .status(202)
165 .body(SdkBody::empty())
166 .expect("unreachable"),
167 ));
168
169 let resp = capture_client.call(HttpRequest::empty()).await.unwrap();
170 assert_eq!(202, resp.status().as_u16());
171 }
172}