1 1 | // Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
|
2 2 | ::pin_project_lite::pin_project! {
|
3 3 | /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the
|
4 - | /// [`QueryIncompatibleOperationInput`](crate::input::QueryIncompatibleOperationInput) using modelled bindings.
|
5 - | pub struct QueryIncompatibleOperationInputFuture {
|
6 - | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::QueryIncompatibleOperationInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
4 + | /// [`NoInputAndNoOutputInput`](crate::input::NoInputAndNoOutputInput) using modelled bindings.
|
5 + | pub struct NoInputAndNoOutputInputFuture {
|
6 + | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::NoInputAndNoOutputInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
7 7 | }
|
8 8 | }
|
9 9 |
|
10 - | impl std::future::Future for QueryIncompatibleOperationInputFuture {
|
10 + | impl std::future::Future for NoInputAndNoOutputInputFuture {
|
11 11 | type Output = Result<
|
12 - | crate::input::QueryIncompatibleOperationInput,
|
12 + | crate::input::NoInputAndNoOutputInput,
|
13 13 | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError,
|
14 14 | >;
|
15 15 |
|
16 16 | fn poll(
|
17 17 | self: std::pin::Pin<&mut Self>,
|
18 18 | cx: &mut std::task::Context<'_>,
|
19 19 | ) -> std::task::Poll<Self::Output> {
|
20 20 | let this = self.project();
|
21 21 | this.inner.as_mut().poll(cx)
|
22 22 | }
|
23 23 | }
|
24 24 |
|
25 25 | impl<B>
|
26 26 | ::aws_smithy_http_server::request::FromRequest<
|
27 27 | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
28 28 | B,
|
29 - | > for crate::input::QueryIncompatibleOperationInput
|
29 + | > for crate::input::NoInputAndNoOutputInput
|
30 30 | where
|
31 31 | B: ::aws_smithy_http_server::body::HttpBody + Send,
|
32 32 | B: 'static,
|
33 33 |
|
34 34 | B::Data: Send,
|
35 35 | ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection:
|
36 36 | From<<B as ::aws_smithy_http_server::body::HttpBody>::Error>,
|
37 37 | {
|
38 38 | type Rejection = ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError;
|
39 - | type Future = QueryIncompatibleOperationInputFuture;
|
39 + | type Future = NoInputAndNoOutputInputFuture;
|
40 40 |
|
41 41 | fn from_request(request: ::http_1x::Request<B>) -> Self::Future {
|
42 42 | let fut = async move {
|
43 43 | if !::aws_smithy_http_server::protocol::accept_header_classifier(
|
44 44 | request.headers(),
|
45 45 | &crate::mimes::CONTENT_TYPE_APPLICATION_X_AMZ_JSON_1_0,
|
46 46 | ) {
|
47 47 | return Err(::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection::NotAcceptable);
|
48 48 | }
|
49 - | crate::protocol_serde::shape_query_incompatible_operation::de_query_incompatible_operation_http_request(request)
|
49 + | crate::protocol_serde::shape_no_input_and_no_output::de_no_input_and_no_output_http_request(request)
|
50 50 | .await
|
51 51 | };
|
52 52 | use ::futures_util::future::TryFutureExt;
|
53 53 | let fut = fut.map_err(
|
54 54 | |e: ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection| {
|
55 55 | ::tracing::debug!(error = %e, "failed to deserialize request");
|
56 56 | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e)
|
57 57 | },
|
58 58 | );
|
59 - | QueryIncompatibleOperationInputFuture {
|
59 + | NoInputAndNoOutputInputFuture {
|
60 60 | inner: Box::pin(fut),
|
61 61 | }
|
62 62 | }
|
63 63 | }
|
64 64 | impl
|
65 65 | ::aws_smithy_http_server::response::IntoResponse<
|
66 66 | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
67 - | > for crate::output::QueryIncompatibleOperationOutput
|
67 + | > for crate::output::NoInputAndNoOutputOutput
|
68 68 | {
|
69 69 | fn into_response(self) -> ::aws_smithy_http_server::response::Response {
|
70 - | match crate::protocol_serde::shape_query_incompatible_operation::ser_query_incompatible_operation_http_response(self) {
|
70 + | match crate::protocol_serde::shape_no_input_and_no_output::ser_no_input_and_no_output_http_response(self) {
|
71 71 | Ok(response) => response,
|
72 72 | Err(e) => {
|
73 73 | ::tracing::error!(error = %e, "failed to serialize response");
|
74 74 | ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0>::into_response(::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e))
|
75 75 | }
|
76 76 | }
|
77 77 | }
|
78 78 | }
|
79 79 |
|
80 80 | #[allow(unreachable_code, unused_variables)]
|
81 81 | #[cfg(test)]
|
82 - | mod query_incompatible_operation_test {
|
82 + | mod no_input_and_no_output_test {
|
83 83 |
|
84 - | /// The query mode header MUST NOT be set on non-query-compatible services.
|
85 - | /// Test ID: NonQueryCompatibleAwsJson10ForbidsQueryModeHeader
|
84 + | /// Clients must always send an empty JSON object payload for
|
85 + | /// operations with no input (that is, `{}`). While AWS service
|
86 + | /// implementations support requests with no payload or requests
|
87 + | /// that send `{}`, always sending `{}` from the client is
|
88 + | /// preferred for forward compatibility in case input is ever
|
89 + | /// added to an operation.
|
90 + | /// Test ID: AwsJson10MustAlwaysSendEmptyJsonPayload
|
86 91 | #[::tokio::test]
|
87 92 | #[::tracing_test::traced_test]
|
88 - | async fn non_query_compatible_aws_json10_forbids_query_mode_header_request() {
|
93 + | async fn aws_json10_must_always_send_empty_json_payload_request() {
|
89 94 | #[allow(unused_mut)]
|
90 95 | let mut http_request = ::http_1x::Request::builder()
|
91 96 | .uri("/")
|
92 97 | .method("POST")
|
93 98 | .header("Content-Type", "application/x-amz-json-1.0")
|
94 - | .header("X-Amz-Target", "JsonRpc10.QueryIncompatibleOperation")
|
99 + | .header("X-Amz-Target", "JsonRpc10.NoInputAndNoOutput")
|
95 100 | .body(::aws_smithy_http_server::body::boxed(
|
96 101 | ::http_body_util::Full::new(::bytes::Bytes::copy_from_slice(
|
97 102 | &::aws_smithy_protocol_test::decode_body_data(
|
98 103 | "{}".as_bytes(),
|
99 104 | ::aws_smithy_protocol_test::MediaType::from("application/json"),
|
100 105 | ),
|
101 106 | )),
|
102 107 | ))
|
103 108 | .unwrap();
|
104 109 | #[allow(unused_mut)]
|
105 110 | let (sender, mut receiver) = ::tokio::sync::mpsc::channel(1);
|
106 111 | let config = crate::service::JsonRpc10Config::builder().build();
|
107 112 | let service =
|
108 113 | crate::service::JsonRpc10::builder::<::aws_smithy_http_server::body::BoxBody, _, _, _>(
|
109 114 | config,
|
110 115 | )
|
111 - | .query_incompatible_operation(
|
112 - | move |input: crate::input::QueryIncompatibleOperationInput| {
|
116 + | .no_input_and_no_output(move |input: crate::input::NoInputAndNoOutputInput| {
|
113 117 | let sender = sender.clone();
|
114 118 | async move {
|
115 119 | let result = {
|
116 - | let expected = crate::input::QueryIncompatibleOperationInput {};
|
120 + | let expected = crate::input::NoInputAndNoOutputInput {};
|
117 121 | ::pretty_assertions::assert_eq!(input, expected);
|
118 - | let output = crate::output::QueryIncompatibleOperationOutput {};
|
122 + | let output = crate::output::NoInputAndNoOutputOutput {};
|
119 123 | output
|
120 124 | };
|
121 125 | sender.send(()).await.expect("receiver dropped early");
|
122 126 | result
|
123 127 | }
|
124 - | },
|
128 + | })
|
129 + | .build_unchecked();
|
130 + | let http_response = ::tower::ServiceExt::oneshot(service, http_request)
|
131 + | .await
|
132 + | .expect("unable to make an HTTP request");
|
133 + | assert!(
|
134 + | receiver.recv().await.is_some(),
|
135 + | "we expected operation handler to be invoked but it was not entered"
|
136 + | );
|
137 + | }
|
138 + |
|
139 + | /// Service implementations must support no payload or an empty
|
140 + | /// object payload for operations that define no input. However,
|
141 + | /// despite the lack of a payload, a Content-Type header is still
|
142 + | /// required in order for the service to properly detect the
|
143 + | /// protocol.
|
144 + | /// Test ID: AwsJson10ServiceSupportsNoPayloadForNoInput
|
145 + | #[::tokio::test]
|
146 + | #[::tracing_test::traced_test]
|
147 + | async fn aws_json10_service_supports_no_payload_for_no_input_request() {
|
148 + | #[allow(unused_mut)]
|
149 + | let mut http_request = ::http_1x::Request::builder()
|
150 + | .uri("/")
|
151 + | .method("POST")
|
152 + | .header("Content-Type", "application/x-amz-json-1.0")
|
153 + | .header("X-Amz-Target", "JsonRpc10.NoInputAndNoOutput")
|
154 + | .body(::aws_smithy_http_server::body::boxed(
|
155 + | ::http_body_util::Full::new(::bytes::Bytes::copy_from_slice(
|
156 + | &::aws_smithy_protocol_test::decode_body_data(
|
157 + | "".as_bytes(),
|
158 + | ::aws_smithy_protocol_test::MediaType::from("unknown"),
|
159 + | ),
|
160 + | )),
|
161 + | ))
|
162 + | .unwrap();
|
163 + | #[allow(unused_mut)]
|
164 + | let (sender, mut receiver) = ::tokio::sync::mpsc::channel(1);
|
165 + | let config = crate::service::JsonRpc10Config::builder().build();
|
166 + | let service =
|
167 + | crate::service::JsonRpc10::builder::<::aws_smithy_http_server::body::BoxBody, _, _, _>(
|
168 + | config,
|
125 169 | )
|
170 + | .no_input_and_no_output(move |input: crate::input::NoInputAndNoOutputInput| {
|
171 + | let sender = sender.clone();
|
172 + | async move {
|
173 + | let result = {
|
174 + | let expected = crate::input::NoInputAndNoOutputInput {};
|
175 + | ::pretty_assertions::assert_eq!(input, expected);
|
176 + | let output = crate::output::NoInputAndNoOutputOutput {};
|
177 + | output
|
178 + | };
|
179 + | sender.send(()).await.expect("receiver dropped early");
|
180 + | result
|
181 + | }
|
182 + | })
|
126 183 | .build_unchecked();
|
127 184 | let http_response = ::tower::ServiceExt::oneshot(service, http_request)
|
128 185 | .await
|
129 186 | .expect("unable to make an HTTP request");
|
130 187 | assert!(
|
131 188 | receiver.recv().await.is_some(),
|
132 189 | "we expected operation handler to be invoked but it was not entered"
|
133 190 | );
|
134 191 | }
|
192 + |
|
193 + | /// When no output is defined, the service is expected to return
|
194 + | /// an empty payload. Despite the lack of a payload, the service
|
195 + | /// is expected to always send a Content-Type header. Clients must
|
196 + | /// handle cases where a service returns a JSON object and where
|
197 + | /// a service returns no JSON at all.
|
198 + | /// Test ID: AwsJson10ServiceRespondsWithNoPayload
|
199 + | #[::tokio::test]
|
200 + | #[::tracing_test::traced_test]
|
201 + | async fn aws_json10_service_responds_with_no_payload_response() {
|
202 + | let output = crate::output::NoInputAndNoOutputOutput {};
|
203 + | use ::aws_smithy_http_server::response::IntoResponse;
|
204 + | let http_response = output.into_response();
|
205 + | ::pretty_assertions::assert_eq!(
|
206 + | ::http_1x::StatusCode::from_u16(200).expect("invalid expected HTTP status code"),
|
207 + | http_response.status()
|
208 + | );
|
209 + | let expected_headers = [("Content-Type", "application/x-amz-json-1.0")];
|
210 + | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_headers(
|
211 + | http_response.headers(),
|
212 + | expected_headers,
|
213 + | ));
|
214 + | use ::http_body_util::BodyExt;
|
215 + | let body = http_response
|
216 + | .into_body()
|
217 + | .collect()
|
218 + | .await
|
219 + | .expect("unable to collect body")
|
220 + | .to_bytes();
|
221 + | // No body.
|
222 + | ::pretty_assertions::assert_eq!(&body, &bytes::Bytes::new());
|
223 + | }
|
135 224 | }
|
136 225 |
|
137 226 | ::pin_project_lite::pin_project! {
|
138 227 | /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the
|
139 - | /// [`OperationWithRequiredMembersWithDefaultsInput`](crate::input::OperationWithRequiredMembersWithDefaultsInput) using modelled bindings.
|
140 - | pub struct OperationWithRequiredMembersWithDefaultsInputFuture {
|
141 - | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::OperationWithRequiredMembersWithDefaultsInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
228 + | /// [`NoInputAndOutputInput`](crate::input::NoInputAndOutputInput) using modelled bindings.
|
229 + | pub struct NoInputAndOutputInputFuture {
|
230 + | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::NoInputAndOutputInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
142 231 | }
|
143 232 | }
|
144 233 |
|
145 - | impl std::future::Future for OperationWithRequiredMembersWithDefaultsInputFuture {
|
234 + | impl std::future::Future for NoInputAndOutputInputFuture {
|
146 235 | type Output = Result<
|
147 - | crate::input::OperationWithRequiredMembersWithDefaultsInput,
|
236 + | crate::input::NoInputAndOutputInput,
|
148 237 | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError,
|
149 238 | >;
|
150 239 |
|
151 240 | fn poll(
|
152 241 | self: std::pin::Pin<&mut Self>,
|
153 242 | cx: &mut std::task::Context<'_>,
|
154 243 | ) -> std::task::Poll<Self::Output> {
|
155 244 | let this = self.project();
|
156 245 | this.inner.as_mut().poll(cx)
|
157 246 | }
|
158 247 | }
|
159 248 |
|
160 249 | impl<B>
|
161 250 | ::aws_smithy_http_server::request::FromRequest<
|
162 251 | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
163 252 | B,
|
164 - | > for crate::input::OperationWithRequiredMembersWithDefaultsInput
|
253 + | > for crate::input::NoInputAndOutputInput
|
165 254 | where
|
166 255 | B: ::aws_smithy_http_server::body::HttpBody + Send,
|
167 256 | B: 'static,
|
168 257 |
|
169 258 | B::Data: Send,
|
170 259 | ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection:
|
171 260 | From<<B as ::aws_smithy_http_server::body::HttpBody>::Error>,
|
172 261 | {
|
173 262 | type Rejection = ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError;
|
174 - | type Future = OperationWithRequiredMembersWithDefaultsInputFuture;
|
263 + | type Future = NoInputAndOutputInputFuture;
|
175 264 |
|
176 265 | fn from_request(request: ::http_1x::Request<B>) -> Self::Future {
|
177 266 | let fut = async move {
|
178 267 | if !::aws_smithy_http_server::protocol::accept_header_classifier(
|
179 268 | request.headers(),
|
180 269 | &crate::mimes::CONTENT_TYPE_APPLICATION_X_AMZ_JSON_1_0,
|
181 270 | ) {
|
182 271 | return Err(::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection::NotAcceptable);
|
183 272 | }
|
184 - | crate::protocol_serde::shape_operation_with_required_members_with_defaults::de_operation_with_required_members_with_defaults_http_request(request)
|
273 + | crate::protocol_serde::shape_no_input_and_output::de_no_input_and_output_http_request(
|
274 + | request,
|
275 + | )
|
185 276 | .await
|
186 277 | };
|
187 278 | use ::futures_util::future::TryFutureExt;
|
188 279 | let fut = fut.map_err(
|
189 280 | |e: ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection| {
|
190 281 | ::tracing::debug!(error = %e, "failed to deserialize request");
|
191 282 | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e)
|
192 283 | },
|
193 284 | );
|
194 - | OperationWithRequiredMembersWithDefaultsInputFuture {
|
285 + | NoInputAndOutputInputFuture {
|
195 286 | inner: Box::pin(fut),
|
196 287 | }
|
197 288 | }
|
198 289 | }
|
199 290 | impl
|
200 291 | ::aws_smithy_http_server::response::IntoResponse<
|
201 292 | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
202 - | > for crate::output::OperationWithRequiredMembersWithDefaultsOutput
|
293 + | > for crate::output::NoInputAndOutputOutput
|
203 294 | {
|
204 295 | fn into_response(self) -> ::aws_smithy_http_server::response::Response {
|
205 - | match crate::protocol_serde::shape_operation_with_required_members_with_defaults::ser_operation_with_required_members_with_defaults_http_response(self) {
|
296 + | match crate::protocol_serde::shape_no_input_and_output::ser_no_input_and_output_http_response(self) {
|
206 297 | Ok(response) => response,
|
207 298 | Err(e) => {
|
208 299 | ::tracing::error!(error = %e, "failed to serialize response");
|
209 300 | ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0>::into_response(::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e))
|
210 301 | }
|
211 302 | }
|
212 303 | }
|
213 304 | }
|
214 305 |
|
306 + | #[allow(unreachable_code, unused_variables)]
|
307 + | #[cfg(test)]
|
308 + | mod no_input_and_output_test {
|
309 + |
|
310 + | /// A client should always send and empty JSON object payload.
|
311 + | /// Test ID: AwsJson10NoInputAndOutput
|
312 + | #[::tokio::test]
|
313 + | #[::tracing_test::traced_test]
|
314 + | async fn aws_json10_no_input_and_output_request() {
|
315 + | #[allow(unused_mut)]
|
316 + | let mut http_request = ::http_1x::Request::builder()
|
317 + | .uri("/")
|
318 + | .method("POST")
|
319 + | .header("Content-Type", "application/x-amz-json-1.0")
|
320 + | .header("X-Amz-Target", "JsonRpc10.NoInputAndOutput")
|
321 + | .body(::aws_smithy_http_server::body::boxed(
|
322 + | ::http_body_util::Full::new(::bytes::Bytes::copy_from_slice(
|
323 + | &::aws_smithy_protocol_test::decode_body_data(
|
324 + | "{}".as_bytes(),
|
325 + | ::aws_smithy_protocol_test::MediaType::from("application/json"),
|
326 + | ),
|
327 + | )),
|
328 + | ))
|
329 + | .unwrap();
|
330 + | #[allow(unused_mut)]
|
331 + | let (sender, mut receiver) = ::tokio::sync::mpsc::channel(1);
|
332 + | let config = crate::service::JsonRpc10Config::builder().build();
|
333 + | let service =
|
334 + | crate::service::JsonRpc10::builder::<::aws_smithy_http_server::body::BoxBody, _, _, _>(
|
335 + | config,
|
336 + | )
|
337 + | .no_input_and_output(move |input: crate::input::NoInputAndOutputInput| {
|
338 + | let sender = sender.clone();
|
339 + | async move {
|
340 + | let result = {
|
341 + | let expected = crate::input::NoInputAndOutputInput {};
|
342 + | ::pretty_assertions::assert_eq!(input, expected);
|
343 + | let output = crate::output::NoInputAndOutputOutput {};
|
344 + | output
|
345 + | };
|
346 + | sender.send(()).await.expect("receiver dropped early");
|
347 + | result
|
348 + | }
|
349 + | })
|
350 + | .build_unchecked();
|
351 + | let http_response = ::tower::ServiceExt::oneshot(service, http_request)
|
352 + | .await
|
353 + | .expect("unable to make an HTTP request");
|
354 + | assert!(
|
355 + | receiver.recv().await.is_some(),
|
356 + | "we expected operation handler to be invoked but it was not entered"
|
357 + | );
|
358 + | }
|
359 + |
|
360 + | /// Empty output always serializes an empty object payload.
|
361 + | /// Test ID: AwsJson10NoInputAndOutput
|
362 + | #[::tokio::test]
|
363 + | #[::tracing_test::traced_test]
|
364 + | async fn aws_json10_no_input_and_output_response() {
|
365 + | let output = crate::output::NoInputAndOutputOutput {};
|
366 + | use ::aws_smithy_http_server::response::IntoResponse;
|
367 + | let http_response = output.into_response();
|
368 + | ::pretty_assertions::assert_eq!(
|
369 + | ::http_1x::StatusCode::from_u16(200).expect("invalid expected HTTP status code"),
|
370 + | http_response.status()
|
371 + | );
|
372 + | let expected_headers = [("Content-Type", "application/x-amz-json-1.0")];
|
373 + | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_headers(
|
374 + | http_response.headers(),
|
375 + | expected_headers,
|
376 + | ));
|
377 + | use ::http_body_util::BodyExt;
|
378 + | let body = http_response
|
379 + | .into_body()
|
380 + | .collect()
|
381 + | .await
|
382 + | .expect("unable to collect body")
|
383 + | .to_bytes();
|
384 + | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_body(
|
385 + | &body,
|
386 + | "{}",
|
387 + | ::aws_smithy_protocol_test::MediaType::from("application/json"),
|
388 + | ));
|
389 + | }
|
390 + | }
|
391 + |
|
215 392 | ::pin_project_lite::pin_project! {
|
216 393 | /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the
|
217 - | /// [`OperationWithNestedStructureInput`](crate::input::OperationWithNestedStructureInput) using modelled bindings.
|
218 - | pub struct OperationWithNestedStructureInputFuture {
|
219 - | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::OperationWithNestedStructureInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
394 + | /// [`EmptyInputAndEmptyOutputInput`](crate::input::EmptyInputAndEmptyOutputInput) using modelled bindings.
|
395 + | pub struct EmptyInputAndEmptyOutputInputFuture {
|
396 + | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::EmptyInputAndEmptyOutputInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
220 397 | }
|
221 398 | }
|
222 399 |
|
223 - | impl std::future::Future for OperationWithNestedStructureInputFuture {
|
400 + | impl std::future::Future for EmptyInputAndEmptyOutputInputFuture {
|
224 401 | type Output = Result<
|
225 - | crate::input::OperationWithNestedStructureInput,
|
402 + | crate::input::EmptyInputAndEmptyOutputInput,
|
226 403 | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError,
|
227 404 | >;
|
228 405 |
|
229 406 | fn poll(
|
230 407 | self: std::pin::Pin<&mut Self>,
|
231 408 | cx: &mut std::task::Context<'_>,
|
232 409 | ) -> std::task::Poll<Self::Output> {
|
233 410 | let this = self.project();
|
234 411 | this.inner.as_mut().poll(cx)
|
235 412 | }
|
236 413 | }
|
237 414 |
|
238 415 | impl<B>
|
239 416 | ::aws_smithy_http_server::request::FromRequest<
|
240 417 | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
241 418 | B,
|
242 - | > for crate::input::OperationWithNestedStructureInput
|
419 + | > for crate::input::EmptyInputAndEmptyOutputInput
|
243 420 | where
|
244 421 | B: ::aws_smithy_http_server::body::HttpBody + Send,
|
245 422 | B: 'static,
|
246 423 |
|
247 424 | B::Data: Send,
|
248 425 | ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection:
|
249 426 | From<<B as ::aws_smithy_http_server::body::HttpBody>::Error>,
|
250 427 | {
|
251 428 | type Rejection = ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError;
|
252 - | type Future = OperationWithNestedStructureInputFuture;
|
429 + | type Future = EmptyInputAndEmptyOutputInputFuture;
|
253 430 |
|
254 431 | fn from_request(request: ::http_1x::Request<B>) -> Self::Future {
|
255 432 | let fut = async move {
|
256 433 | if !::aws_smithy_http_server::protocol::accept_header_classifier(
|
257 434 | request.headers(),
|
258 435 | &crate::mimes::CONTENT_TYPE_APPLICATION_X_AMZ_JSON_1_0,
|
259 436 | ) {
|
260 437 | return Err(::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection::NotAcceptable);
|
261 438 | }
|
262 - | crate::protocol_serde::shape_operation_with_nested_structure::de_operation_with_nested_structure_http_request(request)
|
439 + | crate::protocol_serde::shape_empty_input_and_empty_output::de_empty_input_and_empty_output_http_request(request)
|
263 440 | .await
|
264 441 | };
|
265 442 | use ::futures_util::future::TryFutureExt;
|
266 443 | let fut = fut.map_err(
|
267 444 | |e: ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection| {
|
268 445 | ::tracing::debug!(error = %e, "failed to deserialize request");
|
269 446 | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e)
|
270 447 | },
|
271 448 | );
|
272 - | OperationWithNestedStructureInputFuture {
|
449 + | EmptyInputAndEmptyOutputInputFuture {
|
273 450 | inner: Box::pin(fut),
|
274 451 | }
|
275 452 | }
|
276 453 | }
|
277 454 | impl
|
278 455 | ::aws_smithy_http_server::response::IntoResponse<
|
279 456 | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
280 - | > for crate::output::OperationWithNestedStructureOutput
|
457 + | > for crate::output::EmptyInputAndEmptyOutputOutput
|
281 458 | {
|
282 459 | fn into_response(self) -> ::aws_smithy_http_server::response::Response {
|
283 - | match crate::protocol_serde::shape_operation_with_nested_structure::ser_operation_with_nested_structure_http_response(self) {
|
460 + | match crate::protocol_serde::shape_empty_input_and_empty_output::ser_empty_input_and_empty_output_http_response(self) {
|
284 461 | Ok(response) => response,
|
285 462 | Err(e) => {
|
286 463 | ::tracing::error!(error = %e, "failed to serialize response");
|
287 464 | ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0>::into_response(::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e))
|
288 465 | }
|
289 466 | }
|
290 467 | }
|
291 468 | }
|
292 - | impl
|
293 - | ::aws_smithy_http_server::response::IntoResponse<
|
294 - | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
295 - | > for crate::error::OperationWithNestedStructureError
|
296 - | {
|
297 - | fn into_response(self) -> ::aws_smithy_http_server::response::Response {
|
298 - | match crate::protocol_serde::shape_operation_with_nested_structure::ser_operation_with_nested_structure_http_error(&self) {
|
299 - | Ok(mut response) => {
|
300 - | response.extensions_mut().insert(::aws_smithy_http_server::extension::ModeledErrorExtension::new(self.name()));
|
301 - | response
|
302 - | },
|
303 - | Err(e) => {
|
304 - | ::tracing::error!(error = %e, "failed to serialize response");
|
305 - | ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0>::into_response(::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e))
|
306 - | }
|
307 - | }
|
308 - | }
|
309 - | }
|
310 469 |
|
311 470 | #[allow(unreachable_code, unused_variables)]
|
312 471 | #[cfg(test)]
|
313 - | mod operation_with_nested_structure_test {
|
472 + | mod empty_input_and_empty_output_test {
|
314 473 |
|
315 - | /// Server populates nested default values when missing in request body.
|
316 - | /// Test ID: AwsJson10ServerPopulatesNestedDefaultsWhenMissingInRequestBody
|
474 + | /// Clients must always send an empty object if input is modeled.
|
475 + | /// Test ID: AwsJson10EmptyInputAndEmptyOutput
|
317 476 | #[::tokio::test]
|
318 477 | #[::tracing_test::traced_test]
|
319 - | #[should_panic]
|
320 - | async fn aws_json10_server_populates_nested_defaults_when_missing_in_request_body_request() {
|
478 + | async fn aws_json10_empty_input_and_empty_output_request() {
|
321 479 | #[allow(unused_mut)]
|
322 480 | let mut http_request = ::http_1x::Request::builder()
|
323 481 | .uri("/")
|
324 482 | .method("POST")
|
325 483 | .header("Content-Type", "application/x-amz-json-1.0")
|
326 - | .body(::aws_smithy_http_server::body::boxed(::http_body_util::Full::new(
|
327 - | ::bytes::Bytes::copy_from_slice(
|
328 - | &::aws_smithy_protocol_test::decode_body_data("{\n \"topLevel\": {\n \"dialog\": {\n \"language\": \"en\"\n },\n \"dialogList\": [\n {\n },\n {\n \"farewell\": {}\n },\n {\n \"language\": \"it\",\n \"greeting\": \"ciao\",\n \"farewell\": {\n \"phrase\": \"arrivederci\"\n }\n }\n ],\n \"dialogMap\": {\n \"emptyDialog\": {\n },\n \"partialEmptyDialog\": {\n \"language\": \"en\",\n \"farewell\": {}\n },\n \"nonEmptyDialog\": {\n \"greeting\": \"konnichiwa\",\n \"farewell\": {\n \"phrase\": \"sayonara\"\n }\n }\n }\n }\n}".as_bytes(), ::aws_smithy_protocol_test::MediaType::from("application/json"))
|
329 - | )
|
330 - | ))).unwrap();
|
484 + | .header("X-Amz-Target", "JsonRpc10.EmptyInputAndEmptyOutput")
|
485 + | .body(::aws_smithy_http_server::body::boxed(
|
486 + | ::http_body_util::Full::new(::bytes::Bytes::copy_from_slice(
|
487 + | &::aws_smithy_protocol_test::decode_body_data(
|
488 + | "{}".as_bytes(),
|
489 + | ::aws_smithy_protocol_test::MediaType::from("application/json"),
|
490 + | ),
|
491 + | )),
|
492 + | ))
|
493 + | .unwrap();
|
331 494 | #[allow(unused_mut)]
|
332 495 | let (sender, mut receiver) = ::tokio::sync::mpsc::channel(1);
|
333 496 | let config = crate::service::JsonRpc10Config::builder().build();
|
334 497 | let service = crate::service::JsonRpc10::builder::<
|
335 498 | ::aws_smithy_http_server::body::BoxBody,
|
336 499 | _,
|
337 500 | _,
|
338 501 | _,
|
339 502 | >(config)
|
340 - | .operation_with_nested_structure(
|
341 - | move |input: crate::input::OperationWithNestedStructureInput| {
|
503 + | .empty_input_and_empty_output(move |input: crate::input::EmptyInputAndEmptyOutputInput| {
|
342 504 | let sender = sender.clone();
|
343 505 | async move {
|
344 506 | let result = {
|
345 - | let expected = crate::input::OperationWithNestedStructureInput {
|
346 - | top_level: crate::model::TopLevel {
|
347 - | dialog: crate::model::Dialog {
|
348 - | language: ::std::option::Option::Some("en".to_owned()),
|
349 - | greeting: "hi".to_owned(),
|
350 - | farewell: ::std::option::Option::None,
|
351 - | },
|
352 - | dialog_list: vec![
|
353 - | crate::model::Dialog {
|
354 - | greeting: "hi".to_owned(),
|
355 - | language: ::std::option::Option::None,
|
356 - | farewell: ::std::option::Option::None,
|
357 - | },
|
358 - | crate::model::Dialog {
|
359 - | greeting: "hi".to_owned(),
|
360 - | farewell: ::std::option::Option::Some(
|
361 - | crate::model::Farewell {
|
362 - | phrase: "bye".to_owned(),
|
363 - | },
|
364 - | ),
|
365 - | language: ::std::option::Option::None,
|
366 - | },
|
367 - | crate::model::Dialog {
|
368 - | language: ::std::option::Option::Some("it".to_owned()),
|
369 - | greeting: "ciao".to_owned(),
|
370 - | farewell: ::std::option::Option::Some(
|
371 - | crate::model::Farewell {
|
372 - | phrase: "arrivederci".to_owned(),
|
373 - | },
|
374 - | ),
|
375 - | },
|
376 - | ],
|
377 - | dialog_map: {
|
378 - | let mut ret = ::std::collections::HashMap::new();
|
379 - | ret.insert(
|
380 - | "emptyDialog".to_owned(),
|
381 - | crate::model::Dialog {
|
382 - | greeting: "hi".to_owned(),
|
383 - | language: ::std::option::Option::None,
|
384 - | farewell: ::std::option::Option::None,
|
385 - | },
|
386 - | );
|
387 - | ret.insert(
|
388 - | "partialEmptyDialog".to_owned(),
|
389 - | crate::model::Dialog {
|
390 - | language: ::std::option::Option::Some("en".to_owned()),
|
391 - | greeting: "hi".to_owned(),
|
392 - | farewell: ::std::option::Option::Some(
|
393 - | crate::model::Farewell {
|
394 - | phrase: "bye".to_owned(),
|
395 - | },
|
396 - | ),
|
397 - | },
|
398 - | );
|
399 - | ret.insert(
|
400 - | "nonEmptyDialog".to_owned(),
|
401 - | crate::model::Dialog {
|
402 - | greeting: "konnichiwa".to_owned(),
|
403 - | farewell: ::std::option::Option::Some(
|
404 - | crate::model::Farewell {
|
405 - | phrase: "sayonara".to_owned(),
|
406 - | },
|
407 - | ),
|
408 - | language: ::std::option::Option::None,
|
409 - | },
|
410 - | );
|
411 - | ret
|
412 - | },
|
413 - | },
|
414 - | };
|
507 + | let expected = crate::input::EmptyInputAndEmptyOutputInput {};
|
415 508 | ::pretty_assertions::assert_eq!(input, expected);
|
416 - | let output = crate::output::OperationWithNestedStructureOutput {
|
417 - | dialog: crate::model::Dialog {
|
418 - | greeting: "".to_owned(),
|
419 - | language: ::std::option::Option::None,
|
420 - | farewell: ::std::option::Option::None,
|
421 - | },
|
422 - | dialog_list: vec![],
|
423 - | dialog_map: ::std::collections::HashMap::new(),
|
424 - | };
|
425 - | Ok(output)
|
509 + | let output = crate::output::EmptyInputAndEmptyOutputOutput {};
|
510 + | output
|
426 511 | };
|
427 512 | sender.send(()).await.expect("receiver dropped early");
|
428 513 | result
|
429 514 | }
|
430 - | },
|
431 - | )
|
515 + | })
|
432 516 | .build_unchecked();
|
433 517 | let http_response = ::tower::ServiceExt::oneshot(service, http_request)
|
434 518 | .await
|
435 519 | .expect("unable to make an HTTP request");
|
436 520 | assert!(
|
437 521 | receiver.recv().await.is_some(),
|
438 522 | "we expected operation handler to be invoked but it was not entered"
|
439 523 | );
|
440 524 | }
|
441 525 |
|
442 - | /// Server populates nested default values when missing in response params.
|
443 - | /// Test ID: AwsJson10ServerPopulatesNestedDefaultValuesWhenMissingInInResponseParams
|
526 + | /// A service will always return a JSON object for operations with modeled output.
|
527 + | /// Test ID: AwsJson10EmptyInputAndEmptyOutputSendJsonObject
|
444 528 | #[::tokio::test]
|
445 529 | #[::tracing_test::traced_test]
|
446 - | #[should_panic]
|
447 - | async fn aws_json10_server_populates_nested_default_values_when_missing_in_in_response_params_response(
|
448 - | ) {
|
449 - | let output = crate::output::OperationWithNestedStructureOutput {
|
450 - | dialog: crate::model::Dialog {
|
451 - | greeting: "".to_owned(),
|
452 - | language: ::std::option::Option::Some("en".to_owned()),
|
453 - | farewell: ::std::option::Option::None,
|
454 - | },
|
455 - | dialog_list: vec![
|
456 - | crate::model::Dialog {
|
457 - | greeting: "".to_owned(),
|
458 - | language: ::std::option::Option::None,
|
459 - | farewell: ::std::option::Option::None,
|
460 - | },
|
461 - | crate::model::Dialog {
|
462 - | greeting: "".to_owned(),
|
463 - | farewell: ::std::option::Option::Some(crate::model::Farewell {
|
464 - | phrase: "".to_owned(),
|
465 - | }),
|
466 - | language: ::std::option::Option::None,
|
467 - | },
|
468 - | crate::model::Dialog {
|
469 - | language: ::std::option::Option::Some("it".to_owned()),
|
470 - | greeting: "ciao".to_owned(),
|
471 - | farewell: ::std::option::Option::Some(crate::model::Farewell {
|
472 - | phrase: "arrivederci".to_owned(),
|
473 - | }),
|
474 - | },
|
475 - | ],
|
476 - | dialog_map: {
|
477 - | let mut ret = ::std::collections::HashMap::new();
|
478 - | ret.insert(
|
479 - | "emptyDialog".to_owned(),
|
480 - | crate::model::Dialog {
|
481 - | greeting: "".to_owned(),
|
482 - | language: ::std::option::Option::None,
|
483 - | farewell: ::std::option::Option::None,
|
484 - | },
|
485 - | );
|
486 - | ret.insert(
|
487 - | "partialEmptyDialog".to_owned(),
|
488 - | crate::model::Dialog {
|
489 - | greeting: "".to_owned(),
|
490 - | language: ::std::option::Option::Some("en".to_owned()),
|
491 - | farewell: ::std::option::Option::Some(crate::model::Farewell {
|
492 - | phrase: "".to_owned(),
|
493 - | }),
|
494 - | },
|
495 - | );
|
496 - | ret.insert(
|
497 - | "nonEmptyDialog".to_owned(),
|
498 - | crate::model::Dialog {
|
499 - | greeting: "konnichiwa".to_owned(),
|
500 - | farewell: ::std::option::Option::Some(crate::model::Farewell {
|
501 - | phrase: "sayonara".to_owned(),
|
502 - | }),
|
503 - | language: ::std::option::Option::None,
|
504 - | },
|
505 - | );
|
506 - | ret
|
507 - | },
|
508 - | };
|
530 + | async fn aws_json10_empty_input_and_empty_output_send_json_object_response() {
|
531 + | let output = crate::output::EmptyInputAndEmptyOutputOutput {};
|
509 532 | use ::aws_smithy_http_server::response::IntoResponse;
|
510 533 | let http_response = output.into_response();
|
511 534 | ::pretty_assertions::assert_eq!(
|
512 535 | ::http_1x::StatusCode::from_u16(200).expect("invalid expected HTTP status code"),
|
513 536 | http_response.status()
|
514 537 | );
|
515 538 | let expected_headers = [("Content-Type", "application/x-amz-json-1.0")];
|
516 539 | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_headers(
|
517 540 | http_response.headers(),
|
518 541 | expected_headers,
|
519 542 | ));
|
520 543 | use ::http_body_util::BodyExt;
|
521 544 | let body = http_response
|
522 545 | .into_body()
|
523 546 | .collect()
|
524 547 | .await
|
525 548 | .expect("unable to collect body")
|
526 549 | .to_bytes();
|
527 - | ::aws_smithy_protocol_test::assert_ok(
|
528 - | ::aws_smithy_protocol_test::validate_body(&body, "{\n \"dialog\": {\n \"language\": \"en\",\n \"greeting\": \"hi\"\n },\n \"dialogList\": [\n {\n \"greeting\": \"hi\"\n },\n {\n \"greeting\": \"hi\",\n \"farewell\": {\n \"phrase\": \"bye\"\n }\n },\n {\n \"language\": \"it\",\n \"greeting\": \"ciao\",\n \"farewell\": {\n \"phrase\": \"arrivederci\"\n }\n }\n ],\n \"dialogMap\": {\n \"emptyDialog\": {\n \"greeting\": \"hi\"\n },\n \"partialEmptyDialog\": {\n \"language\": \"en\",\n \"greeting\": \"hi\",\n \"farewell\": {\n \"phrase\": \"bye\"\n }\n },\n \"nonEmptyDialog\": {\n \"greeting\": \"konnichiwa\",\n \"farewell\": {\n \"phrase\": \"sayonara\"\n }\n }\n }\n}", ::aws_smithy_protocol_test::MediaType::from("application/json"))
|
529 - | );
|
550 + | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_body(
|
551 + | &body,
|
552 + | "{}",
|
553 + | ::aws_smithy_protocol_test::MediaType::from("application/json"),
|
554 + | ));
|
530 555 | }
|
531 556 | }
|
532 557 |
|
533 558 | ::pin_project_lite::pin_project! {
|
534 559 | /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the
|
535 - | /// [`OperationWithRequiredMembersInput`](crate::input::OperationWithRequiredMembersInput) using modelled bindings.
|
536 - | pub struct OperationWithRequiredMembersInputFuture {
|
537 - | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::OperationWithRequiredMembersInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
560 + | /// [`SimpleScalarPropertiesInput`](crate::input::SimpleScalarPropertiesInput) using modelled bindings.
|
561 + | pub struct SimpleScalarPropertiesInputFuture {
|
562 + | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::SimpleScalarPropertiesInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
538 563 | }
|
539 564 | }
|
540 565 |
|
541 - | impl std::future::Future for OperationWithRequiredMembersInputFuture {
|
566 + | impl std::future::Future for SimpleScalarPropertiesInputFuture {
|
542 567 | type Output = Result<
|
543 - | crate::input::OperationWithRequiredMembersInput,
|
568 + | crate::input::SimpleScalarPropertiesInput,
|
544 569 | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError,
|
545 570 | >;
|
546 571 |
|
547 572 | fn poll(
|
548 573 | self: std::pin::Pin<&mut Self>,
|
549 574 | cx: &mut std::task::Context<'_>,
|
550 575 | ) -> std::task::Poll<Self::Output> {
|
551 576 | let this = self.project();
|
552 577 | this.inner.as_mut().poll(cx)
|
553 578 | }
|
554 579 | }
|
555 580 |
|
556 581 | impl<B>
|
557 582 | ::aws_smithy_http_server::request::FromRequest<
|
558 583 | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
559 584 | B,
|
560 - | > for crate::input::OperationWithRequiredMembersInput
|
585 + | > for crate::input::SimpleScalarPropertiesInput
|
561 586 | where
|
562 587 | B: ::aws_smithy_http_server::body::HttpBody + Send,
|
563 588 | B: 'static,
|
564 589 |
|
565 590 | B::Data: Send,
|
566 591 | ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection:
|
567 592 | From<<B as ::aws_smithy_http_server::body::HttpBody>::Error>,
|
568 593 | {
|
569 594 | type Rejection = ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError;
|
570 - | type Future = OperationWithRequiredMembersInputFuture;
|
595 + | type Future = SimpleScalarPropertiesInputFuture;
|
571 596 |
|
572 597 | fn from_request(request: ::http_1x::Request<B>) -> Self::Future {
|
573 598 | let fut = async move {
|
574 599 | if !::aws_smithy_http_server::protocol::accept_header_classifier(
|
575 600 | request.headers(),
|
576 601 | &crate::mimes::CONTENT_TYPE_APPLICATION_X_AMZ_JSON_1_0,
|
577 602 | ) {
|
578 603 | return Err(::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection::NotAcceptable);
|
579 604 | }
|
580 - | crate::protocol_serde::shape_operation_with_required_members::de_operation_with_required_members_http_request(request)
|
605 + | crate::protocol_serde::shape_simple_scalar_properties::de_simple_scalar_properties_http_request(request)
|
581 606 | .await
|
582 607 | };
|
583 608 | use ::futures_util::future::TryFutureExt;
|
584 609 | let fut = fut.map_err(
|
585 610 | |e: ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection| {
|
586 611 | ::tracing::debug!(error = %e, "failed to deserialize request");
|
587 612 | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e)
|
588 613 | },
|
589 614 | );
|
590 - | OperationWithRequiredMembersInputFuture {
|
615 + | SimpleScalarPropertiesInputFuture {
|
591 616 | inner: Box::pin(fut),
|
592 617 | }
|
593 618 | }
|
594 619 | }
|
595 620 | impl
|
596 621 | ::aws_smithy_http_server::response::IntoResponse<
|
597 622 | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
598 - | > for crate::output::OperationWithRequiredMembersOutput
|
623 + | > for crate::output::SimpleScalarPropertiesOutput
|
599 624 | {
|
600 625 | fn into_response(self) -> ::aws_smithy_http_server::response::Response {
|
601 - | match crate::protocol_serde::shape_operation_with_required_members::ser_operation_with_required_members_http_response(self) {
|
626 + | match crate::protocol_serde::shape_simple_scalar_properties::ser_simple_scalar_properties_http_response(self) {
|
602 627 | Ok(response) => response,
|
603 628 | Err(e) => {
|
604 629 | ::tracing::error!(error = %e, "failed to serialize response");
|
605 630 | ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0>::into_response(::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e))
|
606 631 | }
|
607 632 | }
|
608 633 | }
|
609 634 | }
|
610 635 |
|
611 - | ::pin_project_lite::pin_project! {
|
612 - | /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the
|
613 - | /// [`OperationWithDefaultsInput`](crate::input::OperationWithDefaultsInput) using modelled bindings.
|
614 - | pub struct OperationWithDefaultsInputFuture {
|
615 - | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::OperationWithDefaultsInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
616 - | }
|
617 - | }
|
618 - |
|
619 - | impl std::future::Future for OperationWithDefaultsInputFuture {
|
620 - | type Output = Result<
|
621 - | crate::input::OperationWithDefaultsInput,
|
622 - | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError,
|
623 - | >;
|
636 + | #[allow(unreachable_code, unused_variables)]
|
637 + | #[cfg(test)]
|
638 + | mod simple_scalar_properties_test {
|
624 639 |
|
625 - | fn poll(
|
626 - | self: std::pin::Pin<&mut Self>,
|
627 - | cx: &mut std::task::Context<'_>,
|
628 - | ) -> std::task::Poll<Self::Output> {
|
629 - | let this = self.project();
|
630 - | this.inner.as_mut().poll(cx)
|
631 - | }
|
632 - | }
|
633 - |
|
634 - | impl<B>
|
635 - | ::aws_smithy_http_server::request::FromRequest<
|
636 - | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
637 - | B,
|
638 - | > for crate::input::OperationWithDefaultsInput
|
639 - | where
|
640 - | B: ::aws_smithy_http_server::body::HttpBody + Send,
|
641 - | B: 'static,
|
642 - |
|
643 - | B::Data: Send,
|
644 - | ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection:
|
645 - | From<<B as ::aws_smithy_http_server::body::HttpBody>::Error>,
|
646 - | {
|
647 - | type Rejection = ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError;
|
648 - | type Future = OperationWithDefaultsInputFuture;
|
649 - |
|
650 - | fn from_request(request: ::http_1x::Request<B>) -> Self::Future {
|
651 - | let fut = async move {
|
652 - | if !::aws_smithy_http_server::protocol::accept_header_classifier(
|
653 - | request.headers(),
|
654 - | &crate::mimes::CONTENT_TYPE_APPLICATION_X_AMZ_JSON_1_0,
|
655 - | ) {
|
656 - | return Err(::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection::NotAcceptable);
|
657 - | }
|
658 - | crate::protocol_serde::shape_operation_with_defaults::de_operation_with_defaults_http_request(request)
|
659 - | .await
|
660 - | };
|
661 - | use ::futures_util::future::TryFutureExt;
|
662 - | let fut = fut.map_err(
|
663 - | |e: ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection| {
|
664 - | ::tracing::debug!(error = %e, "failed to deserialize request");
|
665 - | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e)
|
666 - | },
|
667 - | );
|
668 - | OperationWithDefaultsInputFuture {
|
669 - | inner: Box::pin(fut),
|
670 - | }
|
671 - | }
|
672 - | }
|
673 - | impl
|
674 - | ::aws_smithy_http_server::response::IntoResponse<
|
675 - | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
676 - | > for crate::output::OperationWithDefaultsOutput
|
677 - | {
|
678 - | fn into_response(self) -> ::aws_smithy_http_server::response::Response {
|
679 - | match crate::protocol_serde::shape_operation_with_defaults::ser_operation_with_defaults_http_response(self) {
|
680 - | Ok(response) => response,
|
681 - | Err(e) => {
|
682 - | ::tracing::error!(error = %e, "failed to serialize response");
|
683 - | ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0>::into_response(::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e))
|
684 - | }
|
685 - | }
|
686 - | }
|
687 - | }
|
688 - | impl
|
689 - | ::aws_smithy_http_server::response::IntoResponse<
|
690 - | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
691 - | > for crate::error::OperationWithDefaultsError
|
692 - | {
|
693 - | fn into_response(self) -> ::aws_smithy_http_server::response::Response {
|
694 - | match crate::protocol_serde::shape_operation_with_defaults::ser_operation_with_defaults_http_error(&self) {
|
695 - | Ok(mut response) => {
|
696 - | response.extensions_mut().insert(::aws_smithy_http_server::extension::ModeledErrorExtension::new(self.name()));
|
697 - | response
|
698 - | },
|
699 - | Err(e) => {
|
700 - | ::tracing::error!(error = %e, "failed to serialize response");
|
701 - | ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0>::into_response(::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e))
|
702 - | }
|
703 - | }
|
704 - | }
|
705 - | }
|
706 - |
|
707 - | #[allow(unreachable_code, unused_variables)]
|
708 - | #[cfg(test)]
|
709 - | mod operation_with_defaults_test {
|
710 - |
|
711 - | /// Server populates default values when missing in request body.
|
712 - | /// Test ID: AwsJson10ServerPopulatesDefaultsWhenMissingInRequestBody
|
640 + | /// Supports handling NaN float values.
|
641 + | /// Test ID: AwsJson10SupportsNaNFloatInputs
|
713 642 | #[::tokio::test]
|
714 643 | #[::tracing_test::traced_test]
|
715 - | #[should_panic]
|
716 - | async fn aws_json10_server_populates_defaults_when_missing_in_request_body_request() {
|
644 + | async fn aws_json10_supports_na_n_float_inputs_request() {
|
717 645 | #[allow(unused_mut)]
|
718 646 | let mut http_request = ::http_1x::Request::builder()
|
719 647 | .uri("/")
|
720 648 | .method("POST")
|
721 649 | .header("Content-Type", "application/x-amz-json-1.0")
|
650 + | .header("X-Amz-Target", "JsonRpc10.SimpleScalarProperties")
|
722 651 | .body(::aws_smithy_http_server::body::boxed(
|
723 652 | ::http_body_util::Full::new(::bytes::Bytes::copy_from_slice(
|
724 653 | &::aws_smithy_protocol_test::decode_body_data(
|
725 - | "{\n\"defaults\": {}\n}".as_bytes(),
|
654 + | "{\n \"floatValue\": \"NaN\",\n \"doubleValue\": \"NaN\"\n}"
|
655 + | .as_bytes(),
|
726 656 | ::aws_smithy_protocol_test::MediaType::from("application/json"),
|
727 657 | ),
|
728 658 | )),
|
729 659 | ))
|
730 660 | .unwrap();
|
731 661 | #[allow(unused_mut)]
|
732 662 | let (sender, mut receiver) = ::tokio::sync::mpsc::channel(1);
|
733 663 | let config = crate::service::JsonRpc10Config::builder().build();
|
734 664 | let service = crate::service::JsonRpc10::builder::<
|
735 665 | ::aws_smithy_http_server::body::BoxBody,
|
736 666 | _,
|
737 667 | _,
|
738 668 | _,
|
739 669 | >(config)
|
740 - | .operation_with_defaults(move |input: crate::input::OperationWithDefaultsInput| {
|
670 + | .simple_scalar_properties(move |input: crate::input::SimpleScalarPropertiesInput| {
|
741 671 | let sender = sender.clone();
|
742 672 | async move {
|
743 673 | let result = {
|
744 - | let expected = crate::input::OperationWithDefaultsInput {
|
745 - | defaults: ::std::option::Option::Some(crate::model::Defaults {
|
746 - | default_string: "hi".to_owned(),
|
747 - | default_boolean: true,
|
748 - | default_list: vec![],
|
749 - | default_document_map: {
|
750 - | let json_bytes = br#"{}"#;
|
751 - | let mut tokens =
|
752 - | ::aws_smithy_json::deserialize::json_token_iter(json_bytes)
|
753 - | .peekable();
|
754 - | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
755 - | .expect("well formed json")
|
756 - | },
|
757 - | default_document_string: {
|
758 - | let json_bytes = br#""hi""#;
|
759 - | let mut tokens =
|
760 - | ::aws_smithy_json::deserialize::json_token_iter(json_bytes)
|
761 - | .peekable();
|
762 - | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
763 - | .expect("well formed json")
|
764 - | },
|
765 - | default_document_boolean: {
|
766 - | let json_bytes = br#"true"#;
|
767 - | let mut tokens =
|
768 - | ::aws_smithy_json::deserialize::json_token_iter(json_bytes)
|
769 - | .peekable();
|
770 - | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
771 - | .expect("well formed json")
|
772 - | },
|
773 - | default_document_list: {
|
774 - | let json_bytes = br#"[]"#;
|
775 - | let mut tokens =
|
776 - | ::aws_smithy_json::deserialize::json_token_iter(json_bytes)
|
777 - | .peekable();
|
778 - | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
779 - | .expect("well formed json")
|
780 - | },
|
781 - | default_timestamp: ::aws_smithy_types::DateTime::from_fractional_secs(
|
782 - | 0, 0_f64,
|
674 + | use ::aws_smithy_protocol_test::FloatEquals;
|
675 + | let expected = crate::input::SimpleScalarPropertiesInput {
|
676 + | float_value: ::std::option::Option::Some(
|
677 + | <f32 as ::aws_smithy_types::primitive::Parse>::parse_smithy_primitive(
|
678 + | "NaN",
|
679 + | )
|
680 + | .expect("invalid string for number"),
|
783 681 | ),
|
784 - | default_blob: ::aws_smithy_types::Blob::new("abc"),
|
785 - | default_byte: 1,
|
786 - | default_short: 1,
|
787 - | default_integer: 10,
|
788 - | default_long: 100,
|
789 - | default_float: 1.0_f32,
|
790 - | default_double: 1.0_f64,
|
791 - | default_map: ::std::collections::HashMap::new(),
|
792 - | default_enum: "FOO"
|
793 - | .parse::<crate::model::TestEnum>()
|
794 - | .expect("static value validated to member"),
|
795 - | default_int_enum: 1,
|
796 - | empty_string: "".to_owned(),
|
797 - | false_boolean: false,
|
798 - | empty_blob: ::aws_smithy_types::Blob::new(""),
|
799 - | zero_byte: 0,
|
800 - | zero_short: 0,
|
801 - | zero_integer: 0,
|
802 - | zero_long: 0,
|
803 - | zero_float: 0.0_f32,
|
804 - | zero_double: 0.0_f64,
|
805 - | default_null_document: ::std::option::Option::Some({
|
806 - | let json_bytes = br#"null"#;
|
807 - | let mut tokens =
|
808 - | ::aws_smithy_json::deserialize::json_token_iter(json_bytes)
|
809 - | .peekable();
|
810 - | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
811 - | .expect("well formed json")
|
812 - | }),
|
813 - | }),
|
814 - | top_level_default: "hi".to_owned(),
|
815 - | other_top_level_default: 0,
|
816 - | client_optional_defaults: ::std::option::Option::None,
|
817 - | };
|
818 - | ::pretty_assertions::assert_eq!(input, expected);
|
819 - | let output = crate::output::OperationWithDefaultsOutput {
|
820 - | default_string: "".to_owned(),
|
821 - | default_boolean: false,
|
822 - | default_list: vec![],
|
823 - | default_document_map: {
|
824 - | let json_bytes = br#"{}"#;
|
825 - | let mut tokens =
|
826 - | ::aws_smithy_json::deserialize::json_token_iter(json_bytes)
|
827 - | .peekable();
|
828 - | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
829 - | .expect("well formed json")
|
830 - | },
|
831 - | default_document_string: {
|
832 - | let json_bytes = br#"{}"#;
|
833 - | let mut tokens =
|
834 - | ::aws_smithy_json::deserialize::json_token_iter(json_bytes)
|
835 - | .peekable();
|
836 - | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
837 - | .expect("well formed json")
|
838 - | },
|
839 - | default_document_boolean: {
|
840 - | let json_bytes = br#"{}"#;
|
841 - | let mut tokens =
|
842 - | ::aws_smithy_json::deserialize::json_token_iter(json_bytes)
|
843 - | .peekable();
|
844 - | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
845 - | .expect("well formed json")
|
846 - | },
|
847 - | default_document_list: {
|
848 - | let json_bytes = br#"{}"#;
|
849 - | let mut tokens =
|
850 - | ::aws_smithy_json::deserialize::json_token_iter(json_bytes)
|
851 - | .peekable();
|
852 - | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
853 - | .expect("well formed json")
|
854 - | },
|
855 - | default_timestamp: ::aws_smithy_types::DateTime::from_fractional_secs(
|
856 - | 0, 0_f64,
|
682 + | double_value: ::std::option::Option::Some(
|
683 + | <f64 as ::aws_smithy_types::primitive::Parse>::parse_smithy_primitive(
|
684 + | "NaN",
|
685 + | )
|
686 + | .expect("invalid string for number"),
|
857 687 | ),
|
858 - | default_blob: ::aws_smithy_types::Blob::new(""),
|
859 - | default_byte: 0,
|
860 - | default_short: 0,
|
861 - | default_integer: 0,
|
862 - | default_long: 0,
|
863 - | default_float: 0_f32,
|
864 - | default_double: 0_f64,
|
865 - | default_map: ::std::collections::HashMap::new(),
|
866 - | default_enum: ""
|
867 - | .parse::<crate::model::TestEnum>()
|
868 - | .expect("static value validated to member"),
|
869 - | default_int_enum: 0,
|
870 - | empty_string: "".to_owned(),
|
871 - | false_boolean: false,
|
872 - | empty_blob: ::aws_smithy_types::Blob::new(""),
|
873 - | zero_byte: 0,
|
874 - | zero_short: 0,
|
875 - | zero_integer: 0,
|
876 - | zero_long: 0,
|
877 - | zero_float: 0_f32,
|
878 - | zero_double: 0_f64,
|
879 - | default_null_document: ::std::option::Option::Some({
|
880 - | let json_bytes = br#"null"#;
|
881 - | let mut tokens =
|
882 - | ::aws_smithy_json::deserialize::json_token_iter(json_bytes)
|
883 - | .peekable();
|
884 - | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
885 - | .expect("well formed json")
|
886 - | }),
|
887 - | };
|
888 - | Ok(output)
|
889 688 | };
|
890 - | sender.send(()).await.expect("receiver dropped early");
|
891 - | result
|
892 - | }
|
893 - | })
|
894 - | .build_unchecked();
|
689 + | assert!(
|
690 + | input.float_value.float_equals(&expected.float_value),
|
691 + | "Unexpected value for `float_value` {:?} vs. {:?}",
|
692 + | expected.float_value,
|
693 + | input.float_value
|
694 + | );
|
695 + | assert!(
|
696 + | input.double_value.float_equals(&expected.double_value),
|
697 + | "Unexpected value for `double_value` {:?} vs. {:?}",
|
698 + | expected.double_value,
|
699 + | input.double_value
|
700 + | );
|
701 + | let output = crate::output::SimpleScalarPropertiesOutput {
|
702 + | float_value: ::std::option::Option::None,
|
703 + | double_value: ::std::option::Option::None,
|
704 + | };
|
705 + | output
|
706 + | };
|
707 + | sender.send(()).await.expect("receiver dropped early");
|
708 + | result
|
709 + | }
|
710 + | })
|
711 + | .build_unchecked();
|
895 712 | let http_response = ::tower::ServiceExt::oneshot(service, http_request)
|
896 713 | .await
|
897 714 | .expect("unable to make an HTTP request");
|
898 715 | assert!(
|
899 716 | receiver.recv().await.is_some(),
|
900 717 | "we expected operation handler to be invoked but it was not entered"
|
901 718 | );
|
902 719 | }
|
903 720 |
|
904 - | /// Server populates default values in response when missing in params.
|
905 - | /// Test ID: AwsJson10ServerPopulatesDefaultsInResponseWhenMissingInParams
|
721 + | /// Supports handling Infinity float values.
|
722 + | /// Test ID: AwsJson10SupportsInfinityFloatInputs
|
906 723 | #[::tokio::test]
|
907 724 | #[::tracing_test::traced_test]
|
908 - | #[should_panic]
|
909 - | async fn aws_json10_server_populates_defaults_in_response_when_missing_in_params_response() {
|
910 - | let output = crate::output::OperationWithDefaultsOutput {
|
911 - | default_string: "".to_owned(),
|
912 - | default_boolean: false,
|
913 - | default_list: vec![],
|
914 - | default_document_map: {
|
915 - | let json_bytes = br#"{}"#;
|
916 - | let mut tokens =
|
917 - | ::aws_smithy_json::deserialize::json_token_iter(json_bytes).peekable();
|
918 - | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
919 - | .expect("well formed json")
|
920 - | },
|
921 - | default_document_string: {
|
922 - | let json_bytes = br#"{}"#;
|
923 - | let mut tokens =
|
924 - | ::aws_smithy_json::deserialize::json_token_iter(json_bytes).peekable();
|
925 - | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
926 - | .expect("well formed json")
|
927 - | },
|
928 - | default_document_boolean: {
|
929 - | let json_bytes = br#"{}"#;
|
930 - | let mut tokens =
|
931 - | ::aws_smithy_json::deserialize::json_token_iter(json_bytes).peekable();
|
932 - | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
933 - | .expect("well formed json")
|
934 - | },
|
935 - | default_document_list: {
|
936 - | let json_bytes = br#"{}"#;
|
937 - | let mut tokens =
|
938 - | ::aws_smithy_json::deserialize::json_token_iter(json_bytes).peekable();
|
939 - | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
940 - | .expect("well formed json")
|
941 - | },
|
942 - | default_timestamp: ::aws_smithy_types::DateTime::from_fractional_secs(0, 0_f64),
|
943 - | default_blob: ::aws_smithy_types::Blob::new(""),
|
944 - | default_byte: 0,
|
945 - | default_short: 0,
|
946 - | default_integer: 0,
|
947 - | default_long: 0,
|
948 - | default_float: 0_f32,
|
949 - | default_double: 0_f64,
|
950 - | default_map: ::std::collections::HashMap::new(),
|
951 - | default_enum: ""
|
952 - | .parse::<crate::model::TestEnum>()
|
953 - | .expect("static value validated to member"),
|
954 - | default_int_enum: 0,
|
955 - | empty_string: "".to_owned(),
|
956 - | false_boolean: false,
|
957 - | empty_blob: ::aws_smithy_types::Blob::new(""),
|
958 - | zero_byte: 0,
|
959 - | zero_short: 0,
|
960 - | zero_integer: 0,
|
961 - | zero_long: 0,
|
962 - | zero_float: 0_f32,
|
963 - | zero_double: 0_f64,
|
964 - | default_null_document: ::std::option::Option::Some({
|
965 - | let json_bytes = br#"null"#;
|
966 - | let mut tokens =
|
967 - | ::aws_smithy_json::deserialize::json_token_iter(json_bytes).peekable();
|
968 - | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
969 - | .expect("well formed json")
|
970 - | }),
|
725 + | async fn aws_json10_supports_infinity_float_inputs_request() {
|
726 + | #[allow(unused_mut)]
|
727 + | let mut http_request = ::http_1x::Request::builder()
|
728 + | .uri("/")
|
729 + | .method("POST")
|
730 + | .header("Content-Type", "application/x-amz-json-1.0")
|
731 + | .header("X-Amz-Target", "JsonRpc10.SimpleScalarProperties")
|
732 + | .body(::aws_smithy_http_server::body::boxed(::http_body_util::Full::new(
|
733 + | ::bytes::Bytes::copy_from_slice(
|
734 + | &::aws_smithy_protocol_test::decode_body_data("{\n \"floatValue\": \"Infinity\",\n \"doubleValue\": \"Infinity\"\n}".as_bytes(), ::aws_smithy_protocol_test::MediaType::from("application/json"))
|
735 + | )
|
736 + | ))).unwrap();
|
737 + | #[allow(unused_mut)]
|
738 + | let (sender, mut receiver) = ::tokio::sync::mpsc::channel(1);
|
739 + | let config = crate::service::JsonRpc10Config::builder().build();
|
740 + | let service = crate::service::JsonRpc10::builder::<
|
741 + | ::aws_smithy_http_server::body::BoxBody,
|
742 + | _,
|
743 + | _,
|
744 + | _,
|
745 + | >(config)
|
746 + | .simple_scalar_properties(move |input: crate::input::SimpleScalarPropertiesInput| {
|
747 + | let sender = sender.clone();
|
748 + | async move {
|
749 + | let result = {
|
750 + | use ::aws_smithy_protocol_test::FloatEquals;
|
751 + | let expected = crate::input::SimpleScalarPropertiesInput {
|
752 + | float_value: ::std::option::Option::Some(
|
753 + | <f32 as ::aws_smithy_types::primitive::Parse>::parse_smithy_primitive(
|
754 + | "Infinity",
|
755 + | )
|
756 + | .expect("invalid string for number"),
|
757 + | ),
|
758 + | double_value: ::std::option::Option::Some(
|
759 + | <f64 as ::aws_smithy_types::primitive::Parse>::parse_smithy_primitive(
|
760 + | "Infinity",
|
761 + | )
|
762 + | .expect("invalid string for number"),
|
763 + | ),
|
764 + | };
|
765 + | assert!(
|
766 + | input.float_value.float_equals(&expected.float_value),
|
767 + | "Unexpected value for `float_value` {:?} vs. {:?}",
|
768 + | expected.float_value,
|
769 + | input.float_value
|
770 + | );
|
771 + | assert!(
|
772 + | input.double_value.float_equals(&expected.double_value),
|
773 + | "Unexpected value for `double_value` {:?} vs. {:?}",
|
774 + | expected.double_value,
|
775 + | input.double_value
|
776 + | );
|
777 + | let output = crate::output::SimpleScalarPropertiesOutput {
|
778 + | float_value: ::std::option::Option::None,
|
779 + | double_value: ::std::option::Option::None,
|
780 + | };
|
781 + | output
|
782 + | };
|
783 + | sender.send(()).await.expect("receiver dropped early");
|
784 + | result
|
785 + | }
|
786 + | })
|
787 + | .build_unchecked();
|
788 + | let http_response = ::tower::ServiceExt::oneshot(service, http_request)
|
789 + | .await
|
790 + | .expect("unable to make an HTTP request");
|
791 + | assert!(
|
792 + | receiver.recv().await.is_some(),
|
793 + | "we expected operation handler to be invoked but it was not entered"
|
794 + | );
|
795 + | }
|
796 + |
|
797 + | /// Supports handling -Infinity float values.
|
798 + | /// Test ID: AwsJson10SupportsNegativeInfinityFloatInputs
|
799 + | #[::tokio::test]
|
800 + | #[::tracing_test::traced_test]
|
801 + | async fn aws_json10_supports_negative_infinity_float_inputs_request() {
|
802 + | #[allow(unused_mut)]
|
803 + | let mut http_request = ::http_1x::Request::builder()
|
804 + | .uri("/")
|
805 + | .method("POST")
|
806 + | .header("Content-Type", "application/x-amz-json-1.0")
|
807 + | .header("X-Amz-Target", "JsonRpc10.SimpleScalarProperties")
|
808 + | .body(::aws_smithy_http_server::body::boxed(::http_body_util::Full::new(
|
809 + | ::bytes::Bytes::copy_from_slice(
|
810 + | &::aws_smithy_protocol_test::decode_body_data("{\n \"floatValue\": \"-Infinity\",\n \"doubleValue\": \"-Infinity\"\n}".as_bytes(), ::aws_smithy_protocol_test::MediaType::from("application/json"))
|
811 + | )
|
812 + | ))).unwrap();
|
813 + | #[allow(unused_mut)]
|
814 + | let (sender, mut receiver) = ::tokio::sync::mpsc::channel(1);
|
815 + | let config = crate::service::JsonRpc10Config::builder().build();
|
816 + | let service = crate::service::JsonRpc10::builder::<
|
817 + | ::aws_smithy_http_server::body::BoxBody,
|
818 + | _,
|
819 + | _,
|
820 + | _,
|
821 + | >(config)
|
822 + | .simple_scalar_properties(move |input: crate::input::SimpleScalarPropertiesInput| {
|
823 + | let sender = sender.clone();
|
824 + | async move {
|
825 + | let result = {
|
826 + | use ::aws_smithy_protocol_test::FloatEquals;
|
827 + | let expected = crate::input::SimpleScalarPropertiesInput {
|
828 + | float_value: ::std::option::Option::Some(
|
829 + | <f32 as ::aws_smithy_types::primitive::Parse>::parse_smithy_primitive(
|
830 + | "-Infinity",
|
831 + | )
|
832 + | .expect("invalid string for number"),
|
833 + | ),
|
834 + | double_value: ::std::option::Option::Some(
|
835 + | <f64 as ::aws_smithy_types::primitive::Parse>::parse_smithy_primitive(
|
836 + | "-Infinity",
|
837 + | )
|
838 + | .expect("invalid string for number"),
|
839 + | ),
|
840 + | };
|
841 + | assert!(
|
842 + | input.float_value.float_equals(&expected.float_value),
|
843 + | "Unexpected value for `float_value` {:?} vs. {:?}",
|
844 + | expected.float_value,
|
845 + | input.float_value
|
846 + | );
|
847 + | assert!(
|
848 + | input.double_value.float_equals(&expected.double_value),
|
849 + | "Unexpected value for `double_value` {:?} vs. {:?}",
|
850 + | expected.double_value,
|
851 + | input.double_value
|
852 + | );
|
853 + | let output = crate::output::SimpleScalarPropertiesOutput {
|
854 + | float_value: ::std::option::Option::None,
|
855 + | double_value: ::std::option::Option::None,
|
856 + | };
|
857 + | output
|
858 + | };
|
859 + | sender.send(()).await.expect("receiver dropped early");
|
860 + | result
|
861 + | }
|
862 + | })
|
863 + | .build_unchecked();
|
864 + | let http_response = ::tower::ServiceExt::oneshot(service, http_request)
|
865 + | .await
|
866 + | .expect("unable to make an HTTP request");
|
867 + | assert!(
|
868 + | receiver.recv().await.is_some(),
|
869 + | "we expected operation handler to be invoked but it was not entered"
|
870 + | );
|
871 + | }
|
872 + |
|
873 + | /// Supports handling NaN float values.
|
874 + | /// Test ID: AwsJson10SupportsNaNFloatInputs
|
875 + | #[::tokio::test]
|
876 + | #[::tracing_test::traced_test]
|
877 + | async fn aws_json10_supports_na_n_float_inputs_response() {
|
878 + | let output = crate::output::SimpleScalarPropertiesOutput {
|
879 + | float_value: ::std::option::Option::Some(
|
880 + | <f32 as ::aws_smithy_types::primitive::Parse>::parse_smithy_primitive("NaN")
|
881 + | .expect("invalid string for number"),
|
882 + | ),
|
883 + | double_value: ::std::option::Option::Some(
|
884 + | <f64 as ::aws_smithy_types::primitive::Parse>::parse_smithy_primitive("NaN")
|
885 + | .expect("invalid string for number"),
|
886 + | ),
|
971 887 | };
|
972 888 | use ::aws_smithy_http_server::response::IntoResponse;
|
973 889 | let http_response = output.into_response();
|
974 890 | ::pretty_assertions::assert_eq!(
|
975 891 | ::http_1x::StatusCode::from_u16(200).expect("invalid expected HTTP status code"),
|
976 892 | http_response.status()
|
977 893 | );
|
978 894 | let expected_headers = [("Content-Type", "application/x-amz-json-1.0")];
|
979 895 | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_headers(
|
980 896 | http_response.headers(),
|
981 897 | expected_headers,
|
982 898 | ));
|
983 899 | use ::http_body_util::BodyExt;
|
984 900 | let body = http_response
|
985 901 | .into_body()
|
986 902 | .collect()
|
987 903 | .await
|
988 904 | .expect("unable to collect body")
|
989 905 | .to_bytes();
|
990 - | ::aws_smithy_protocol_test::assert_ok(
|
991 - | ::aws_smithy_protocol_test::validate_body(&body, "{\n \"defaultString\": \"hi\",\n \"defaultBoolean\": true,\n \"defaultList\": [],\n \"defaultDocumentMap\": {},\n \"defaultDocumentString\": \"hi\",\n \"defaultDocumentBoolean\": true,\n \"defaultDocumentList\": [],\n \"defaultTimestamp\": 0,\n \"defaultBlob\": \"YWJj\",\n \"defaultByte\": 1,\n \"defaultShort\": 1,\n \"defaultInteger\": 10,\n \"defaultLong\": 100,\n \"defaultFloat\": 1.0,\n \"defaultDouble\": 1.0,\n \"defaultMap\": {},\n \"defaultEnum\": \"FOO\",\n \"defaultIntEnum\": 1,\n \"emptyString\": \"\",\n \"falseBoolean\": false,\n \"emptyBlob\": \"\",\n \"zeroByte\": 0,\n \"zeroShort\": 0,\n \"zeroInteger\": 0,\n \"zeroLong\": 0,\n \"zeroFloat\": 0.0,\n \"zeroDouble\": 0.0\n}", ::aws_smithy_protocol_test::MediaType::from("application/json"))
|
992 - | );
|
993 - | }
|
994 - | }
|
995 - |
|
996 - | ::pin_project_lite::pin_project! {
|
997 - | /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the
|
998 - | /// [`ContentTypeParametersInput`](crate::input::ContentTypeParametersInput) using modelled bindings.
|
999 - | pub struct ContentTypeParametersInputFuture {
|
1000 - | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::ContentTypeParametersInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
1001 - | }
|
1002 - | }
|
1003 - |
|
1004 - | impl std::future::Future for ContentTypeParametersInputFuture {
|
1005 - | type Output = Result<
|
1006 - | crate::input::ContentTypeParametersInput,
|
1007 - | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError,
|
1008 - | >;
|
1009 - |
|
1010 - | fn poll(
|
1011 - | self: std::pin::Pin<&mut Self>,
|
1012 - | cx: &mut std::task::Context<'_>,
|
1013 - | ) -> std::task::Poll<Self::Output> {
|
1014 - | let this = self.project();
|
1015 - | this.inner.as_mut().poll(cx)
|
1016 - | }
|
1017 - | }
|
1018 - |
|
1019 - | impl<B>
|
1020 - | ::aws_smithy_http_server::request::FromRequest<
|
1021 - | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
1022 - | B,
|
1023 - | > for crate::input::ContentTypeParametersInput
|
1024 - | where
|
1025 - | B: ::aws_smithy_http_server::body::HttpBody + Send,
|
1026 - | B: 'static,
|
1027 - |
|
1028 - | B::Data: Send,
|
1029 - | ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection:
|
1030 - | From<<B as ::aws_smithy_http_server::body::HttpBody>::Error>,
|
1031 - | {
|
1032 - | type Rejection = ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError;
|
1033 - | type Future = ContentTypeParametersInputFuture;
|
1034 - |
|
1035 - | fn from_request(request: ::http_1x::Request<B>) -> Self::Future {
|
1036 - | let fut = async move {
|
1037 - | if !::aws_smithy_http_server::protocol::accept_header_classifier(
|
1038 - | request.headers(),
|
1039 - | &crate::mimes::CONTENT_TYPE_APPLICATION_X_AMZ_JSON_1_0,
|
1040 - | ) {
|
1041 - | return Err(::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection::NotAcceptable);
|
1042 - | }
|
1043 - | crate::protocol_serde::shape_content_type_parameters::de_content_type_parameters_http_request(request)
|
1044 - | .await
|
1045 - | };
|
1046 - | use ::futures_util::future::TryFutureExt;
|
1047 - | let fut = fut.map_err(
|
1048 - | |e: ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection| {
|
1049 - | ::tracing::debug!(error = %e, "failed to deserialize request");
|
1050 - | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e)
|
1051 - | },
|
1052 - | );
|
1053 - | ContentTypeParametersInputFuture {
|
1054 - | inner: Box::pin(fut),
|
1055 - | }
|
1056 - | }
|
1057 - | }
|
1058 - | impl
|
1059 - | ::aws_smithy_http_server::response::IntoResponse<
|
1060 - | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
1061 - | > for crate::output::ContentTypeParametersOutput
|
1062 - | {
|
1063 - | fn into_response(self) -> ::aws_smithy_http_server::response::Response {
|
1064 - | match crate::protocol_serde::shape_content_type_parameters::ser_content_type_parameters_http_response(self) {
|
1065 - | Ok(response) => response,
|
1066 - | Err(e) => {
|
1067 - | ::tracing::error!(error = %e, "failed to serialize response");
|
1068 - | ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0>::into_response(::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e))
|
1069 - | }
|
1070 - | }
|
906 + | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_body(
|
907 + | &body,
|
908 + | "{\n \"floatValue\": \"NaN\",\n \"doubleValue\": \"NaN\"\n}",
|
909 + | ::aws_smithy_protocol_test::MediaType::from("application/json"),
|
910 + | ));
|
1071 911 | }
|
1072 - | }
|
1073 912 |
|
1074 - | #[allow(unreachable_code, unused_variables)]
|
1075 - | #[cfg(test)]
|
1076 - | mod content_type_parameters_test {
|
1077 - |
|
1078 - | /// A server should ignore parameters added to the content type
|
1079 - | /// Test ID: AwsJson10MustSupportParametersInContentType
|
913 + | /// Supports handling Infinity float values.
|
914 + | /// Test ID: AwsJson10SupportsInfinityFloatInputs
|
1080 915 | #[::tokio::test]
|
1081 916 | #[::tracing_test::traced_test]
|
1082 - | async fn aws_json10_must_support_parameters_in_content_type_request() {
|
1083 - | #[allow(unused_mut)]
|
1084 - | let mut http_request = ::http_1x::Request::builder()
|
1085 - | .uri("/")
|
1086 - | .method("POST")
|
1087 - | .header("Content-Type", "application/x-amz-json-1.0; charset=utf-8")
|
1088 - | .header("X-Amz-Target", "JsonRpc10.ContentTypeParameters")
|
1089 - | .body(::aws_smithy_http_server::body::boxed(
|
1090 - | ::http_body_util::Full::new(::bytes::Bytes::copy_from_slice(
|
1091 - | &::aws_smithy_protocol_test::decode_body_data(
|
1092 - | "{\"value\":5}".as_bytes(),
|
1093 - | ::aws_smithy_protocol_test::MediaType::from("application/json"),
|
917 + | async fn aws_json10_supports_infinity_float_inputs_response() {
|
918 + | let output = crate::output::SimpleScalarPropertiesOutput {
|
919 + | float_value: ::std::option::Option::Some(
|
920 + | <f32 as ::aws_smithy_types::primitive::Parse>::parse_smithy_primitive("Infinity")
|
921 + | .expect("invalid string for number"),
|
922 + | ),
|
923 + | double_value: ::std::option::Option::Some(
|
924 + | <f64 as ::aws_smithy_types::primitive::Parse>::parse_smithy_primitive("Infinity")
|
925 + | .expect("invalid string for number"),
|
1094 926 | ),
|
1095 - | )),
|
1096 - | ))
|
1097 - | .unwrap();
|
1098 - | #[allow(unused_mut)]
|
1099 - | let (sender, mut receiver) = ::tokio::sync::mpsc::channel(1);
|
1100 - | let config = crate::service::JsonRpc10Config::builder().build();
|
1101 - | let service =
|
1102 - | crate::service::JsonRpc10::builder::<::aws_smithy_http_server::body::BoxBody, _, _, _>(
|
1103 - | config,
|
1104 - | )
|
1105 - | .content_type_parameters(move |input: crate::input::ContentTypeParametersInput| {
|
1106 - | let sender = sender.clone();
|
1107 - | async move {
|
1108 - | let result = {
|
1109 - | let expected = crate::input::ContentTypeParametersInput {
|
1110 - | value: ::std::option::Option::Some(5),
|
1111 - | };
|
1112 - | ::pretty_assertions::assert_eq!(input, expected);
|
1113 - | let output = crate::output::ContentTypeParametersOutput {};
|
1114 - | output
|
1115 927 | };
|
1116 - | sender.send(()).await.expect("receiver dropped early");
|
1117 - | result
|
1118 - | }
|
1119 - | })
|
1120 - | .build_unchecked();
|
1121 - | let http_response = ::tower::ServiceExt::oneshot(service, http_request)
|
1122 - | .await
|
1123 - | .expect("unable to make an HTTP request");
|
1124 - | assert!(
|
1125 - | receiver.recv().await.is_some(),
|
1126 - | "we expected operation handler to be invoked but it was not entered"
|
928 + | use ::aws_smithy_http_server::response::IntoResponse;
|
929 + | let http_response = output.into_response();
|
930 + | ::pretty_assertions::assert_eq!(
|
931 + | ::http_1x::StatusCode::from_u16(200).expect("invalid expected HTTP status code"),
|
932 + | http_response.status()
|
1127 933 | );
|
1128 - | }
|
1129 - | }
|
1130 - |
|
1131 - | ::pin_project_lite::pin_project! {
|
1132 - | /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the
|
1133 - | /// [`PutWithContentEncodingInput`](crate::input::PutWithContentEncodingInput) using modelled bindings.
|
1134 - | pub struct PutWithContentEncodingInputFuture {
|
1135 - | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::PutWithContentEncodingInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
1136 - | }
|
1137 - | }
|
1138 - |
|
1139 - | impl std::future::Future for PutWithContentEncodingInputFuture {
|
1140 - | type Output = Result<
|
1141 - | crate::input::PutWithContentEncodingInput,
|
1142 - | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError,
|
1143 - | >;
|
1144 - |
|
1145 - | fn poll(
|
1146 - | self: std::pin::Pin<&mut Self>,
|
1147 - | cx: &mut std::task::Context<'_>,
|
1148 - | ) -> std::task::Poll<Self::Output> {
|
1149 - | let this = self.project();
|
1150 - | this.inner.as_mut().poll(cx)
|
1151 - | }
|
1152 - | }
|
1153 - |
|
1154 - | impl<B>
|
1155 - | ::aws_smithy_http_server::request::FromRequest<
|
1156 - | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
1157 - | B,
|
1158 - | > for crate::input::PutWithContentEncodingInput
|
1159 - | where
|
1160 - | B: ::aws_smithy_http_server::body::HttpBody + Send,
|
1161 - | B: 'static,
|
1162 - |
|
1163 - | B::Data: Send,
|
1164 - | ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection:
|
1165 - | From<<B as ::aws_smithy_http_server::body::HttpBody>::Error>,
|
1166 - | {
|
1167 - | type Rejection = ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError;
|
1168 - | type Future = PutWithContentEncodingInputFuture;
|
1169 - |
|
1170 - | fn from_request(request: ::http_1x::Request<B>) -> Self::Future {
|
1171 - | let fut = async move {
|
1172 - | if !::aws_smithy_http_server::protocol::accept_header_classifier(
|
1173 - | request.headers(),
|
1174 - | &crate::mimes::CONTENT_TYPE_APPLICATION_X_AMZ_JSON_1_0,
|
1175 - | ) {
|
1176 - | return Err(::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection::NotAcceptable);
|
1177 - | }
|
1178 - | crate::protocol_serde::shape_put_with_content_encoding::de_put_with_content_encoding_http_request(request)
|
934 + | let expected_headers = [("Content-Type", "application/x-amz-json-1.0")];
|
935 + | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_headers(
|
936 + | http_response.headers(),
|
937 + | expected_headers,
|
938 + | ));
|
939 + | use ::http_body_util::BodyExt;
|
940 + | let body = http_response
|
941 + | .into_body()
|
942 + | .collect()
|
1179 943 | .await
|
1180 - | };
|
1181 - | use ::futures_util::future::TryFutureExt;
|
1182 - | let fut = fut.map_err(
|
1183 - | |e: ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection| {
|
1184 - | ::tracing::debug!(error = %e, "failed to deserialize request");
|
1185 - | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e)
|
1186 - | },
|
1187 - | );
|
1188 - | PutWithContentEncodingInputFuture {
|
1189 - | inner: Box::pin(fut),
|
1190 - | }
|
1191 - | }
|
1192 - | }
|
1193 - | impl
|
1194 - | ::aws_smithy_http_server::response::IntoResponse<
|
1195 - | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
1196 - | > for crate::output::PutWithContentEncodingOutput
|
1197 - | {
|
1198 - | fn into_response(self) -> ::aws_smithy_http_server::response::Response {
|
1199 - | match crate::protocol_serde::shape_put_with_content_encoding::ser_put_with_content_encoding_http_response(self) {
|
1200 - | Ok(response) => response,
|
1201 - | Err(e) => {
|
1202 - | ::tracing::error!(error = %e, "failed to serialize response");
|
1203 - | ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0>::into_response(::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e))
|
1204 - | }
|
1205 - | }
|
1206 - | }
|
1207 - | }
|
1208 - |
|
1209 - | ::pin_project_lite::pin_project! {
|
1210 - | /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the
|
1211 - | /// [`HostWithPathOperationInput`](crate::input::HostWithPathOperationInput) using modelled bindings.
|
1212 - | pub struct HostWithPathOperationInputFuture {
|
1213 - | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::HostWithPathOperationInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
1214 - | }
|
1215 - | }
|
1216 - |
|
1217 - | impl std::future::Future for HostWithPathOperationInputFuture {
|
1218 - | type Output = Result<
|
1219 - | crate::input::HostWithPathOperationInput,
|
1220 - | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError,
|
1221 - | >;
|
1222 - |
|
1223 - | fn poll(
|
1224 - | self: std::pin::Pin<&mut Self>,
|
1225 - | cx: &mut std::task::Context<'_>,
|
1226 - | ) -> std::task::Poll<Self::Output> {
|
1227 - | let this = self.project();
|
1228 - | this.inner.as_mut().poll(cx)
|
1229 - | }
|
1230 - | }
|
1231 - |
|
1232 - | impl<B>
|
1233 - | ::aws_smithy_http_server::request::FromRequest<
|
1234 - | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
1235 - | B,
|
1236 - | > for crate::input::HostWithPathOperationInput
|
1237 - | where
|
1238 - | B: ::aws_smithy_http_server::body::HttpBody + Send,
|
1239 - | B: 'static,
|
1240 - |
|
1241 - | B::Data: Send,
|
1242 - | ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection:
|
1243 - | From<<B as ::aws_smithy_http_server::body::HttpBody>::Error>,
|
1244 - | {
|
1245 - | type Rejection = ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError;
|
1246 - | type Future = HostWithPathOperationInputFuture;
|
1247 - |
|
1248 - | fn from_request(request: ::http_1x::Request<B>) -> Self::Future {
|
1249 - | let fut = async move {
|
1250 - | if !::aws_smithy_http_server::protocol::accept_header_classifier(
|
1251 - | request.headers(),
|
1252 - | &crate::mimes::CONTENT_TYPE_APPLICATION_X_AMZ_JSON_1_0,
|
1253 - | ) {
|
1254 - | return Err(::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection::NotAcceptable);
|
944 + | .expect("unable to collect body")
|
945 + | .to_bytes();
|
946 + | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_body(
|
947 + | &body,
|
948 + | "{\n \"floatValue\": \"Infinity\",\n \"doubleValue\": \"Infinity\"\n}",
|
949 + | ::aws_smithy_protocol_test::MediaType::from("application/json"),
|
950 + | ));
|
1255 951 | }
|
1256 - | crate::protocol_serde::shape_host_with_path_operation::de_host_with_path_operation_http_request(request)
|
1257 - | .await
|
952 + |
|
953 + | /// Supports handling -Infinity float values.
|
954 + | /// Test ID: AwsJson10SupportsNegativeInfinityFloatInputs
|
955 + | #[::tokio::test]
|
956 + | #[::tracing_test::traced_test]
|
957 + | async fn aws_json10_supports_negative_infinity_float_inputs_response() {
|
958 + | let output = crate::output::SimpleScalarPropertiesOutput {
|
959 + | float_value: ::std::option::Option::Some(
|
960 + | <f32 as ::aws_smithy_types::primitive::Parse>::parse_smithy_primitive("-Infinity")
|
961 + | .expect("invalid string for number"),
|
962 + | ),
|
963 + | double_value: ::std::option::Option::Some(
|
964 + | <f64 as ::aws_smithy_types::primitive::Parse>::parse_smithy_primitive("-Infinity")
|
965 + | .expect("invalid string for number"),
|
966 + | ),
|
1258 967 | };
|
1259 - | use ::futures_util::future::TryFutureExt;
|
1260 - | let fut = fut.map_err(
|
1261 - | |e: ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection| {
|
1262 - | ::tracing::debug!(error = %e, "failed to deserialize request");
|
1263 - | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e)
|
1264 - | },
|
968 + | use ::aws_smithy_http_server::response::IntoResponse;
|
969 + | let http_response = output.into_response();
|
970 + | ::pretty_assertions::assert_eq!(
|
971 + | ::http_1x::StatusCode::from_u16(200).expect("invalid expected HTTP status code"),
|
972 + | http_response.status()
|
1265 973 | );
|
1266 - | HostWithPathOperationInputFuture {
|
1267 - | inner: Box::pin(fut),
|
1268 - | }
|
1269 - | }
|
1270 - | }
|
1271 - | impl
|
1272 - | ::aws_smithy_http_server::response::IntoResponse<
|
1273 - | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
1274 - | > for crate::output::HostWithPathOperationOutput
|
1275 - | {
|
1276 - | fn into_response(self) -> ::aws_smithy_http_server::response::Response {
|
1277 - | match crate::protocol_serde::shape_host_with_path_operation::ser_host_with_path_operation_http_response(self) {
|
1278 - | Ok(response) => response,
|
1279 - | Err(e) => {
|
1280 - | ::tracing::error!(error = %e, "failed to serialize response");
|
1281 - | ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0>::into_response(::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e))
|
1282 - | }
|
1283 - | }
|
974 + | let expected_headers = [("Content-Type", "application/x-amz-json-1.0")];
|
975 + | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_headers(
|
976 + | http_response.headers(),
|
977 + | expected_headers,
|
978 + | ));
|
979 + | use ::http_body_util::BodyExt;
|
980 + | let body = http_response
|
981 + | .into_body()
|
982 + | .collect()
|
983 + | .await
|
984 + | .expect("unable to collect body")
|
985 + | .to_bytes();
|
986 + | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_body(
|
987 + | &body,
|
988 + | "{\n \"floatValue\": \"-Infinity\",\n \"doubleValue\": \"-Infinity\"\n}",
|
989 + | ::aws_smithy_protocol_test::MediaType::from("application/json"),
|
990 + | ));
|
1284 991 | }
|
1285 992 | }
|
1286 993 |
|
1287 994 | ::pin_project_lite::pin_project! {
|
1288 995 | /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the
|
1289 - | /// [`EndpointWithHostLabelOperationInput`](crate::input::EndpointWithHostLabelOperationInput) using modelled bindings.
|
1290 - | pub struct EndpointWithHostLabelOperationInputFuture {
|
1291 - | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::EndpointWithHostLabelOperationInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
996 + | /// [`GreetingWithErrorsInput`](crate::input::GreetingWithErrorsInput) using modelled bindings.
|
997 + | pub struct GreetingWithErrorsInputFuture {
|
998 + | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::GreetingWithErrorsInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
1292 999 | }
|
1293 1000 | }
|
1294 1001 |
|
1295 - | impl std::future::Future for EndpointWithHostLabelOperationInputFuture {
|
1002 + | impl std::future::Future for GreetingWithErrorsInputFuture {
|
1296 1003 | type Output = Result<
|
1297 - | crate::input::EndpointWithHostLabelOperationInput,
|
1004 + | crate::input::GreetingWithErrorsInput,
|
1298 1005 | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError,
|
1299 1006 | >;
|
1300 1007 |
|
1301 1008 | fn poll(
|
1302 1009 | self: std::pin::Pin<&mut Self>,
|
1303 1010 | cx: &mut std::task::Context<'_>,
|
1304 1011 | ) -> std::task::Poll<Self::Output> {
|
1305 1012 | let this = self.project();
|
1306 1013 | this.inner.as_mut().poll(cx)
|
1307 1014 | }
|
1308 1015 | }
|
1309 1016 |
|
1310 1017 | impl<B>
|
1311 1018 | ::aws_smithy_http_server::request::FromRequest<
|
1312 1019 | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
1313 1020 | B,
|
1314 - | > for crate::input::EndpointWithHostLabelOperationInput
|
1021 + | > for crate::input::GreetingWithErrorsInput
|
1315 1022 | where
|
1316 1023 | B: ::aws_smithy_http_server::body::HttpBody + Send,
|
1317 1024 | B: 'static,
|
1318 1025 |
|
1319 1026 | B::Data: Send,
|
1320 1027 | ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection:
|
1321 1028 | From<<B as ::aws_smithy_http_server::body::HttpBody>::Error>,
|
1322 1029 | {
|
1323 1030 | type Rejection = ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError;
|
1324 - | type Future = EndpointWithHostLabelOperationInputFuture;
|
1031 + | type Future = GreetingWithErrorsInputFuture;
|
1325 1032 |
|
1326 1033 | fn from_request(request: ::http_1x::Request<B>) -> Self::Future {
|
1327 1034 | let fut = async move {
|
1328 1035 | if !::aws_smithy_http_server::protocol::accept_header_classifier(
|
1329 1036 | request.headers(),
|
1330 1037 | &crate::mimes::CONTENT_TYPE_APPLICATION_X_AMZ_JSON_1_0,
|
1331 1038 | ) {
|
1332 1039 | return Err(::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection::NotAcceptable);
|
1333 1040 | }
|
1334 - | crate::protocol_serde::shape_endpoint_with_host_label_operation::de_endpoint_with_host_label_operation_http_request(request)
|
1041 + | crate::protocol_serde::shape_greeting_with_errors::de_greeting_with_errors_http_request(
|
1042 + | request,
|
1043 + | )
|
1335 1044 | .await
|
1336 1045 | };
|
1337 1046 | use ::futures_util::future::TryFutureExt;
|
1338 1047 | let fut = fut.map_err(
|
1339 1048 | |e: ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection| {
|
1340 1049 | ::tracing::debug!(error = %e, "failed to deserialize request");
|
1341 1050 | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e)
|
1342 1051 | },
|
1343 1052 | );
|
1344 - | EndpointWithHostLabelOperationInputFuture {
|
1053 + | GreetingWithErrorsInputFuture {
|
1345 1054 | inner: Box::pin(fut),
|
1346 1055 | }
|
1347 1056 | }
|
1348 1057 | }
|
1349 1058 | impl
|
1350 1059 | ::aws_smithy_http_server::response::IntoResponse<
|
1351 1060 | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
1352 - | > for crate::output::EndpointWithHostLabelOperationOutput
|
1061 + | > for crate::output::GreetingWithErrorsOutput
|
1353 1062 | {
|
1354 1063 | fn into_response(self) -> ::aws_smithy_http_server::response::Response {
|
1355 - | match crate::protocol_serde::shape_endpoint_with_host_label_operation::ser_endpoint_with_host_label_operation_http_response(self) {
|
1064 + | match crate::protocol_serde::shape_greeting_with_errors::ser_greeting_with_errors_http_response(self) {
|
1356 1065 | Ok(response) => response,
|
1357 1066 | Err(e) => {
|
1358 1067 | ::tracing::error!(error = %e, "failed to serialize response");
|
1359 1068 | ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0>::into_response(::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e))
|
1360 1069 | }
|
1361 1070 | }
|
1362 1071 | }
|
1363 1072 | }
|
1364 1073 | impl
|
1365 1074 | ::aws_smithy_http_server::response::IntoResponse<
|
1366 1075 | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
1367 - | > for crate::error::EndpointWithHostLabelOperationError
|
1076 + | > for crate::error::GreetingWithErrorsError
|
1368 1077 | {
|
1369 1078 | fn into_response(self) -> ::aws_smithy_http_server::response::Response {
|
1370 - | match crate::protocol_serde::shape_endpoint_with_host_label_operation::ser_endpoint_with_host_label_operation_http_error(&self) {
|
1079 + | match crate::protocol_serde::shape_greeting_with_errors::ser_greeting_with_errors_http_error(
|
1080 + | &self,
|
1081 + | ) {
|
1371 1082 | Ok(mut response) => {
|
1372 - | response.extensions_mut().insert(::aws_smithy_http_server::extension::ModeledErrorExtension::new(self.name()));
|
1083 + | response.extensions_mut().insert(
|
1084 + | ::aws_smithy_http_server::extension::ModeledErrorExtension::new(self.name()),
|
1085 + | );
|
1373 1086 | response
|
1374 - | },
|
1087 + | }
|
1375 1088 | Err(e) => {
|
1376 1089 | ::tracing::error!(error = %e, "failed to serialize response");
|
1377 - | ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0>::into_response(::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e))
|
1090 + | ::aws_smithy_http_server::response::IntoResponse::<
|
1091 + | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
1092 + | >::into_response(
|
1093 + | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(
|
1094 + | e,
|
1095 + | ),
|
1096 + | )
|
1378 1097 | }
|
1379 1098 | }
|
1380 1099 | }
|
1381 1100 | }
|
1382 1101 |
|
1383 1102 | #[allow(unreachable_code, unused_variables)]
|
1384 1103 | #[cfg(test)]
|
1385 - | mod endpoint_with_host_label_operation_test {
|
1104 + | mod greeting_with_errors_test {
|
1386 1105 |
|
1387 - | /// Operations can prepend to the given host if they define the
|
1388 - | /// endpoint trait, and can use the host label trait to define
|
1389 - | /// further customization based on user input.
|
1390 - | /// Test ID: AwsJson10EndpointTraitWithHostLabel
|
1106 + | /// Parses simple JSON errors
|
1107 + | /// Test ID: AwsJson10InvalidGreetingError
|
1391 1108 | #[::tokio::test]
|
1392 1109 | #[::tracing_test::traced_test]
|
1393 - | #[should_panic]
|
1394 - | async fn aws_json10_endpoint_trait_with_host_label_request() {
|
1395 - | #[allow(unused_mut)]
|
1396 - | let mut http_request = ::http_1x::Request::builder()
|
1397 - | .uri("/")
|
1398 - | .method("POST")
|
1399 - | .body(::aws_smithy_http_server::body::boxed(
|
1400 - | ::http_body_util::Full::new(::bytes::Bytes::copy_from_slice(
|
1401 - | &::aws_smithy_protocol_test::decode_body_data(
|
1402 - | "{\"label\": \"bar\"}".as_bytes(),
|
1403 - | ::aws_smithy_protocol_test::MediaType::from("application/json"),
|
1404 - | ),
|
1405 - | )),
|
1406 - | ))
|
1407 - | .unwrap();
|
1408 - | todo!("endpoint trait not supported yet");
|
1409 - | #[allow(unused_mut)]
|
1410 - | let (sender, mut receiver) = ::tokio::sync::mpsc::channel(1);
|
1411 - | let config = crate::service::JsonRpc10Config::builder().build();
|
1412 - | let service =
|
1413 - | crate::service::JsonRpc10::builder::<::aws_smithy_http_server::body::BoxBody, _, _, _>(
|
1414 - | config,
|
1415 - | )
|
1416 - | .endpoint_with_host_label_operation(
|
1417 - | move |input: crate::input::EndpointWithHostLabelOperationInput| {
|
1418 - | let sender = sender.clone();
|
1419 - | async move {
|
1420 - | let result = {
|
1421 - | let expected = crate::input::EndpointWithHostLabelOperationInput {
|
1422 - | label: "bar".to_owned(),
|
1423 - | };
|
1424 - | ::pretty_assertions::assert_eq!(input, expected);
|
1425 - | let output = crate::output::EndpointWithHostLabelOperationOutput {};
|
1426 - | Ok(output)
|
1110 + | async fn aws_json10_invalid_greeting_error_response() {
|
1111 + | let output = crate::error::InvalidGreeting {
|
1112 + | message: ::std::option::Option::Some("Hi".to_owned()),
|
1427 1113 | };
|
1428 - | sender.send(()).await.expect("receiver dropped early");
|
1429 - | result
|
1430 - | }
|
1431 - | },
|
1432 - | )
|
1433 - | .build_unchecked();
|
1434 - | let http_response = ::tower::ServiceExt::oneshot(service, http_request)
|
1114 + | let output = crate::error::GreetingWithErrorsError::InvalidGreeting(output);
|
1115 + | use ::aws_smithy_http_server::response::IntoResponse;
|
1116 + | let http_response = output.into_response();
|
1117 + | ::pretty_assertions::assert_eq!(
|
1118 + | ::http_1x::StatusCode::from_u16(400).expect("invalid expected HTTP status code"),
|
1119 + | http_response.status()
|
1120 + | );
|
1121 + | let expected_headers = [("Content-Type", "application/x-amz-json-1.0")];
|
1122 + | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_headers(
|
1123 + | http_response.headers(),
|
1124 + | expected_headers,
|
1125 + | ));
|
1126 + | use ::http_body_util::BodyExt;
|
1127 + | let body = http_response
|
1128 + | .into_body()
|
1129 + | .collect()
|
1435 1130 | .await
|
1436 - | .expect("unable to make an HTTP request");
|
1437 - | assert!(
|
1438 - | receiver.recv().await.is_some(),
|
1439 - | "we expected operation handler to be invoked but it was not entered"
|
1131 + | .expect("unable to collect body")
|
1132 + | .to_bytes();
|
1133 + | ::aws_smithy_protocol_test::assert_ok(
|
1134 + | ::aws_smithy_protocol_test::validate_body(&body, "{\n \"__type\": \"aws.protocoltests.json10#InvalidGreeting\",\n \"Message\": \"Hi\"\n}", ::aws_smithy_protocol_test::MediaType::from("application/json"))
|
1440 1135 | );
|
1441 1136 | }
|
1442 - | }
|
1443 - |
|
1444 - | ::pin_project_lite::pin_project! {
|
1445 - | /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the
|
1446 - | /// [`EndpointOperationInput`](crate::input::EndpointOperationInput) using modelled bindings.
|
1447 - | pub struct EndpointOperationInputFuture {
|
1448 - | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::EndpointOperationInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
1449 - | }
|
1450 - | }
|
1451 - |
|
1452 - | impl std::future::Future for EndpointOperationInputFuture {
|
1453 - | type Output = Result<
|
1454 - | crate::input::EndpointOperationInput,
|
1455 - | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError,
|
1456 - | >;
|
1457 - |
|
1458 - | fn poll(
|
1459 - | self: std::pin::Pin<&mut Self>,
|
1460 - | cx: &mut std::task::Context<'_>,
|
1461 - | ) -> std::task::Poll<Self::Output> {
|
1462 - | let this = self.project();
|
1463 - | this.inner.as_mut().poll(cx)
|
1464 - | }
|
1465 - | }
|
1466 - |
|
1467 - | impl<B>
|
1468 - | ::aws_smithy_http_server::request::FromRequest<
|
1469 - | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
1470 - | B,
|
1471 - | > for crate::input::EndpointOperationInput
|
1472 - | where
|
1473 - | B: ::aws_smithy_http_server::body::HttpBody + Send,
|
1474 - | B: 'static,
|
1475 - |
|
1476 - | B::Data: Send,
|
1477 - | ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection:
|
1478 - | From<<B as ::aws_smithy_http_server::body::HttpBody>::Error>,
|
1479 - | {
|
1480 - | type Rejection = ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError;
|
1481 - | type Future = EndpointOperationInputFuture;
|
1482 1137 |
|
1483 - | fn from_request(request: ::http_1x::Request<B>) -> Self::Future {
|
1484 - | let fut = async move {
|
1485 - | if !::aws_smithy_http_server::protocol::accept_header_classifier(
|
1486 - | request.headers(),
|
1487 - | &crate::mimes::CONTENT_TYPE_APPLICATION_X_AMZ_JSON_1_0,
|
1488 - | ) {
|
1489 - | return Err(::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection::NotAcceptable);
|
1490 - | }
|
1491 - | crate::protocol_serde::shape_endpoint_operation::de_endpoint_operation_http_request(
|
1492 - | request,
|
1493 - | )
|
1138 + | /// Parses a complex error with no message member
|
1139 + | /// Test ID: AwsJson10ComplexError
|
1140 + | #[::tokio::test]
|
1141 + | #[::tracing_test::traced_test]
|
1142 + | async fn aws_json10_complex_error_response() {
|
1143 + | let output = crate::error::ComplexError {
|
1144 + | top_level: ::std::option::Option::Some("Top level".to_owned()),
|
1145 + | nested: ::std::option::Option::Some(crate::model::ComplexNestedErrorData {
|
1146 + | foo: ::std::option::Option::Some("bar".to_owned()),
|
1147 + | }),
|
1148 + | };
|
1149 + | let output = crate::error::GreetingWithErrorsError::ComplexError(output);
|
1150 + | use ::aws_smithy_http_server::response::IntoResponse;
|
1151 + | let http_response = output.into_response();
|
1152 + | ::pretty_assertions::assert_eq!(
|
1153 + | ::http_1x::StatusCode::from_u16(400).expect("invalid expected HTTP status code"),
|
1154 + | http_response.status()
|
1155 + | );
|
1156 + | let expected_headers = [("Content-Type", "application/x-amz-json-1.0")];
|
1157 + | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_headers(
|
1158 + | http_response.headers(),
|
1159 + | expected_headers,
|
1160 + | ));
|
1161 + | use ::http_body_util::BodyExt;
|
1162 + | let body = http_response
|
1163 + | .into_body()
|
1164 + | .collect()
|
1494 1165 | .await
|
1495 - | };
|
1496 - | use ::futures_util::future::TryFutureExt;
|
1497 - | let fut = fut.map_err(
|
1498 - | |e: ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection| {
|
1499 - | ::tracing::debug!(error = %e, "failed to deserialize request");
|
1500 - | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e)
|
1501 - | },
|
1166 + | .expect("unable to collect body")
|
1167 + | .to_bytes();
|
1168 + | ::aws_smithy_protocol_test::assert_ok(
|
1169 + | ::aws_smithy_protocol_test::validate_body(&body, "{\n \"__type\": \"aws.protocoltests.json10#ComplexError\",\n \"TopLevel\": \"Top level\",\n \"Nested\": {\n \"Foo\": \"bar\"\n }\n}", ::aws_smithy_protocol_test::MediaType::from("application/json"))
|
1502 1170 | );
|
1503 - | EndpointOperationInputFuture {
|
1504 - | inner: Box::pin(fut),
|
1505 - | }
|
1506 - | }
|
1507 - | }
|
1508 - | impl
|
1509 - | ::aws_smithy_http_server::response::IntoResponse<
|
1510 - | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
1511 - | > for crate::output::EndpointOperationOutput
|
1512 - | {
|
1513 - | fn into_response(self) -> ::aws_smithy_http_server::response::Response {
|
1514 - | match crate::protocol_serde::shape_endpoint_operation::ser_endpoint_operation_http_response(
|
1515 - | self,
|
1516 - | ) {
|
1517 - | Ok(response) => response,
|
1518 - | Err(e) => {
|
1519 - | ::tracing::error!(error = %e, "failed to serialize response");
|
1520 - | ::aws_smithy_http_server::response::IntoResponse::<
|
1521 - | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
1522 - | >::into_response(
|
1523 - | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(
|
1524 - | e,
|
1525 - | ),
|
1526 - | )
|
1527 - | }
|
1528 - | }
|
1529 1171 | }
|
1530 - | }
|
1531 - |
|
1532 - | #[allow(unreachable_code, unused_variables)]
|
1533 - | #[cfg(test)]
|
1534 - | mod endpoint_operation_test {
|
1535 1172 |
|
1536 - | /// Operations can prepend to the given host if they define the
|
1537 - | /// endpoint trait.
|
1538 - | /// Test ID: AwsJson10EndpointTrait
|
1173 + | /// Parses a complex error with an empty body
|
1174 + | /// Test ID: AwsJson10EmptyComplexError
|
1539 1175 | #[::tokio::test]
|
1540 1176 | #[::tracing_test::traced_test]
|
1541 - | #[should_panic]
|
1542 - | async fn aws_json10_endpoint_trait_request() {
|
1543 - | #[allow(unused_mut)]
|
1544 - | let mut http_request = ::http_1x::Request::builder()
|
1545 - | .uri("/")
|
1546 - | .method("POST")
|
1547 - | .body(::aws_smithy_http_server::body::boxed(
|
1548 - | ::http_body_util::Full::new(::bytes::Bytes::copy_from_slice(
|
1549 - | &::aws_smithy_protocol_test::decode_body_data(
|
1550 - | "{}".as_bytes(),
|
1551 - | ::aws_smithy_protocol_test::MediaType::from("unknown"),
|
1552 - | ),
|
1553 - | )),
|
1554 - | ))
|
1555 - | .unwrap();
|
1556 - | todo!("endpoint trait not supported yet");
|
1557 - | #[allow(unused_mut)]
|
1558 - | let (sender, mut receiver) = ::tokio::sync::mpsc::channel(1);
|
1559 - | let config = crate::service::JsonRpc10Config::builder().build();
|
1560 - | let service =
|
1561 - | crate::service::JsonRpc10::builder::<::aws_smithy_http_server::body::BoxBody, _, _, _>(
|
1562 - | config,
|
1563 - | )
|
1564 - | .endpoint_operation(move |input: crate::input::EndpointOperationInput| {
|
1565 - | let sender = sender.clone();
|
1566 - | async move {
|
1567 - | let result = {
|
1568 - | let expected = crate::input::EndpointOperationInput {};
|
1569 - | ::pretty_assertions::assert_eq!(input, expected);
|
1570 - | let output = crate::output::EndpointOperationOutput {};
|
1571 - | output
|
1177 + | async fn aws_json10_empty_complex_error_response() {
|
1178 + | let output = crate::error::ComplexError {
|
1179 + | top_level: ::std::option::Option::None,
|
1180 + | nested: ::std::option::Option::None,
|
1572 1181 | };
|
1573 - | sender.send(()).await.expect("receiver dropped early");
|
1574 - | result
|
1575 - | }
|
1576 - | })
|
1577 - | .build_unchecked();
|
1578 - | let http_response = ::tower::ServiceExt::oneshot(service, http_request)
|
1579 - | .await
|
1580 - | .expect("unable to make an HTTP request");
|
1581 - | assert!(
|
1582 - | receiver.recv().await.is_some(),
|
1583 - | "we expected operation handler to be invoked but it was not entered"
|
1182 + | let output = crate::error::GreetingWithErrorsError::ComplexError(output);
|
1183 + | use ::aws_smithy_http_server::response::IntoResponse;
|
1184 + | let http_response = output.into_response();
|
1185 + | ::pretty_assertions::assert_eq!(
|
1186 + | ::http_1x::StatusCode::from_u16(400).expect("invalid expected HTTP status code"),
|
1187 + | http_response.status()
|
1584 1188 | );
|
1189 + | let expected_headers = [("Content-Type", "application/x-amz-json-1.0")];
|
1190 + | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_headers(
|
1191 + | http_response.headers(),
|
1192 + | expected_headers,
|
1193 + | ));
|
1194 + | use ::http_body_util::BodyExt;
|
1195 + | let body = http_response
|
1196 + | .into_body()
|
1197 + | .collect()
|
1198 + | .await
|
1199 + | .expect("unable to collect body")
|
1200 + | .to_bytes();
|
1201 + | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_body(
|
1202 + | &body,
|
1203 + | "{\n \"__type\": \"aws.protocoltests.json10#ComplexError\"\n}",
|
1204 + | ::aws_smithy_protocol_test::MediaType::from("application/json"),
|
1205 + | ));
|
1585 1206 | }
|
1586 1207 | }
|
1587 1208 |
|
1588 1209 | ::pin_project_lite::pin_project! {
|
1589 1210 | /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the
|
1590 1211 | /// [`JsonUnionsInput`](crate::input::JsonUnionsInput) using modelled bindings.
|
1591 1212 | pub struct JsonUnionsInputFuture {
|
1592 1213 | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::JsonUnionsInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
1593 1214 | }
|
1594 1215 | }
|
2606 2227 | let expected_headers = [("Content-Type", "application/x-amz-json-1.0")];
|
2607 2228 | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_headers(
|
2608 2229 | http_response.headers(),
|
2609 2230 | expected_headers,
|
2610 2231 | ));
|
2611 2232 | use ::http_body_util::BodyExt;
|
2612 2233 | let body = http_response
|
2613 2234 | .into_body()
|
2614 2235 | .collect()
|
2615 2236 | .await
|
2616 - | .expect("unable to collect body")
|
2617 - | .to_bytes();
|
2618 - | ::aws_smithy_protocol_test::assert_ok(
|
2619 - | ::aws_smithy_protocol_test::validate_body(&body, "{\n \"contents\": {\n \"structureValue\": {\n \"hi\": \"hello\"\n }\n }\n}", ::aws_smithy_protocol_test::MediaType::from("application/json"))
|
2237 + | .expect("unable to collect body")
|
2238 + | .to_bytes();
|
2239 + | ::aws_smithy_protocol_test::assert_ok(
|
2240 + | ::aws_smithy_protocol_test::validate_body(&body, "{\n \"contents\": {\n \"structureValue\": {\n \"hi\": \"hello\"\n }\n }\n}", ::aws_smithy_protocol_test::MediaType::from("application/json"))
|
2241 + | );
|
2242 + | }
|
2243 + | }
|
2244 + |
|
2245 + | ::pin_project_lite::pin_project! {
|
2246 + | /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the
|
2247 + | /// [`EndpointOperationInput`](crate::input::EndpointOperationInput) using modelled bindings.
|
2248 + | pub struct EndpointOperationInputFuture {
|
2249 + | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::EndpointOperationInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
2250 + | }
|
2251 + | }
|
2252 + |
|
2253 + | impl std::future::Future for EndpointOperationInputFuture {
|
2254 + | type Output = Result<
|
2255 + | crate::input::EndpointOperationInput,
|
2256 + | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError,
|
2257 + | >;
|
2258 + |
|
2259 + | fn poll(
|
2260 + | self: std::pin::Pin<&mut Self>,
|
2261 + | cx: &mut std::task::Context<'_>,
|
2262 + | ) -> std::task::Poll<Self::Output> {
|
2263 + | let this = self.project();
|
2264 + | this.inner.as_mut().poll(cx)
|
2265 + | }
|
2266 + | }
|
2267 + |
|
2268 + | impl<B>
|
2269 + | ::aws_smithy_http_server::request::FromRequest<
|
2270 + | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
2271 + | B,
|
2272 + | > for crate::input::EndpointOperationInput
|
2273 + | where
|
2274 + | B: ::aws_smithy_http_server::body::HttpBody + Send,
|
2275 + | B: 'static,
|
2276 + |
|
2277 + | B::Data: Send,
|
2278 + | ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection:
|
2279 + | From<<B as ::aws_smithy_http_server::body::HttpBody>::Error>,
|
2280 + | {
|
2281 + | type Rejection = ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError;
|
2282 + | type Future = EndpointOperationInputFuture;
|
2283 + |
|
2284 + | fn from_request(request: ::http_1x::Request<B>) -> Self::Future {
|
2285 + | let fut = async move {
|
2286 + | if !::aws_smithy_http_server::protocol::accept_header_classifier(
|
2287 + | request.headers(),
|
2288 + | &crate::mimes::CONTENT_TYPE_APPLICATION_X_AMZ_JSON_1_0,
|
2289 + | ) {
|
2290 + | return Err(::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection::NotAcceptable);
|
2291 + | }
|
2292 + | crate::protocol_serde::shape_endpoint_operation::de_endpoint_operation_http_request(
|
2293 + | request,
|
2294 + | )
|
2295 + | .await
|
2296 + | };
|
2297 + | use ::futures_util::future::TryFutureExt;
|
2298 + | let fut = fut.map_err(
|
2299 + | |e: ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection| {
|
2300 + | ::tracing::debug!(error = %e, "failed to deserialize request");
|
2301 + | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e)
|
2302 + | },
|
2303 + | );
|
2304 + | EndpointOperationInputFuture {
|
2305 + | inner: Box::pin(fut),
|
2306 + | }
|
2307 + | }
|
2308 + | }
|
2309 + | impl
|
2310 + | ::aws_smithy_http_server::response::IntoResponse<
|
2311 + | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
2312 + | > for crate::output::EndpointOperationOutput
|
2313 + | {
|
2314 + | fn into_response(self) -> ::aws_smithy_http_server::response::Response {
|
2315 + | match crate::protocol_serde::shape_endpoint_operation::ser_endpoint_operation_http_response(
|
2316 + | self,
|
2317 + | ) {
|
2318 + | Ok(response) => response,
|
2319 + | Err(e) => {
|
2320 + | ::tracing::error!(error = %e, "failed to serialize response");
|
2321 + | ::aws_smithy_http_server::response::IntoResponse::<
|
2322 + | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
2323 + | >::into_response(
|
2324 + | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(
|
2325 + | e,
|
2326 + | ),
|
2327 + | )
|
2328 + | }
|
2329 + | }
|
2330 + | }
|
2331 + | }
|
2332 + |
|
2333 + | #[allow(unreachable_code, unused_variables)]
|
2334 + | #[cfg(test)]
|
2335 + | mod endpoint_operation_test {
|
2336 + |
|
2337 + | /// Operations can prepend to the given host if they define the
|
2338 + | /// endpoint trait.
|
2339 + | /// Test ID: AwsJson10EndpointTrait
|
2340 + | #[::tokio::test]
|
2341 + | #[::tracing_test::traced_test]
|
2342 + | #[should_panic]
|
2343 + | async fn aws_json10_endpoint_trait_request() {
|
2344 + | #[allow(unused_mut)]
|
2345 + | let mut http_request = ::http_1x::Request::builder()
|
2346 + | .uri("/")
|
2347 + | .method("POST")
|
2348 + | .body(::aws_smithy_http_server::body::boxed(
|
2349 + | ::http_body_util::Full::new(::bytes::Bytes::copy_from_slice(
|
2350 + | &::aws_smithy_protocol_test::decode_body_data(
|
2351 + | "{}".as_bytes(),
|
2352 + | ::aws_smithy_protocol_test::MediaType::from("unknown"),
|
2353 + | ),
|
2354 + | )),
|
2355 + | ))
|
2356 + | .unwrap();
|
2357 + | todo!("endpoint trait not supported yet");
|
2358 + | #[allow(unused_mut)]
|
2359 + | let (sender, mut receiver) = ::tokio::sync::mpsc::channel(1);
|
2360 + | let config = crate::service::JsonRpc10Config::builder().build();
|
2361 + | let service =
|
2362 + | crate::service::JsonRpc10::builder::<::aws_smithy_http_server::body::BoxBody, _, _, _>(
|
2363 + | config,
|
2364 + | )
|
2365 + | .endpoint_operation(move |input: crate::input::EndpointOperationInput| {
|
2366 + | let sender = sender.clone();
|
2367 + | async move {
|
2368 + | let result = {
|
2369 + | let expected = crate::input::EndpointOperationInput {};
|
2370 + | ::pretty_assertions::assert_eq!(input, expected);
|
2371 + | let output = crate::output::EndpointOperationOutput {};
|
2372 + | output
|
2373 + | };
|
2374 + | sender.send(()).await.expect("receiver dropped early");
|
2375 + | result
|
2376 + | }
|
2377 + | })
|
2378 + | .build_unchecked();
|
2379 + | let http_response = ::tower::ServiceExt::oneshot(service, http_request)
|
2380 + | .await
|
2381 + | .expect("unable to make an HTTP request");
|
2382 + | assert!(
|
2383 + | receiver.recv().await.is_some(),
|
2384 + | "we expected operation handler to be invoked but it was not entered"
|
2620 2385 | );
|
2621 2386 | }
|
2622 2387 | }
|
2623 2388 |
|
2624 2389 | ::pin_project_lite::pin_project! {
|
2625 2390 | /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the
|
2626 - | /// [`GreetingWithErrorsInput`](crate::input::GreetingWithErrorsInput) using modelled bindings.
|
2627 - | pub struct GreetingWithErrorsInputFuture {
|
2628 - | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::GreetingWithErrorsInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
2391 + | /// [`EndpointWithHostLabelOperationInput`](crate::input::EndpointWithHostLabelOperationInput) using modelled bindings.
|
2392 + | pub struct EndpointWithHostLabelOperationInputFuture {
|
2393 + | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::EndpointWithHostLabelOperationInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
2629 2394 | }
|
2630 2395 | }
|
2631 2396 |
|
2632 - | impl std::future::Future for GreetingWithErrorsInputFuture {
|
2397 + | impl std::future::Future for EndpointWithHostLabelOperationInputFuture {
|
2633 2398 | type Output = Result<
|
2634 - | crate::input::GreetingWithErrorsInput,
|
2399 + | crate::input::EndpointWithHostLabelOperationInput,
|
2635 2400 | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError,
|
2636 2401 | >;
|
2637 2402 |
|
2638 2403 | fn poll(
|
2639 2404 | self: std::pin::Pin<&mut Self>,
|
2640 2405 | cx: &mut std::task::Context<'_>,
|
2641 2406 | ) -> std::task::Poll<Self::Output> {
|
2642 2407 | let this = self.project();
|
2643 2408 | this.inner.as_mut().poll(cx)
|
2644 2409 | }
|
2645 2410 | }
|
2646 2411 |
|
2647 2412 | impl<B>
|
2648 2413 | ::aws_smithy_http_server::request::FromRequest<
|
2649 2414 | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
2650 2415 | B,
|
2651 - | > for crate::input::GreetingWithErrorsInput
|
2416 + | > for crate::input::EndpointWithHostLabelOperationInput
|
2652 2417 | where
|
2653 2418 | B: ::aws_smithy_http_server::body::HttpBody + Send,
|
2654 2419 | B: 'static,
|
2655 2420 |
|
2656 2421 | B::Data: Send,
|
2657 2422 | ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection:
|
2658 2423 | From<<B as ::aws_smithy_http_server::body::HttpBody>::Error>,
|
2659 2424 | {
|
2660 2425 | type Rejection = ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError;
|
2661 - | type Future = GreetingWithErrorsInputFuture;
|
2426 + | type Future = EndpointWithHostLabelOperationInputFuture;
|
2662 2427 |
|
2663 2428 | fn from_request(request: ::http_1x::Request<B>) -> Self::Future {
|
2664 2429 | let fut = async move {
|
2665 2430 | if !::aws_smithy_http_server::protocol::accept_header_classifier(
|
2666 2431 | request.headers(),
|
2667 2432 | &crate::mimes::CONTENT_TYPE_APPLICATION_X_AMZ_JSON_1_0,
|
2668 2433 | ) {
|
2669 2434 | return Err(::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection::NotAcceptable);
|
2670 2435 | }
|
2671 - | crate::protocol_serde::shape_greeting_with_errors::de_greeting_with_errors_http_request(
|
2672 - | request,
|
2673 - | )
|
2436 + | crate::protocol_serde::shape_endpoint_with_host_label_operation::de_endpoint_with_host_label_operation_http_request(request)
|
2674 2437 | .await
|
2675 2438 | };
|
2676 2439 | use ::futures_util::future::TryFutureExt;
|
2677 2440 | let fut = fut.map_err(
|
2678 2441 | |e: ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection| {
|
2679 2442 | ::tracing::debug!(error = %e, "failed to deserialize request");
|
2680 2443 | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e)
|
2681 2444 | },
|
2682 2445 | );
|
2683 - | GreetingWithErrorsInputFuture {
|
2446 + | EndpointWithHostLabelOperationInputFuture {
|
2684 2447 | inner: Box::pin(fut),
|
2685 2448 | }
|
2686 2449 | }
|
2687 2450 | }
|
2688 2451 | impl
|
2689 2452 | ::aws_smithy_http_server::response::IntoResponse<
|
2690 2453 | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
2691 - | > for crate::output::GreetingWithErrorsOutput
|
2454 + | > for crate::output::EndpointWithHostLabelOperationOutput
|
2692 2455 | {
|
2693 2456 | fn into_response(self) -> ::aws_smithy_http_server::response::Response {
|
2694 - | match crate::protocol_serde::shape_greeting_with_errors::ser_greeting_with_errors_http_response(self) {
|
2457 + | match crate::protocol_serde::shape_endpoint_with_host_label_operation::ser_endpoint_with_host_label_operation_http_response(self) {
|
2695 2458 | Ok(response) => response,
|
2696 2459 | Err(e) => {
|
2697 2460 | ::tracing::error!(error = %e, "failed to serialize response");
|
2698 2461 | ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0>::into_response(::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e))
|
2699 2462 | }
|
2700 2463 | }
|
2701 2464 | }
|
2702 2465 | }
|
2703 2466 | impl
|
2704 2467 | ::aws_smithy_http_server::response::IntoResponse<
|
2705 2468 | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
2706 - | > for crate::error::GreetingWithErrorsError
|
2469 + | > for crate::error::EndpointWithHostLabelOperationError
|
2707 2470 | {
|
2708 2471 | fn into_response(self) -> ::aws_smithy_http_server::response::Response {
|
2709 - | match crate::protocol_serde::shape_greeting_with_errors::ser_greeting_with_errors_http_error(
|
2710 - | &self,
|
2711 - | ) {
|
2472 + | match crate::protocol_serde::shape_endpoint_with_host_label_operation::ser_endpoint_with_host_label_operation_http_error(&self) {
|
2712 2473 | Ok(mut response) => {
|
2713 - | response.extensions_mut().insert(
|
2714 - | ::aws_smithy_http_server::extension::ModeledErrorExtension::new(self.name()),
|
2715 - | );
|
2474 + | response.extensions_mut().insert(::aws_smithy_http_server::extension::ModeledErrorExtension::new(self.name()));
|
2716 2475 | response
|
2717 - | }
|
2476 + | },
|
2718 2477 | Err(e) => {
|
2719 2478 | ::tracing::error!(error = %e, "failed to serialize response");
|
2720 - | ::aws_smithy_http_server::response::IntoResponse::<
|
2721 - | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
2722 - | >::into_response(
|
2723 - | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(
|
2724 - | e,
|
2725 - | ),
|
2726 - | )
|
2479 + | ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0>::into_response(::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e))
|
2727 2480 | }
|
2728 2481 | }
|
2729 2482 | }
|
2730 2483 | }
|
2731 2484 |
|
2732 2485 | #[allow(unreachable_code, unused_variables)]
|
2733 2486 | #[cfg(test)]
|
2734 - | mod greeting_with_errors_test {
|
2487 + | mod endpoint_with_host_label_operation_test {
|
2735 2488 |
|
2736 - | /// Parses simple JSON errors
|
2737 - | /// Test ID: AwsJson10InvalidGreetingError
|
2489 + | /// Operations can prepend to the given host if they define the
|
2490 + | /// endpoint trait, and can use the host label trait to define
|
2491 + | /// further customization based on user input.
|
2492 + | /// Test ID: AwsJson10EndpointTraitWithHostLabel
|
2738 2493 | #[::tokio::test]
|
2739 2494 | #[::tracing_test::traced_test]
|
2740 - | async fn aws_json10_invalid_greeting_error_response() {
|
2741 - | let output = crate::error::InvalidGreeting {
|
2742 - | message: ::std::option::Option::Some("Hi".to_owned()),
|
2495 + | #[should_panic]
|
2496 + | async fn aws_json10_endpoint_trait_with_host_label_request() {
|
2497 + | #[allow(unused_mut)]
|
2498 + | let mut http_request = ::http_1x::Request::builder()
|
2499 + | .uri("/")
|
2500 + | .method("POST")
|
2501 + | .body(::aws_smithy_http_server::body::boxed(
|
2502 + | ::http_body_util::Full::new(::bytes::Bytes::copy_from_slice(
|
2503 + | &::aws_smithy_protocol_test::decode_body_data(
|
2504 + | "{\"label\": \"bar\"}".as_bytes(),
|
2505 + | ::aws_smithy_protocol_test::MediaType::from("application/json"),
|
2506 + | ),
|
2507 + | )),
|
2508 + | ))
|
2509 + | .unwrap();
|
2510 + | todo!("endpoint trait not supported yet");
|
2511 + | #[allow(unused_mut)]
|
2512 + | let (sender, mut receiver) = ::tokio::sync::mpsc::channel(1);
|
2513 + | let config = crate::service::JsonRpc10Config::builder().build();
|
2514 + | let service =
|
2515 + | crate::service::JsonRpc10::builder::<::aws_smithy_http_server::body::BoxBody, _, _, _>(
|
2516 + | config,
|
2517 + | )
|
2518 + | .endpoint_with_host_label_operation(
|
2519 + | move |input: crate::input::EndpointWithHostLabelOperationInput| {
|
2520 + | let sender = sender.clone();
|
2521 + | async move {
|
2522 + | let result = {
|
2523 + | let expected = crate::input::EndpointWithHostLabelOperationInput {
|
2524 + | label: "bar".to_owned(),
|
2743 2525 | };
|
2744 - | let output = crate::error::GreetingWithErrorsError::InvalidGreeting(output);
|
2745 - | use ::aws_smithy_http_server::response::IntoResponse;
|
2746 - | let http_response = output.into_response();
|
2747 - | ::pretty_assertions::assert_eq!(
|
2748 - | ::http_1x::StatusCode::from_u16(400).expect("invalid expected HTTP status code"),
|
2749 - | http_response.status()
|
2750 - | );
|
2751 - | let expected_headers = [("Content-Type", "application/x-amz-json-1.0")];
|
2752 - | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_headers(
|
2753 - | http_response.headers(),
|
2754 - | expected_headers,
|
2755 - | ));
|
2756 - | use ::http_body_util::BodyExt;
|
2757 - | let body = http_response
|
2758 - | .into_body()
|
2759 - | .collect()
|
2526 + | ::pretty_assertions::assert_eq!(input, expected);
|
2527 + | let output = crate::output::EndpointWithHostLabelOperationOutput {};
|
2528 + | Ok(output)
|
2529 + | };
|
2530 + | sender.send(()).await.expect("receiver dropped early");
|
2531 + | result
|
2532 + | }
|
2533 + | },
|
2534 + | )
|
2535 + | .build_unchecked();
|
2536 + | let http_response = ::tower::ServiceExt::oneshot(service, http_request)
|
2760 2537 | .await
|
2761 - | .expect("unable to collect body")
|
2762 - | .to_bytes();
|
2763 - | ::aws_smithy_protocol_test::assert_ok(
|
2764 - | ::aws_smithy_protocol_test::validate_body(&body, "{\n \"__type\": \"aws.protocoltests.json10#InvalidGreeting\",\n \"Message\": \"Hi\"\n}", ::aws_smithy_protocol_test::MediaType::from("application/json"))
|
2538 + | .expect("unable to make an HTTP request");
|
2539 + | assert!(
|
2540 + | receiver.recv().await.is_some(),
|
2541 + | "we expected operation handler to be invoked but it was not entered"
|
2765 2542 | );
|
2766 2543 | }
|
2544 + | }
|
2767 2545 |
|
2768 - | /// Parses a complex error with no message member
|
2769 - | /// Test ID: AwsJson10ComplexError
|
2770 - | #[::tokio::test]
|
2771 - | #[::tracing_test::traced_test]
|
2772 - | async fn aws_json10_complex_error_response() {
|
2773 - | let output = crate::error::ComplexError {
|
2774 - | top_level: ::std::option::Option::Some("Top level".to_owned()),
|
2775 - | nested: ::std::option::Option::Some(crate::model::ComplexNestedErrorData {
|
2776 - | foo: ::std::option::Option::Some("bar".to_owned()),
|
2777 - | }),
|
2778 - | };
|
2779 - | let output = crate::error::GreetingWithErrorsError::ComplexError(output);
|
2780 - | use ::aws_smithy_http_server::response::IntoResponse;
|
2781 - | let http_response = output.into_response();
|
2782 - | ::pretty_assertions::assert_eq!(
|
2783 - | ::http_1x::StatusCode::from_u16(400).expect("invalid expected HTTP status code"),
|
2784 - | http_response.status()
|
2785 - | );
|
2786 - | let expected_headers = [("Content-Type", "application/x-amz-json-1.0")];
|
2787 - | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_headers(
|
2788 - | http_response.headers(),
|
2789 - | expected_headers,
|
2790 - | ));
|
2791 - | use ::http_body_util::BodyExt;
|
2792 - | let body = http_response
|
2793 - | .into_body()
|
2794 - | .collect()
|
2546 + | ::pin_project_lite::pin_project! {
|
2547 + | /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the
|
2548 + | /// [`HostWithPathOperationInput`](crate::input::HostWithPathOperationInput) using modelled bindings.
|
2549 + | pub struct HostWithPathOperationInputFuture {
|
2550 + | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::HostWithPathOperationInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
2551 + | }
|
2552 + | }
|
2553 + |
|
2554 + | impl std::future::Future for HostWithPathOperationInputFuture {
|
2555 + | type Output = Result<
|
2556 + | crate::input::HostWithPathOperationInput,
|
2557 + | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError,
|
2558 + | >;
|
2559 + |
|
2560 + | fn poll(
|
2561 + | self: std::pin::Pin<&mut Self>,
|
2562 + | cx: &mut std::task::Context<'_>,
|
2563 + | ) -> std::task::Poll<Self::Output> {
|
2564 + | let this = self.project();
|
2565 + | this.inner.as_mut().poll(cx)
|
2566 + | }
|
2567 + | }
|
2568 + |
|
2569 + | impl<B>
|
2570 + | ::aws_smithy_http_server::request::FromRequest<
|
2571 + | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
2572 + | B,
|
2573 + | > for crate::input::HostWithPathOperationInput
|
2574 + | where
|
2575 + | B: ::aws_smithy_http_server::body::HttpBody + Send,
|
2576 + | B: 'static,
|
2577 + |
|
2578 + | B::Data: Send,
|
2579 + | ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection:
|
2580 + | From<<B as ::aws_smithy_http_server::body::HttpBody>::Error>,
|
2581 + | {
|
2582 + | type Rejection = ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError;
|
2583 + | type Future = HostWithPathOperationInputFuture;
|
2584 + |
|
2585 + | fn from_request(request: ::http_1x::Request<B>) -> Self::Future {
|
2586 + | let fut = async move {
|
2587 + | if !::aws_smithy_http_server::protocol::accept_header_classifier(
|
2588 + | request.headers(),
|
2589 + | &crate::mimes::CONTENT_TYPE_APPLICATION_X_AMZ_JSON_1_0,
|
2590 + | ) {
|
2591 + | return Err(::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection::NotAcceptable);
|
2592 + | }
|
2593 + | crate::protocol_serde::shape_host_with_path_operation::de_host_with_path_operation_http_request(request)
|
2795 2594 | .await
|
2796 - | .expect("unable to collect body")
|
2797 - | .to_bytes();
|
2798 - | ::aws_smithy_protocol_test::assert_ok(
|
2799 - | ::aws_smithy_protocol_test::validate_body(&body, "{\n \"__type\": \"aws.protocoltests.json10#ComplexError\",\n \"TopLevel\": \"Top level\",\n \"Nested\": {\n \"Foo\": \"bar\"\n }\n}", ::aws_smithy_protocol_test::MediaType::from("application/json"))
|
2595 + | };
|
2596 + | use ::futures_util::future::TryFutureExt;
|
2597 + | let fut = fut.map_err(
|
2598 + | |e: ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection| {
|
2599 + | ::tracing::debug!(error = %e, "failed to deserialize request");
|
2600 + | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e)
|
2601 + | },
|
2800 2602 | );
|
2603 + | HostWithPathOperationInputFuture {
|
2604 + | inner: Box::pin(fut),
|
2605 + | }
|
2606 + | }
|
2607 + | }
|
2608 + | impl
|
2609 + | ::aws_smithy_http_server::response::IntoResponse<
|
2610 + | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
2611 + | > for crate::output::HostWithPathOperationOutput
|
2612 + | {
|
2613 + | fn into_response(self) -> ::aws_smithy_http_server::response::Response {
|
2614 + | match crate::protocol_serde::shape_host_with_path_operation::ser_host_with_path_operation_http_response(self) {
|
2615 + | Ok(response) => response,
|
2616 + | Err(e) => {
|
2617 + | ::tracing::error!(error = %e, "failed to serialize response");
|
2618 + | ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0>::into_response(::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e))
|
2619 + | }
|
2620 + | }
|
2621 + | }
|
2622 + | }
|
2623 + |
|
2624 + | ::pin_project_lite::pin_project! {
|
2625 + | /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the
|
2626 + | /// [`PutWithContentEncodingInput`](crate::input::PutWithContentEncodingInput) using modelled bindings.
|
2627 + | pub struct PutWithContentEncodingInputFuture {
|
2628 + | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::PutWithContentEncodingInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
2629 + | }
|
2630 + | }
|
2631 + |
|
2632 + | impl std::future::Future for PutWithContentEncodingInputFuture {
|
2633 + | type Output = Result<
|
2634 + | crate::input::PutWithContentEncodingInput,
|
2635 + | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError,
|
2636 + | >;
|
2637 + |
|
2638 + | fn poll(
|
2639 + | self: std::pin::Pin<&mut Self>,
|
2640 + | cx: &mut std::task::Context<'_>,
|
2641 + | ) -> std::task::Poll<Self::Output> {
|
2642 + | let this = self.project();
|
2643 + | this.inner.as_mut().poll(cx)
|
2801 2644 | }
|
2645 + | }
|
2802 2646 |
|
2803 - | /// Parses a complex error with an empty body
|
2804 - | /// Test ID: AwsJson10EmptyComplexError
|
2805 - | #[::tokio::test]
|
2806 - | #[::tracing_test::traced_test]
|
2807 - | async fn aws_json10_empty_complex_error_response() {
|
2808 - | let output = crate::error::ComplexError {
|
2809 - | top_level: ::std::option::Option::None,
|
2810 - | nested: ::std::option::Option::None,
|
2647 + | impl<B>
|
2648 + | ::aws_smithy_http_server::request::FromRequest<
|
2649 + | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
2650 + | B,
|
2651 + | > for crate::input::PutWithContentEncodingInput
|
2652 + | where
|
2653 + | B: ::aws_smithy_http_server::body::HttpBody + Send,
|
2654 + | B: 'static,
|
2655 + |
|
2656 + | B::Data: Send,
|
2657 + | ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection:
|
2658 + | From<<B as ::aws_smithy_http_server::body::HttpBody>::Error>,
|
2659 + | {
|
2660 + | type Rejection = ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError;
|
2661 + | type Future = PutWithContentEncodingInputFuture;
|
2662 + |
|
2663 + | fn from_request(request: ::http_1x::Request<B>) -> Self::Future {
|
2664 + | let fut = async move {
|
2665 + | if !::aws_smithy_http_server::protocol::accept_header_classifier(
|
2666 + | request.headers(),
|
2667 + | &crate::mimes::CONTENT_TYPE_APPLICATION_X_AMZ_JSON_1_0,
|
2668 + | ) {
|
2669 + | return Err(::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection::NotAcceptable);
|
2670 + | }
|
2671 + | crate::protocol_serde::shape_put_with_content_encoding::de_put_with_content_encoding_http_request(request)
|
2672 + | .await
|
2811 2673 | };
|
2812 - | let output = crate::error::GreetingWithErrorsError::ComplexError(output);
|
2813 - | use ::aws_smithy_http_server::response::IntoResponse;
|
2814 - | let http_response = output.into_response();
|
2815 - | ::pretty_assertions::assert_eq!(
|
2816 - | ::http_1x::StatusCode::from_u16(400).expect("invalid expected HTTP status code"),
|
2817 - | http_response.status()
|
2674 + | use ::futures_util::future::TryFutureExt;
|
2675 + | let fut = fut.map_err(
|
2676 + | |e: ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection| {
|
2677 + | ::tracing::debug!(error = %e, "failed to deserialize request");
|
2678 + | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e)
|
2679 + | },
|
2818 2680 | );
|
2819 - | let expected_headers = [("Content-Type", "application/x-amz-json-1.0")];
|
2820 - | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_headers(
|
2821 - | http_response.headers(),
|
2822 - | expected_headers,
|
2823 - | ));
|
2824 - | use ::http_body_util::BodyExt;
|
2825 - | let body = http_response
|
2826 - | .into_body()
|
2827 - | .collect()
|
2828 - | .await
|
2829 - | .expect("unable to collect body")
|
2830 - | .to_bytes();
|
2831 - | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_body(
|
2832 - | &body,
|
2833 - | "{\n \"__type\": \"aws.protocoltests.json10#ComplexError\"\n}",
|
2834 - | ::aws_smithy_protocol_test::MediaType::from("application/json"),
|
2835 - | ));
|
2681 + | PutWithContentEncodingInputFuture {
|
2682 + | inner: Box::pin(fut),
|
2683 + | }
|
2684 + | }
|
2685 + | }
|
2686 + | impl
|
2687 + | ::aws_smithy_http_server::response::IntoResponse<
|
2688 + | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
2689 + | > for crate::output::PutWithContentEncodingOutput
|
2690 + | {
|
2691 + | fn into_response(self) -> ::aws_smithy_http_server::response::Response {
|
2692 + | match crate::protocol_serde::shape_put_with_content_encoding::ser_put_with_content_encoding_http_response(self) {
|
2693 + | Ok(response) => response,
|
2694 + | Err(e) => {
|
2695 + | ::tracing::error!(error = %e, "failed to serialize response");
|
2696 + | ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0>::into_response(::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e))
|
2697 + | }
|
2698 + | }
|
2836 2699 | }
|
2837 2700 | }
|
2838 2701 |
|
2839 2702 | ::pin_project_lite::pin_project! {
|
2840 2703 | /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the
|
2841 - | /// [`SimpleScalarPropertiesInput`](crate::input::SimpleScalarPropertiesInput) using modelled bindings.
|
2842 - | pub struct SimpleScalarPropertiesInputFuture {
|
2843 - | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::SimpleScalarPropertiesInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
2704 + | /// [`ContentTypeParametersInput`](crate::input::ContentTypeParametersInput) using modelled bindings.
|
2705 + | pub struct ContentTypeParametersInputFuture {
|
2706 + | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::ContentTypeParametersInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
2844 2707 | }
|
2845 2708 | }
|
2846 2709 |
|
2847 - | impl std::future::Future for SimpleScalarPropertiesInputFuture {
|
2710 + | impl std::future::Future for ContentTypeParametersInputFuture {
|
2848 2711 | type Output = Result<
|
2849 - | crate::input::SimpleScalarPropertiesInput,
|
2712 + | crate::input::ContentTypeParametersInput,
|
2850 2713 | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError,
|
2851 2714 | >;
|
2852 2715 |
|
2853 2716 | fn poll(
|
2854 2717 | self: std::pin::Pin<&mut Self>,
|
2855 2718 | cx: &mut std::task::Context<'_>,
|
2856 2719 | ) -> std::task::Poll<Self::Output> {
|
2857 2720 | let this = self.project();
|
2858 2721 | this.inner.as_mut().poll(cx)
|
2859 2722 | }
|
2860 2723 | }
|
2861 2724 |
|
2862 2725 | impl<B>
|
2863 2726 | ::aws_smithy_http_server::request::FromRequest<
|
2864 2727 | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
2865 2728 | B,
|
2866 - | > for crate::input::SimpleScalarPropertiesInput
|
2729 + | > for crate::input::ContentTypeParametersInput
|
2867 2730 | where
|
2868 2731 | B: ::aws_smithy_http_server::body::HttpBody + Send,
|
2869 2732 | B: 'static,
|
2870 2733 |
|
2871 2734 | B::Data: Send,
|
2872 2735 | ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection:
|
2873 2736 | From<<B as ::aws_smithy_http_server::body::HttpBody>::Error>,
|
2874 2737 | {
|
2875 2738 | type Rejection = ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError;
|
2876 - | type Future = SimpleScalarPropertiesInputFuture;
|
2739 + | type Future = ContentTypeParametersInputFuture;
|
2877 2740 |
|
2878 2741 | fn from_request(request: ::http_1x::Request<B>) -> Self::Future {
|
2879 2742 | let fut = async move {
|
2880 2743 | if !::aws_smithy_http_server::protocol::accept_header_classifier(
|
2881 2744 | request.headers(),
|
2882 2745 | &crate::mimes::CONTENT_TYPE_APPLICATION_X_AMZ_JSON_1_0,
|
2883 2746 | ) {
|
2884 2747 | return Err(::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection::NotAcceptable);
|
2885 2748 | }
|
2886 - | crate::protocol_serde::shape_simple_scalar_properties::de_simple_scalar_properties_http_request(request)
|
2749 + | crate::protocol_serde::shape_content_type_parameters::de_content_type_parameters_http_request(request)
|
2887 2750 | .await
|
2888 2751 | };
|
2889 2752 | use ::futures_util::future::TryFutureExt;
|
2890 2753 | let fut = fut.map_err(
|
2891 2754 | |e: ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection| {
|
2892 2755 | ::tracing::debug!(error = %e, "failed to deserialize request");
|
2893 2756 | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e)
|
2894 2757 | },
|
2895 2758 | );
|
2896 - | SimpleScalarPropertiesInputFuture {
|
2759 + | ContentTypeParametersInputFuture {
|
2897 2760 | inner: Box::pin(fut),
|
2898 2761 | }
|
2899 2762 | }
|
2900 2763 | }
|
2901 2764 | impl
|
2902 2765 | ::aws_smithy_http_server::response::IntoResponse<
|
2903 2766 | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
2904 - | > for crate::output::SimpleScalarPropertiesOutput
|
2767 + | > for crate::output::ContentTypeParametersOutput
|
2905 2768 | {
|
2906 2769 | fn into_response(self) -> ::aws_smithy_http_server::response::Response {
|
2907 - | match crate::protocol_serde::shape_simple_scalar_properties::ser_simple_scalar_properties_http_response(self) {
|
2770 + | match crate::protocol_serde::shape_content_type_parameters::ser_content_type_parameters_http_response(self) {
|
2908 2771 | Ok(response) => response,
|
2909 2772 | Err(e) => {
|
2910 2773 | ::tracing::error!(error = %e, "failed to serialize response");
|
2911 2774 | ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0>::into_response(::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e))
|
2912 2775 | }
|
2913 2776 | }
|
2914 2777 | }
|
2915 2778 | }
|
2916 2779 |
|
2917 2780 | #[allow(unreachable_code, unused_variables)]
|
2918 2781 | #[cfg(test)]
|
2919 - | mod simple_scalar_properties_test {
|
2920 - |
|
2921 - | /// Supports handling NaN float values.
|
2922 - | /// Test ID: AwsJson10SupportsNaNFloatInputs
|
2923 - | #[::tokio::test]
|
2924 - | #[::tracing_test::traced_test]
|
2925 - | async fn aws_json10_supports_na_n_float_inputs_request() {
|
2926 - | #[allow(unused_mut)]
|
2927 - | let mut http_request = ::http_1x::Request::builder()
|
2928 - | .uri("/")
|
2929 - | .method("POST")
|
2930 - | .header("Content-Type", "application/x-amz-json-1.0")
|
2931 - | .header("X-Amz-Target", "JsonRpc10.SimpleScalarProperties")
|
2932 - | .body(::aws_smithy_http_server::body::boxed(
|
2933 - | ::http_body_util::Full::new(::bytes::Bytes::copy_from_slice(
|
2934 - | &::aws_smithy_protocol_test::decode_body_data(
|
2935 - | "{\n \"floatValue\": \"NaN\",\n \"doubleValue\": \"NaN\"\n}"
|
2936 - | .as_bytes(),
|
2937 - | ::aws_smithy_protocol_test::MediaType::from("application/json"),
|
2938 - | ),
|
2939 - | )),
|
2940 - | ))
|
2941 - | .unwrap();
|
2942 - | #[allow(unused_mut)]
|
2943 - | let (sender, mut receiver) = ::tokio::sync::mpsc::channel(1);
|
2944 - | let config = crate::service::JsonRpc10Config::builder().build();
|
2945 - | let service = crate::service::JsonRpc10::builder::<
|
2946 - | ::aws_smithy_http_server::body::BoxBody,
|
2947 - | _,
|
2948 - | _,
|
2949 - | _,
|
2950 - | >(config)
|
2951 - | .simple_scalar_properties(move |input: crate::input::SimpleScalarPropertiesInput| {
|
2952 - | let sender = sender.clone();
|
2953 - | async move {
|
2954 - | let result = {
|
2955 - | use ::aws_smithy_protocol_test::FloatEquals;
|
2956 - | let expected = crate::input::SimpleScalarPropertiesInput {
|
2957 - | float_value: ::std::option::Option::Some(
|
2958 - | <f32 as ::aws_smithy_types::primitive::Parse>::parse_smithy_primitive(
|
2959 - | "NaN",
|
2960 - | )
|
2961 - | .expect("invalid string for number"),
|
2962 - | ),
|
2963 - | double_value: ::std::option::Option::Some(
|
2964 - | <f64 as ::aws_smithy_types::primitive::Parse>::parse_smithy_primitive(
|
2965 - | "NaN",
|
2966 - | )
|
2967 - | .expect("invalid string for number"),
|
2968 - | ),
|
2969 - | };
|
2970 - | assert!(
|
2971 - | input.float_value.float_equals(&expected.float_value),
|
2972 - | "Unexpected value for `float_value` {:?} vs. {:?}",
|
2973 - | expected.float_value,
|
2974 - | input.float_value
|
2975 - | );
|
2976 - | assert!(
|
2977 - | input.double_value.float_equals(&expected.double_value),
|
2978 - | "Unexpected value for `double_value` {:?} vs. {:?}",
|
2979 - | expected.double_value,
|
2980 - | input.double_value
|
2981 - | );
|
2982 - | let output = crate::output::SimpleScalarPropertiesOutput {
|
2983 - | float_value: ::std::option::Option::None,
|
2984 - | double_value: ::std::option::Option::None,
|
2985 - | };
|
2986 - | output
|
2987 - | };
|
2988 - | sender.send(()).await.expect("receiver dropped early");
|
2989 - | result
|
2990 - | }
|
2991 - | })
|
2992 - | .build_unchecked();
|
2993 - | let http_response = ::tower::ServiceExt::oneshot(service, http_request)
|
2994 - | .await
|
2995 - | .expect("unable to make an HTTP request");
|
2996 - | assert!(
|
2997 - | receiver.recv().await.is_some(),
|
2998 - | "we expected operation handler to be invoked but it was not entered"
|
2999 - | );
|
3000 - | }
|
2782 + | mod content_type_parameters_test {
|
3001 2783 |
|
3002 - | /// Supports handling Infinity float values.
|
3003 - | /// Test ID: AwsJson10SupportsInfinityFloatInputs
|
2784 + | /// A server should ignore parameters added to the content type
|
2785 + | /// Test ID: AwsJson10MustSupportParametersInContentType
|
3004 2786 | #[::tokio::test]
|
3005 2787 | #[::tracing_test::traced_test]
|
3006 - | async fn aws_json10_supports_infinity_float_inputs_request() {
|
2788 + | async fn aws_json10_must_support_parameters_in_content_type_request() {
|
3007 2789 | #[allow(unused_mut)]
|
3008 2790 | let mut http_request = ::http_1x::Request::builder()
|
3009 2791 | .uri("/")
|
3010 2792 | .method("POST")
|
3011 - | .header("Content-Type", "application/x-amz-json-1.0")
|
3012 - | .header("X-Amz-Target", "JsonRpc10.SimpleScalarProperties")
|
3013 - | .body(::aws_smithy_http_server::body::boxed(::http_body_util::Full::new(
|
3014 - | ::bytes::Bytes::copy_from_slice(
|
3015 - | &::aws_smithy_protocol_test::decode_body_data("{\n \"floatValue\": \"Infinity\",\n \"doubleValue\": \"Infinity\"\n}".as_bytes(), ::aws_smithy_protocol_test::MediaType::from("application/json"))
|
3016 - | )
|
3017 - | ))).unwrap();
|
3018 - | #[allow(unused_mut)]
|
3019 - | let (sender, mut receiver) = ::tokio::sync::mpsc::channel(1);
|
3020 - | let config = crate::service::JsonRpc10Config::builder().build();
|
3021 - | let service = crate::service::JsonRpc10::builder::<
|
3022 - | ::aws_smithy_http_server::body::BoxBody,
|
3023 - | _,
|
3024 - | _,
|
3025 - | _,
|
3026 - | >(config)
|
3027 - | .simple_scalar_properties(move |input: crate::input::SimpleScalarPropertiesInput| {
|
3028 - | let sender = sender.clone();
|
3029 - | async move {
|
3030 - | let result = {
|
3031 - | use ::aws_smithy_protocol_test::FloatEquals;
|
3032 - | let expected = crate::input::SimpleScalarPropertiesInput {
|
3033 - | float_value: ::std::option::Option::Some(
|
3034 - | <f32 as ::aws_smithy_types::primitive::Parse>::parse_smithy_primitive(
|
3035 - | "Infinity",
|
3036 - | )
|
3037 - | .expect("invalid string for number"),
|
3038 - | ),
|
3039 - | double_value: ::std::option::Option::Some(
|
3040 - | <f64 as ::aws_smithy_types::primitive::Parse>::parse_smithy_primitive(
|
3041 - | "Infinity",
|
3042 - | )
|
3043 - | .expect("invalid string for number"),
|
3044 - | ),
|
3045 - | };
|
3046 - | assert!(
|
3047 - | input.float_value.float_equals(&expected.float_value),
|
3048 - | "Unexpected value for `float_value` {:?} vs. {:?}",
|
3049 - | expected.float_value,
|
3050 - | input.float_value
|
3051 - | );
|
3052 - | assert!(
|
3053 - | input.double_value.float_equals(&expected.double_value),
|
3054 - | "Unexpected value for `double_value` {:?} vs. {:?}",
|
3055 - | expected.double_value,
|
3056 - | input.double_value
|
3057 - | );
|
3058 - | let output = crate::output::SimpleScalarPropertiesOutput {
|
3059 - | float_value: ::std::option::Option::None,
|
3060 - | double_value: ::std::option::Option::None,
|
2793 + | .header("Content-Type", "application/x-amz-json-1.0; charset=utf-8")
|
2794 + | .header("X-Amz-Target", "JsonRpc10.ContentTypeParameters")
|
2795 + | .body(::aws_smithy_http_server::body::boxed(
|
2796 + | ::http_body_util::Full::new(::bytes::Bytes::copy_from_slice(
|
2797 + | &::aws_smithy_protocol_test::decode_body_data(
|
2798 + | "{\"value\":5}".as_bytes(),
|
2799 + | ::aws_smithy_protocol_test::MediaType::from("application/json"),
|
2800 + | ),
|
2801 + | )),
|
2802 + | ))
|
2803 + | .unwrap();
|
2804 + | #[allow(unused_mut)]
|
2805 + | let (sender, mut receiver) = ::tokio::sync::mpsc::channel(1);
|
2806 + | let config = crate::service::JsonRpc10Config::builder().build();
|
2807 + | let service =
|
2808 + | crate::service::JsonRpc10::builder::<::aws_smithy_http_server::body::BoxBody, _, _, _>(
|
2809 + | config,
|
2810 + | )
|
2811 + | .content_type_parameters(move |input: crate::input::ContentTypeParametersInput| {
|
2812 + | let sender = sender.clone();
|
2813 + | async move {
|
2814 + | let result = {
|
2815 + | let expected = crate::input::ContentTypeParametersInput {
|
2816 + | value: ::std::option::Option::Some(5),
|
3061 2817 | };
|
2818 + | ::pretty_assertions::assert_eq!(input, expected);
|
2819 + | let output = crate::output::ContentTypeParametersOutput {};
|
3062 2820 | output
|
3063 2821 | };
|
3064 2822 | sender.send(()).await.expect("receiver dropped early");
|
3065 2823 | result
|
3066 2824 | }
|
3067 2825 | })
|
3068 2826 | .build_unchecked();
|
3069 2827 | let http_response = ::tower::ServiceExt::oneshot(service, http_request)
|
3070 2828 | .await
|
3071 2829 | .expect("unable to make an HTTP request");
|
3072 2830 | assert!(
|
3073 2831 | receiver.recv().await.is_some(),
|
3074 2832 | "we expected operation handler to be invoked but it was not entered"
|
3075 2833 | );
|
3076 2834 | }
|
2835 + | }
|
3077 2836 |
|
3078 - | /// Supports handling -Infinity float values.
|
3079 - | /// Test ID: AwsJson10SupportsNegativeInfinityFloatInputs
|
2837 + | ::pin_project_lite::pin_project! {
|
2838 + | /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the
|
2839 + | /// [`OperationWithDefaultsInput`](crate::input::OperationWithDefaultsInput) using modelled bindings.
|
2840 + | pub struct OperationWithDefaultsInputFuture {
|
2841 + | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::OperationWithDefaultsInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
2842 + | }
|
2843 + | }
|
2844 + |
|
2845 + | impl std::future::Future for OperationWithDefaultsInputFuture {
|
2846 + | type Output = Result<
|
2847 + | crate::input::OperationWithDefaultsInput,
|
2848 + | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError,
|
2849 + | >;
|
2850 + |
|
2851 + | fn poll(
|
2852 + | self: std::pin::Pin<&mut Self>,
|
2853 + | cx: &mut std::task::Context<'_>,
|
2854 + | ) -> std::task::Poll<Self::Output> {
|
2855 + | let this = self.project();
|
2856 + | this.inner.as_mut().poll(cx)
|
2857 + | }
|
2858 + | }
|
2859 + |
|
2860 + | impl<B>
|
2861 + | ::aws_smithy_http_server::request::FromRequest<
|
2862 + | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
2863 + | B,
|
2864 + | > for crate::input::OperationWithDefaultsInput
|
2865 + | where
|
2866 + | B: ::aws_smithy_http_server::body::HttpBody + Send,
|
2867 + | B: 'static,
|
2868 + |
|
2869 + | B::Data: Send,
|
2870 + | ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection:
|
2871 + | From<<B as ::aws_smithy_http_server::body::HttpBody>::Error>,
|
2872 + | {
|
2873 + | type Rejection = ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError;
|
2874 + | type Future = OperationWithDefaultsInputFuture;
|
2875 + |
|
2876 + | fn from_request(request: ::http_1x::Request<B>) -> Self::Future {
|
2877 + | let fut = async move {
|
2878 + | if !::aws_smithy_http_server::protocol::accept_header_classifier(
|
2879 + | request.headers(),
|
2880 + | &crate::mimes::CONTENT_TYPE_APPLICATION_X_AMZ_JSON_1_0,
|
2881 + | ) {
|
2882 + | return Err(::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection::NotAcceptable);
|
2883 + | }
|
2884 + | crate::protocol_serde::shape_operation_with_defaults::de_operation_with_defaults_http_request(request)
|
2885 + | .await
|
2886 + | };
|
2887 + | use ::futures_util::future::TryFutureExt;
|
2888 + | let fut = fut.map_err(
|
2889 + | |e: ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection| {
|
2890 + | ::tracing::debug!(error = %e, "failed to deserialize request");
|
2891 + | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e)
|
2892 + | },
|
2893 + | );
|
2894 + | OperationWithDefaultsInputFuture {
|
2895 + | inner: Box::pin(fut),
|
2896 + | }
|
2897 + | }
|
2898 + | }
|
2899 + | impl
|
2900 + | ::aws_smithy_http_server::response::IntoResponse<
|
2901 + | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
2902 + | > for crate::output::OperationWithDefaultsOutput
|
2903 + | {
|
2904 + | fn into_response(self) -> ::aws_smithy_http_server::response::Response {
|
2905 + | match crate::protocol_serde::shape_operation_with_defaults::ser_operation_with_defaults_http_response(self) {
|
2906 + | Ok(response) => response,
|
2907 + | Err(e) => {
|
2908 + | ::tracing::error!(error = %e, "failed to serialize response");
|
2909 + | ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0>::into_response(::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e))
|
2910 + | }
|
2911 + | }
|
2912 + | }
|
2913 + | }
|
2914 + | impl
|
2915 + | ::aws_smithy_http_server::response::IntoResponse<
|
2916 + | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
2917 + | > for crate::error::OperationWithDefaultsError
|
2918 + | {
|
2919 + | fn into_response(self) -> ::aws_smithy_http_server::response::Response {
|
2920 + | match crate::protocol_serde::shape_operation_with_defaults::ser_operation_with_defaults_http_error(&self) {
|
2921 + | Ok(mut response) => {
|
2922 + | response.extensions_mut().insert(::aws_smithy_http_server::extension::ModeledErrorExtension::new(self.name()));
|
2923 + | response
|
2924 + | },
|
2925 + | Err(e) => {
|
2926 + | ::tracing::error!(error = %e, "failed to serialize response");
|
2927 + | ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0>::into_response(::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e))
|
2928 + | }
|
2929 + | }
|
2930 + | }
|
2931 + | }
|
2932 + |
|
2933 + | #[allow(unreachable_code, unused_variables)]
|
2934 + | #[cfg(test)]
|
2935 + | mod operation_with_defaults_test {
|
2936 + |
|
2937 + | /// Server populates default values when missing in request body.
|
2938 + | /// Test ID: AwsJson10ServerPopulatesDefaultsWhenMissingInRequestBody
|
3080 2939 | #[::tokio::test]
|
3081 2940 | #[::tracing_test::traced_test]
|
3082 - | async fn aws_json10_supports_negative_infinity_float_inputs_request() {
|
2941 + | #[should_panic]
|
2942 + | async fn aws_json10_server_populates_defaults_when_missing_in_request_body_request() {
|
3083 2943 | #[allow(unused_mut)]
|
3084 2944 | let mut http_request = ::http_1x::Request::builder()
|
3085 2945 | .uri("/")
|
3086 2946 | .method("POST")
|
3087 2947 | .header("Content-Type", "application/x-amz-json-1.0")
|
3088 - | .header("X-Amz-Target", "JsonRpc10.SimpleScalarProperties")
|
3089 - | .body(::aws_smithy_http_server::body::boxed(::http_body_util::Full::new(
|
3090 - | ::bytes::Bytes::copy_from_slice(
|
3091 - | &::aws_smithy_protocol_test::decode_body_data("{\n \"floatValue\": \"-Infinity\",\n \"doubleValue\": \"-Infinity\"\n}".as_bytes(), ::aws_smithy_protocol_test::MediaType::from("application/json"))
|
3092 - | )
|
3093 - | ))).unwrap();
|
2948 + | .body(::aws_smithy_http_server::body::boxed(
|
2949 + | ::http_body_util::Full::new(::bytes::Bytes::copy_from_slice(
|
2950 + | &::aws_smithy_protocol_test::decode_body_data(
|
2951 + | "{\n\"defaults\": {}\n}".as_bytes(),
|
2952 + | ::aws_smithy_protocol_test::MediaType::from("application/json"),
|
2953 + | ),
|
2954 + | )),
|
2955 + | ))
|
2956 + | .unwrap();
|
3094 2957 | #[allow(unused_mut)]
|
3095 2958 | let (sender, mut receiver) = ::tokio::sync::mpsc::channel(1);
|
3096 2959 | let config = crate::service::JsonRpc10Config::builder().build();
|
3097 2960 | let service = crate::service::JsonRpc10::builder::<
|
3098 2961 | ::aws_smithy_http_server::body::BoxBody,
|
3099 2962 | _,
|
3100 2963 | _,
|
3101 2964 | _,
|
3102 2965 | >(config)
|
3103 - | .simple_scalar_properties(move |input: crate::input::SimpleScalarPropertiesInput| {
|
2966 + | .operation_with_defaults(move |input: crate::input::OperationWithDefaultsInput| {
|
3104 2967 | let sender = sender.clone();
|
3105 2968 | async move {
|
3106 2969 | let result = {
|
3107 - | use ::aws_smithy_protocol_test::FloatEquals;
|
3108 - | let expected = crate::input::SimpleScalarPropertiesInput {
|
3109 - | float_value: ::std::option::Option::Some(
|
3110 - | <f32 as ::aws_smithy_types::primitive::Parse>::parse_smithy_primitive(
|
3111 - | "-Infinity",
|
3112 - | )
|
3113 - | .expect("invalid string for number"),
|
2970 + | let expected = crate::input::OperationWithDefaultsInput {
|
2971 + | defaults: ::std::option::Option::Some(crate::model::Defaults {
|
2972 + | default_string: "hi".to_owned(),
|
2973 + | default_boolean: true,
|
2974 + | default_list: vec![],
|
2975 + | default_document_map: {
|
2976 + | let json_bytes = br#"{}"#;
|
2977 + | let mut tokens =
|
2978 + | ::aws_smithy_json::deserialize::json_token_iter(json_bytes)
|
2979 + | .peekable();
|
2980 + | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
2981 + | .expect("well formed json")
|
2982 + | },
|
2983 + | default_document_string: {
|
2984 + | let json_bytes = br#""hi""#;
|
2985 + | let mut tokens =
|
2986 + | ::aws_smithy_json::deserialize::json_token_iter(json_bytes)
|
2987 + | .peekable();
|
2988 + | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
2989 + | .expect("well formed json")
|
2990 + | },
|
2991 + | default_document_boolean: {
|
2992 + | let json_bytes = br#"true"#;
|
2993 + | let mut tokens =
|
2994 + | ::aws_smithy_json::deserialize::json_token_iter(json_bytes)
|
2995 + | .peekable();
|
2996 + | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
2997 + | .expect("well formed json")
|
2998 + | },
|
2999 + | default_document_list: {
|
3000 + | let json_bytes = br#"[]"#;
|
3001 + | let mut tokens =
|
3002 + | ::aws_smithy_json::deserialize::json_token_iter(json_bytes)
|
3003 + | .peekable();
|
3004 + | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
3005 + | .expect("well formed json")
|
3006 + | },
|
3007 + | default_timestamp: ::aws_smithy_types::DateTime::from_fractional_secs(
|
3008 + | 0, 0_f64,
|
3114 3009 | ),
|
3115 - | double_value: ::std::option::Option::Some(
|
3116 - | <f64 as ::aws_smithy_types::primitive::Parse>::parse_smithy_primitive(
|
3117 - | "-Infinity",
|
3118 - | )
|
3119 - | .expect("invalid string for number"),
|
3010 + | default_blob: ::aws_smithy_types::Blob::new("abc"),
|
3011 + | default_byte: 1,
|
3012 + | default_short: 1,
|
3013 + | default_integer: 10,
|
3014 + | default_long: 100,
|
3015 + | default_float: 1.0_f32,
|
3016 + | default_double: 1.0_f64,
|
3017 + | default_map: ::std::collections::HashMap::new(),
|
3018 + | default_enum: "FOO"
|
3019 + | .parse::<crate::model::TestEnum>()
|
3020 + | .expect("static value validated to member"),
|
3021 + | default_int_enum: 1,
|
3022 + | empty_string: "".to_owned(),
|
3023 + | false_boolean: false,
|
3024 + | empty_blob: ::aws_smithy_types::Blob::new(""),
|
3025 + | zero_byte: 0,
|
3026 + | zero_short: 0,
|
3027 + | zero_integer: 0,
|
3028 + | zero_long: 0,
|
3029 + | zero_float: 0.0_f32,
|
3030 + | zero_double: 0.0_f64,
|
3031 + | default_null_document: ::std::option::Option::Some({
|
3032 + | let json_bytes = br#"null"#;
|
3033 + | let mut tokens =
|
3034 + | ::aws_smithy_json::deserialize::json_token_iter(json_bytes)
|
3035 + | .peekable();
|
3036 + | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
3037 + | .expect("well formed json")
|
3038 + | }),
|
3039 + | }),
|
3040 + | top_level_default: "hi".to_owned(),
|
3041 + | other_top_level_default: 0,
|
3042 + | client_optional_defaults: ::std::option::Option::None,
|
3043 + | };
|
3044 + | ::pretty_assertions::assert_eq!(input, expected);
|
3045 + | let output = crate::output::OperationWithDefaultsOutput {
|
3046 + | default_string: "".to_owned(),
|
3047 + | default_boolean: false,
|
3048 + | default_list: vec![],
|
3049 + | default_document_map: {
|
3050 + | let json_bytes = br#"{}"#;
|
3051 + | let mut tokens =
|
3052 + | ::aws_smithy_json::deserialize::json_token_iter(json_bytes)
|
3053 + | .peekable();
|
3054 + | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
3055 + | .expect("well formed json")
|
3056 + | },
|
3057 + | default_document_string: {
|
3058 + | let json_bytes = br#"{}"#;
|
3059 + | let mut tokens =
|
3060 + | ::aws_smithy_json::deserialize::json_token_iter(json_bytes)
|
3061 + | .peekable();
|
3062 + | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
3063 + | .expect("well formed json")
|
3064 + | },
|
3065 + | default_document_boolean: {
|
3066 + | let json_bytes = br#"{}"#;
|
3067 + | let mut tokens =
|
3068 + | ::aws_smithy_json::deserialize::json_token_iter(json_bytes)
|
3069 + | .peekable();
|
3070 + | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
3071 + | .expect("well formed json")
|
3072 + | },
|
3073 + | default_document_list: {
|
3074 + | let json_bytes = br#"{}"#;
|
3075 + | let mut tokens =
|
3076 + | ::aws_smithy_json::deserialize::json_token_iter(json_bytes)
|
3077 + | .peekable();
|
3078 + | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
3079 + | .expect("well formed json")
|
3080 + | },
|
3081 + | default_timestamp: ::aws_smithy_types::DateTime::from_fractional_secs(
|
3082 + | 0, 0_f64,
|
3120 3083 | ),
|
3084 + | default_blob: ::aws_smithy_types::Blob::new(""),
|
3085 + | default_byte: 0,
|
3086 + | default_short: 0,
|
3087 + | default_integer: 0,
|
3088 + | default_long: 0,
|
3089 + | default_float: 0_f32,
|
3090 + | default_double: 0_f64,
|
3091 + | default_map: ::std::collections::HashMap::new(),
|
3092 + | default_enum: ""
|
3093 + | .parse::<crate::model::TestEnum>()
|
3094 + | .expect("static value validated to member"),
|
3095 + | default_int_enum: 0,
|
3096 + | empty_string: "".to_owned(),
|
3097 + | false_boolean: false,
|
3098 + | empty_blob: ::aws_smithy_types::Blob::new(""),
|
3099 + | zero_byte: 0,
|
3100 + | zero_short: 0,
|
3101 + | zero_integer: 0,
|
3102 + | zero_long: 0,
|
3103 + | zero_float: 0_f32,
|
3104 + | zero_double: 0_f64,
|
3105 + | default_null_document: ::std::option::Option::Some({
|
3106 + | let json_bytes = br#"null"#;
|
3107 + | let mut tokens =
|
3108 + | ::aws_smithy_json::deserialize::json_token_iter(json_bytes)
|
3109 + | .peekable();
|
3110 + | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
3111 + | .expect("well formed json")
|
3112 + | }),
|
3121 3113 | };
|
3122 - | assert!(
|
3123 - | input.float_value.float_equals(&expected.float_value),
|
3124 - | "Unexpected value for `float_value` {:?} vs. {:?}",
|
3125 - | expected.float_value,
|
3126 - | input.float_value
|
3127 - | );
|
3128 - | assert!(
|
3129 - | input.double_value.float_equals(&expected.double_value),
|
3130 - | "Unexpected value for `double_value` {:?} vs. {:?}",
|
3131 - | expected.double_value,
|
3132 - | input.double_value
|
3133 - | );
|
3134 - | let output = crate::output::SimpleScalarPropertiesOutput {
|
3135 - | float_value: ::std::option::Option::None,
|
3136 - | double_value: ::std::option::Option::None,
|
3137 - | };
|
3138 - | output
|
3114 + | Ok(output)
|
3139 3115 | };
|
3140 3116 | sender.send(()).await.expect("receiver dropped early");
|
3141 3117 | result
|
3142 3118 | }
|
3143 3119 | })
|
3144 3120 | .build_unchecked();
|
3145 3121 | let http_response = ::tower::ServiceExt::oneshot(service, http_request)
|
3146 3122 | .await
|
3147 3123 | .expect("unable to make an HTTP request");
|
3148 3124 | assert!(
|
3149 3125 | receiver.recv().await.is_some(),
|
3150 3126 | "we expected operation handler to be invoked but it was not entered"
|
3151 3127 | );
|
3152 3128 | }
|
3153 3129 |
|
3154 - | /// Supports handling NaN float values.
|
3155 - | /// Test ID: AwsJson10SupportsNaNFloatInputs
|
3130 + | /// Server populates default values in response when missing in params.
|
3131 + | /// Test ID: AwsJson10ServerPopulatesDefaultsInResponseWhenMissingInParams
|
3156 3132 | #[::tokio::test]
|
3157 3133 | #[::tracing_test::traced_test]
|
3158 - | async fn aws_json10_supports_na_n_float_inputs_response() {
|
3159 - | let output = crate::output::SimpleScalarPropertiesOutput {
|
3160 - | float_value: ::std::option::Option::Some(
|
3161 - | <f32 as ::aws_smithy_types::primitive::Parse>::parse_smithy_primitive("NaN")
|
3162 - | .expect("invalid string for number"),
|
3163 - | ),
|
3164 - | double_value: ::std::option::Option::Some(
|
3165 - | <f64 as ::aws_smithy_types::primitive::Parse>::parse_smithy_primitive("NaN")
|
3166 - | .expect("invalid string for number"),
|
3167 - | ),
|
3134 + | #[should_panic]
|
3135 + | async fn aws_json10_server_populates_defaults_in_response_when_missing_in_params_response() {
|
3136 + | let output = crate::output::OperationWithDefaultsOutput {
|
3137 + | default_string: "".to_owned(),
|
3138 + | default_boolean: false,
|
3139 + | default_list: vec![],
|
3140 + | default_document_map: {
|
3141 + | let json_bytes = br#"{}"#;
|
3142 + | let mut tokens =
|
3143 + | ::aws_smithy_json::deserialize::json_token_iter(json_bytes).peekable();
|
3144 + | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
3145 + | .expect("well formed json")
|
3146 + | },
|
3147 + | default_document_string: {
|
3148 + | let json_bytes = br#"{}"#;
|
3149 + | let mut tokens =
|
3150 + | ::aws_smithy_json::deserialize::json_token_iter(json_bytes).peekable();
|
3151 + | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
3152 + | .expect("well formed json")
|
3153 + | },
|
3154 + | default_document_boolean: {
|
3155 + | let json_bytes = br#"{}"#;
|
3156 + | let mut tokens =
|
3157 + | ::aws_smithy_json::deserialize::json_token_iter(json_bytes).peekable();
|
3158 + | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
3159 + | .expect("well formed json")
|
3160 + | },
|
3161 + | default_document_list: {
|
3162 + | let json_bytes = br#"{}"#;
|
3163 + | let mut tokens =
|
3164 + | ::aws_smithy_json::deserialize::json_token_iter(json_bytes).peekable();
|
3165 + | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
3166 + | .expect("well formed json")
|
3167 + | },
|
3168 + | default_timestamp: ::aws_smithy_types::DateTime::from_fractional_secs(0, 0_f64),
|
3169 + | default_blob: ::aws_smithy_types::Blob::new(""),
|
3170 + | default_byte: 0,
|
3171 + | default_short: 0,
|
3172 + | default_integer: 0,
|
3173 + | default_long: 0,
|
3174 + | default_float: 0_f32,
|
3175 + | default_double: 0_f64,
|
3176 + | default_map: ::std::collections::HashMap::new(),
|
3177 + | default_enum: ""
|
3178 + | .parse::<crate::model::TestEnum>()
|
3179 + | .expect("static value validated to member"),
|
3180 + | default_int_enum: 0,
|
3181 + | empty_string: "".to_owned(),
|
3182 + | false_boolean: false,
|
3183 + | empty_blob: ::aws_smithy_types::Blob::new(""),
|
3184 + | zero_byte: 0,
|
3185 + | zero_short: 0,
|
3186 + | zero_integer: 0,
|
3187 + | zero_long: 0,
|
3188 + | zero_float: 0_f32,
|
3189 + | zero_double: 0_f64,
|
3190 + | default_null_document: ::std::option::Option::Some({
|
3191 + | let json_bytes = br#"null"#;
|
3192 + | let mut tokens =
|
3193 + | ::aws_smithy_json::deserialize::json_token_iter(json_bytes).peekable();
|
3194 + | ::aws_smithy_json::deserialize::token::expect_document(&mut tokens)
|
3195 + | .expect("well formed json")
|
3196 + | }),
|
3168 3197 | };
|
3169 3198 | use ::aws_smithy_http_server::response::IntoResponse;
|
3170 3199 | let http_response = output.into_response();
|
3171 3200 | ::pretty_assertions::assert_eq!(
|
3172 3201 | ::http_1x::StatusCode::from_u16(200).expect("invalid expected HTTP status code"),
|
3173 3202 | http_response.status()
|
3174 3203 | );
|
3175 3204 | let expected_headers = [("Content-Type", "application/x-amz-json-1.0")];
|
3176 3205 | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_headers(
|
3177 3206 | http_response.headers(),
|
3178 3207 | expected_headers,
|
3179 3208 | ));
|
3180 3209 | use ::http_body_util::BodyExt;
|
3181 3210 | let body = http_response
|
3182 3211 | .into_body()
|
3183 3212 | .collect()
|
3184 3213 | .await
|
3185 3214 | .expect("unable to collect body")
|
3186 3215 | .to_bytes();
|
3187 - | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_body(
|
3188 - | &body,
|
3189 - | "{\n \"floatValue\": \"NaN\",\n \"doubleValue\": \"NaN\"\n}",
|
3190 - | ::aws_smithy_protocol_test::MediaType::from("application/json"),
|
3191 - | ));
|
3216 + | ::aws_smithy_protocol_test::assert_ok(
|
3217 + | ::aws_smithy_protocol_test::validate_body(&body, "{\n \"defaultString\": \"hi\",\n \"defaultBoolean\": true,\n \"defaultList\": [],\n \"defaultDocumentMap\": {},\n \"defaultDocumentString\": \"hi\",\n \"defaultDocumentBoolean\": true,\n \"defaultDocumentList\": [],\n \"defaultTimestamp\": 0,\n \"defaultBlob\": \"YWJj\",\n \"defaultByte\": 1,\n \"defaultShort\": 1,\n \"defaultInteger\": 10,\n \"defaultLong\": 100,\n \"defaultFloat\": 1.0,\n \"defaultDouble\": 1.0,\n \"defaultMap\": {},\n \"defaultEnum\": \"FOO\",\n \"defaultIntEnum\": 1,\n \"emptyString\": \"\",\n \"falseBoolean\": false,\n \"emptyBlob\": \"\",\n \"zeroByte\": 0,\n \"zeroShort\": 0,\n \"zeroInteger\": 0,\n \"zeroLong\": 0,\n \"zeroFloat\": 0.0,\n \"zeroDouble\": 0.0\n}", ::aws_smithy_protocol_test::MediaType::from("application/json"))
|
3218 + | );
|
3192 3219 | }
|
3220 + | }
|
3193 3221 |
|
3194 - | /// Supports handling Infinity float values.
|
3195 - | /// Test ID: AwsJson10SupportsInfinityFloatInputs
|
3196 - | #[::tokio::test]
|
3197 - | #[::tracing_test::traced_test]
|
3198 - | async fn aws_json10_supports_infinity_float_inputs_response() {
|
3199 - | let output = crate::output::SimpleScalarPropertiesOutput {
|
3200 - | float_value: ::std::option::Option::Some(
|
3201 - | <f32 as ::aws_smithy_types::primitive::Parse>::parse_smithy_primitive("Infinity")
|
3202 - | .expect("invalid string for number"),
|
3203 - | ),
|
3204 - | double_value: ::std::option::Option::Some(
|
3205 - | <f64 as ::aws_smithy_types::primitive::Parse>::parse_smithy_primitive("Infinity")
|
3206 - | .expect("invalid string for number"),
|
3207 - | ),
|
3208 - | };
|
3209 - | use ::aws_smithy_http_server::response::IntoResponse;
|
3210 - | let http_response = output.into_response();
|
3211 - | ::pretty_assertions::assert_eq!(
|
3212 - | ::http_1x::StatusCode::from_u16(200).expect("invalid expected HTTP status code"),
|
3213 - | http_response.status()
|
3214 - | );
|
3215 - | let expected_headers = [("Content-Type", "application/x-amz-json-1.0")];
|
3216 - | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_headers(
|
3217 - | http_response.headers(),
|
3218 - | expected_headers,
|
3219 - | ));
|
3220 - | use ::http_body_util::BodyExt;
|
3221 - | let body = http_response
|
3222 - | .into_body()
|
3223 - | .collect()
|
3224 - | .await
|
3225 - | .expect("unable to collect body")
|
3226 - | .to_bytes();
|
3227 - | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_body(
|
3228 - | &body,
|
3229 - | "{\n \"floatValue\": \"Infinity\",\n \"doubleValue\": \"Infinity\"\n}",
|
3230 - | ::aws_smithy_protocol_test::MediaType::from("application/json"),
|
3231 - | ));
|
3222 + | ::pin_project_lite::pin_project! {
|
3223 + | /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the
|
3224 + | /// [`OperationWithRequiredMembersInput`](crate::input::OperationWithRequiredMembersInput) using modelled bindings.
|
3225 + | pub struct OperationWithRequiredMembersInputFuture {
|
3226 + | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::OperationWithRequiredMembersInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
3232 3227 | }
|
3228 + | }
|
3233 3229 |
|
3234 - | /// Supports handling -Infinity float values.
|
3235 - | /// Test ID: AwsJson10SupportsNegativeInfinityFloatInputs
|
3236 - | #[::tokio::test]
|
3237 - | #[::tracing_test::traced_test]
|
3238 - | async fn aws_json10_supports_negative_infinity_float_inputs_response() {
|
3239 - | let output = crate::output::SimpleScalarPropertiesOutput {
|
3240 - | float_value: ::std::option::Option::Some(
|
3241 - | <f32 as ::aws_smithy_types::primitive::Parse>::parse_smithy_primitive("-Infinity")
|
3242 - | .expect("invalid string for number"),
|
3243 - | ),
|
3244 - | double_value: ::std::option::Option::Some(
|
3245 - | <f64 as ::aws_smithy_types::primitive::Parse>::parse_smithy_primitive("-Infinity")
|
3246 - | .expect("invalid string for number"),
|
3247 - | ),
|
3248 - | };
|
3249 - | use ::aws_smithy_http_server::response::IntoResponse;
|
3250 - | let http_response = output.into_response();
|
3251 - | ::pretty_assertions::assert_eq!(
|
3252 - | ::http_1x::StatusCode::from_u16(200).expect("invalid expected HTTP status code"),
|
3253 - | http_response.status()
|
3254 - | );
|
3255 - | let expected_headers = [("Content-Type", "application/x-amz-json-1.0")];
|
3256 - | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_headers(
|
3257 - | http_response.headers(),
|
3258 - | expected_headers,
|
3259 - | ));
|
3260 - | use ::http_body_util::BodyExt;
|
3261 - | let body = http_response
|
3262 - | .into_body()
|
3263 - | .collect()
|
3230 + | impl std::future::Future for OperationWithRequiredMembersInputFuture {
|
3231 + | type Output = Result<
|
3232 + | crate::input::OperationWithRequiredMembersInput,
|
3233 + | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError,
|
3234 + | >;
|
3235 + |
|
3236 + | fn poll(
|
3237 + | self: std::pin::Pin<&mut Self>,
|
3238 + | cx: &mut std::task::Context<'_>,
|
3239 + | ) -> std::task::Poll<Self::Output> {
|
3240 + | let this = self.project();
|
3241 + | this.inner.as_mut().poll(cx)
|
3242 + | }
|
3243 + | }
|
3244 + |
|
3245 + | impl<B>
|
3246 + | ::aws_smithy_http_server::request::FromRequest<
|
3247 + | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
3248 + | B,
|
3249 + | > for crate::input::OperationWithRequiredMembersInput
|
3250 + | where
|
3251 + | B: ::aws_smithy_http_server::body::HttpBody + Send,
|
3252 + | B: 'static,
|
3253 + |
|
3254 + | B::Data: Send,
|
3255 + | ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection:
|
3256 + | From<<B as ::aws_smithy_http_server::body::HttpBody>::Error>,
|
3257 + | {
|
3258 + | type Rejection = ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError;
|
3259 + | type Future = OperationWithRequiredMembersInputFuture;
|
3260 + |
|
3261 + | fn from_request(request: ::http_1x::Request<B>) -> Self::Future {
|
3262 + | let fut = async move {
|
3263 + | if !::aws_smithy_http_server::protocol::accept_header_classifier(
|
3264 + | request.headers(),
|
3265 + | &crate::mimes::CONTENT_TYPE_APPLICATION_X_AMZ_JSON_1_0,
|
3266 + | ) {
|
3267 + | return Err(::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection::NotAcceptable);
|
3268 + | }
|
3269 + | crate::protocol_serde::shape_operation_with_required_members::de_operation_with_required_members_http_request(request)
|
3264 3270 | .await
|
3265 - | .expect("unable to collect body")
|
3266 - | .to_bytes();
|
3267 - | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_body(
|
3268 - | &body,
|
3269 - | "{\n \"floatValue\": \"-Infinity\",\n \"doubleValue\": \"-Infinity\"\n}",
|
3270 - | ::aws_smithy_protocol_test::MediaType::from("application/json"),
|
3271 - | ));
|
3271 + | };
|
3272 + | use ::futures_util::future::TryFutureExt;
|
3273 + | let fut = fut.map_err(
|
3274 + | |e: ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection| {
|
3275 + | ::tracing::debug!(error = %e, "failed to deserialize request");
|
3276 + | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e)
|
3277 + | },
|
3278 + | );
|
3279 + | OperationWithRequiredMembersInputFuture {
|
3280 + | inner: Box::pin(fut),
|
3281 + | }
|
3282 + | }
|
3283 + | }
|
3284 + | impl
|
3285 + | ::aws_smithy_http_server::response::IntoResponse<
|
3286 + | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
3287 + | > for crate::output::OperationWithRequiredMembersOutput
|
3288 + | {
|
3289 + | fn into_response(self) -> ::aws_smithy_http_server::response::Response {
|
3290 + | match crate::protocol_serde::shape_operation_with_required_members::ser_operation_with_required_members_http_response(self) {
|
3291 + | Ok(response) => response,
|
3292 + | Err(e) => {
|
3293 + | ::tracing::error!(error = %e, "failed to serialize response");
|
3294 + | ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0>::into_response(::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e))
|
3295 + | }
|
3296 + | }
|
3272 3297 | }
|
3273 3298 | }
|
3274 3299 |
|
3275 3300 | ::pin_project_lite::pin_project! {
|
3276 3301 | /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the
|
3277 - | /// [`EmptyInputAndEmptyOutputInput`](crate::input::EmptyInputAndEmptyOutputInput) using modelled bindings.
|
3278 - | pub struct EmptyInputAndEmptyOutputInputFuture {
|
3279 - | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::EmptyInputAndEmptyOutputInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
3302 + | /// [`OperationWithNestedStructureInput`](crate::input::OperationWithNestedStructureInput) using modelled bindings.
|
3303 + | pub struct OperationWithNestedStructureInputFuture {
|
3304 + | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::OperationWithNestedStructureInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
3280 3305 | }
|
3281 3306 | }
|
3282 3307 |
|
3283 - | impl std::future::Future for EmptyInputAndEmptyOutputInputFuture {
|
3308 + | impl std::future::Future for OperationWithNestedStructureInputFuture {
|
3284 3309 | type Output = Result<
|
3285 - | crate::input::EmptyInputAndEmptyOutputInput,
|
3310 + | crate::input::OperationWithNestedStructureInput,
|
3286 3311 | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError,
|
3287 3312 | >;
|
3288 3313 |
|
3289 3314 | fn poll(
|
3290 3315 | self: std::pin::Pin<&mut Self>,
|
3291 3316 | cx: &mut std::task::Context<'_>,
|
3292 3317 | ) -> std::task::Poll<Self::Output> {
|
3293 3318 | let this = self.project();
|
3294 3319 | this.inner.as_mut().poll(cx)
|
3295 3320 | }
|
3296 3321 | }
|
3297 3322 |
|
3298 3323 | impl<B>
|
3299 3324 | ::aws_smithy_http_server::request::FromRequest<
|
3300 3325 | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
3301 3326 | B,
|
3302 - | > for crate::input::EmptyInputAndEmptyOutputInput
|
3327 + | > for crate::input::OperationWithNestedStructureInput
|
3303 3328 | where
|
3304 3329 | B: ::aws_smithy_http_server::body::HttpBody + Send,
|
3305 3330 | B: 'static,
|
3306 3331 |
|
3307 3332 | B::Data: Send,
|
3308 3333 | ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection:
|
3309 3334 | From<<B as ::aws_smithy_http_server::body::HttpBody>::Error>,
|
3310 3335 | {
|
3311 3336 | type Rejection = ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError;
|
3312 - | type Future = EmptyInputAndEmptyOutputInputFuture;
|
3337 + | type Future = OperationWithNestedStructureInputFuture;
|
3313 3338 |
|
3314 3339 | fn from_request(request: ::http_1x::Request<B>) -> Self::Future {
|
3315 3340 | let fut = async move {
|
3316 3341 | if !::aws_smithy_http_server::protocol::accept_header_classifier(
|
3317 3342 | request.headers(),
|
3318 3343 | &crate::mimes::CONTENT_TYPE_APPLICATION_X_AMZ_JSON_1_0,
|
3319 3344 | ) {
|
3320 3345 | return Err(::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection::NotAcceptable);
|
3321 3346 | }
|
3322 - | crate::protocol_serde::shape_empty_input_and_empty_output::de_empty_input_and_empty_output_http_request(request)
|
3347 + | crate::protocol_serde::shape_operation_with_nested_structure::de_operation_with_nested_structure_http_request(request)
|
3323 3348 | .await
|
3324 3349 | };
|
3325 3350 | use ::futures_util::future::TryFutureExt;
|
3326 3351 | let fut = fut.map_err(
|
3327 3352 | |e: ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection| {
|
3328 3353 | ::tracing::debug!(error = %e, "failed to deserialize request");
|
3329 3354 | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e)
|
3330 3355 | },
|
3331 3356 | );
|
3332 - | EmptyInputAndEmptyOutputInputFuture {
|
3357 + | OperationWithNestedStructureInputFuture {
|
3333 3358 | inner: Box::pin(fut),
|
3334 3359 | }
|
3335 3360 | }
|
3336 3361 | }
|
3337 3362 | impl
|
3338 3363 | ::aws_smithy_http_server::response::IntoResponse<
|
3339 3364 | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
3340 - | > for crate::output::EmptyInputAndEmptyOutputOutput
|
3365 + | > for crate::output::OperationWithNestedStructureOutput
|
3341 3366 | {
|
3342 3367 | fn into_response(self) -> ::aws_smithy_http_server::response::Response {
|
3343 - | match crate::protocol_serde::shape_empty_input_and_empty_output::ser_empty_input_and_empty_output_http_response(self) {
|
3368 + | match crate::protocol_serde::shape_operation_with_nested_structure::ser_operation_with_nested_structure_http_response(self) {
|
3344 3369 | Ok(response) => response,
|
3345 3370 | Err(e) => {
|
3346 3371 | ::tracing::error!(error = %e, "failed to serialize response");
|
3347 3372 | ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0>::into_response(::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e))
|
3348 3373 | }
|
3349 3374 | }
|
3350 3375 | }
|
3351 3376 | }
|
3377 + | impl
|
3378 + | ::aws_smithy_http_server::response::IntoResponse<
|
3379 + | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
3380 + | > for crate::error::OperationWithNestedStructureError
|
3381 + | {
|
3382 + | fn into_response(self) -> ::aws_smithy_http_server::response::Response {
|
3383 + | match crate::protocol_serde::shape_operation_with_nested_structure::ser_operation_with_nested_structure_http_error(&self) {
|
3384 + | Ok(mut response) => {
|
3385 + | response.extensions_mut().insert(::aws_smithy_http_server::extension::ModeledErrorExtension::new(self.name()));
|
3386 + | response
|
3387 + | },
|
3388 + | Err(e) => {
|
3389 + | ::tracing::error!(error = %e, "failed to serialize response");
|
3390 + | ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0>::into_response(::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e))
|
3391 + | }
|
3392 + | }
|
3393 + | }
|
3394 + | }
|
3352 3395 |
|
3353 3396 | #[allow(unreachable_code, unused_variables)]
|
3354 3397 | #[cfg(test)]
|
3355 - | mod empty_input_and_empty_output_test {
|
3398 + | mod operation_with_nested_structure_test {
|
3356 3399 |
|
3357 - | /// Clients must always send an empty object if input is modeled.
|
3358 - | /// Test ID: AwsJson10EmptyInputAndEmptyOutput
|
3400 + | /// Server populates nested default values when missing in request body.
|
3401 + | /// Test ID: AwsJson10ServerPopulatesNestedDefaultsWhenMissingInRequestBody
|
3359 3402 | #[::tokio::test]
|
3360 3403 | #[::tracing_test::traced_test]
|
3361 - | async fn aws_json10_empty_input_and_empty_output_request() {
|
3404 + | #[should_panic]
|
3405 + | async fn aws_json10_server_populates_nested_defaults_when_missing_in_request_body_request() {
|
3362 3406 | #[allow(unused_mut)]
|
3363 3407 | let mut http_request = ::http_1x::Request::builder()
|
3364 3408 | .uri("/")
|
3365 3409 | .method("POST")
|
3366 3410 | .header("Content-Type", "application/x-amz-json-1.0")
|
3367 - | .header("X-Amz-Target", "JsonRpc10.EmptyInputAndEmptyOutput")
|
3368 - | .body(::aws_smithy_http_server::body::boxed(
|
3369 - | ::http_body_util::Full::new(::bytes::Bytes::copy_from_slice(
|
3370 - | &::aws_smithy_protocol_test::decode_body_data(
|
3371 - | "{}".as_bytes(),
|
3372 - | ::aws_smithy_protocol_test::MediaType::from("application/json"),
|
3373 - | ),
|
3374 - | )),
|
3375 - | ))
|
3376 - | .unwrap();
|
3411 + | .body(::aws_smithy_http_server::body::boxed(::http_body_util::Full::new(
|
3412 + | ::bytes::Bytes::copy_from_slice(
|
3413 + | &::aws_smithy_protocol_test::decode_body_data("{\n \"topLevel\": {\n \"dialog\": {\n \"language\": \"en\"\n },\n \"dialogList\": [\n {\n },\n {\n \"farewell\": {}\n },\n {\n \"language\": \"it\",\n \"greeting\": \"ciao\",\n \"farewell\": {\n \"phrase\": \"arrivederci\"\n }\n }\n ],\n \"dialogMap\": {\n \"emptyDialog\": {\n },\n \"partialEmptyDialog\": {\n \"language\": \"en\",\n \"farewell\": {}\n },\n \"nonEmptyDialog\": {\n \"greeting\": \"konnichiwa\",\n \"farewell\": {\n \"phrase\": \"sayonara\"\n }\n }\n }\n }\n}".as_bytes(), ::aws_smithy_protocol_test::MediaType::from("application/json"))
|
3414 + | )
|
3415 + | ))).unwrap();
|
3377 3416 | #[allow(unused_mut)]
|
3378 3417 | let (sender, mut receiver) = ::tokio::sync::mpsc::channel(1);
|
3379 3418 | let config = crate::service::JsonRpc10Config::builder().build();
|
3380 3419 | let service = crate::service::JsonRpc10::builder::<
|
3381 3420 | ::aws_smithy_http_server::body::BoxBody,
|
3382 3421 | _,
|
3383 3422 | _,
|
3384 3423 | _,
|
3385 3424 | >(config)
|
3386 - | .empty_input_and_empty_output(move |input: crate::input::EmptyInputAndEmptyOutputInput| {
|
3425 + | .operation_with_nested_structure(
|
3426 + | move |input: crate::input::OperationWithNestedStructureInput| {
|
3387 3427 | let sender = sender.clone();
|
3388 3428 | async move {
|
3389 3429 | let result = {
|
3390 - | let expected = crate::input::EmptyInputAndEmptyOutputInput {};
|
3430 + | let expected = crate::input::OperationWithNestedStructureInput {
|
3431 + | top_level: crate::model::TopLevel {
|
3432 + | dialog: crate::model::Dialog {
|
3433 + | language: ::std::option::Option::Some("en".to_owned()),
|
3434 + | greeting: "hi".to_owned(),
|
3435 + | farewell: ::std::option::Option::None,
|
3436 + | },
|
3437 + | dialog_list: vec![
|
3438 + | crate::model::Dialog {
|
3439 + | greeting: "hi".to_owned(),
|
3440 + | language: ::std::option::Option::None,
|
3441 + | farewell: ::std::option::Option::None,
|
3442 + | },
|
3443 + | crate::model::Dialog {
|
3444 + | greeting: "hi".to_owned(),
|
3445 + | farewell: ::std::option::Option::Some(
|
3446 + | crate::model::Farewell {
|
3447 + | phrase: "bye".to_owned(),
|
3448 + | },
|
3449 + | ),
|
3450 + | language: ::std::option::Option::None,
|
3451 + | },
|
3452 + | crate::model::Dialog {
|
3453 + | language: ::std::option::Option::Some("it".to_owned()),
|
3454 + | greeting: "ciao".to_owned(),
|
3455 + | farewell: ::std::option::Option::Some(
|
3456 + | crate::model::Farewell {
|
3457 + | phrase: "arrivederci".to_owned(),
|
3458 + | },
|
3459 + | ),
|
3460 + | },
|
3461 + | ],
|
3462 + | dialog_map: {
|
3463 + | let mut ret = ::std::collections::HashMap::new();
|
3464 + | ret.insert(
|
3465 + | "emptyDialog".to_owned(),
|
3466 + | crate::model::Dialog {
|
3467 + | greeting: "hi".to_owned(),
|
3468 + | language: ::std::option::Option::None,
|
3469 + | farewell: ::std::option::Option::None,
|
3470 + | },
|
3471 + | );
|
3472 + | ret.insert(
|
3473 + | "partialEmptyDialog".to_owned(),
|
3474 + | crate::model::Dialog {
|
3475 + | language: ::std::option::Option::Some("en".to_owned()),
|
3476 + | greeting: "hi".to_owned(),
|
3477 + | farewell: ::std::option::Option::Some(
|
3478 + | crate::model::Farewell {
|
3479 + | phrase: "bye".to_owned(),
|
3480 + | },
|
3481 + | ),
|
3482 + | },
|
3483 + | );
|
3484 + | ret.insert(
|
3485 + | "nonEmptyDialog".to_owned(),
|
3486 + | crate::model::Dialog {
|
3487 + | greeting: "konnichiwa".to_owned(),
|
3488 + | farewell: ::std::option::Option::Some(
|
3489 + | crate::model::Farewell {
|
3490 + | phrase: "sayonara".to_owned(),
|
3491 + | },
|
3492 + | ),
|
3493 + | language: ::std::option::Option::None,
|
3494 + | },
|
3495 + | );
|
3496 + | ret
|
3497 + | },
|
3498 + | },
|
3499 + | };
|
3391 3500 | ::pretty_assertions::assert_eq!(input, expected);
|
3392 - | let output = crate::output::EmptyInputAndEmptyOutputOutput {};
|
3393 - | output
|
3501 + | let output = crate::output::OperationWithNestedStructureOutput {
|
3502 + | dialog: crate::model::Dialog {
|
3503 + | greeting: "".to_owned(),
|
3504 + | language: ::std::option::Option::None,
|
3505 + | farewell: ::std::option::Option::None,
|
3506 + | },
|
3507 + | dialog_list: vec![],
|
3508 + | dialog_map: ::std::collections::HashMap::new(),
|
3509 + | };
|
3510 + | Ok(output)
|
3394 3511 | };
|
3395 3512 | sender.send(()).await.expect("receiver dropped early");
|
3396 3513 | result
|
3397 3514 | }
|
3398 - | })
|
3515 + | },
|
3516 + | )
|
3399 3517 | .build_unchecked();
|
3400 3518 | let http_response = ::tower::ServiceExt::oneshot(service, http_request)
|
3401 3519 | .await
|
3402 3520 | .expect("unable to make an HTTP request");
|
3403 3521 | assert!(
|
3404 3522 | receiver.recv().await.is_some(),
|
3405 3523 | "we expected operation handler to be invoked but it was not entered"
|
3406 3524 | );
|
3407 3525 | }
|
3408 3526 |
|
3409 - | /// A service will always return a JSON object for operations with modeled output.
|
3410 - | /// Test ID: AwsJson10EmptyInputAndEmptyOutputSendJsonObject
|
3527 + | /// Server populates nested default values when missing in response params.
|
3528 + | /// Test ID: AwsJson10ServerPopulatesNestedDefaultValuesWhenMissingInInResponseParams
|
3411 3529 | #[::tokio::test]
|
3412 3530 | #[::tracing_test::traced_test]
|
3413 - | async fn aws_json10_empty_input_and_empty_output_send_json_object_response() {
|
3414 - | let output = crate::output::EmptyInputAndEmptyOutputOutput {};
|
3531 + | #[should_panic]
|
3532 + | async fn aws_json10_server_populates_nested_default_values_when_missing_in_in_response_params_response(
|
3533 + | ) {
|
3534 + | let output = crate::output::OperationWithNestedStructureOutput {
|
3535 + | dialog: crate::model::Dialog {
|
3536 + | greeting: "".to_owned(),
|
3537 + | language: ::std::option::Option::Some("en".to_owned()),
|
3538 + | farewell: ::std::option::Option::None,
|
3539 + | },
|
3540 + | dialog_list: vec![
|
3541 + | crate::model::Dialog {
|
3542 + | greeting: "".to_owned(),
|
3543 + | language: ::std::option::Option::None,
|
3544 + | farewell: ::std::option::Option::None,
|
3545 + | },
|
3546 + | crate::model::Dialog {
|
3547 + | greeting: "".to_owned(),
|
3548 + | farewell: ::std::option::Option::Some(crate::model::Farewell {
|
3549 + | phrase: "".to_owned(),
|
3550 + | }),
|
3551 + | language: ::std::option::Option::None,
|
3552 + | },
|
3553 + | crate::model::Dialog {
|
3554 + | language: ::std::option::Option::Some("it".to_owned()),
|
3555 + | greeting: "ciao".to_owned(),
|
3556 + | farewell: ::std::option::Option::Some(crate::model::Farewell {
|
3557 + | phrase: "arrivederci".to_owned(),
|
3558 + | }),
|
3559 + | },
|
3560 + | ],
|
3561 + | dialog_map: {
|
3562 + | let mut ret = ::std::collections::HashMap::new();
|
3563 + | ret.insert(
|
3564 + | "emptyDialog".to_owned(),
|
3565 + | crate::model::Dialog {
|
3566 + | greeting: "".to_owned(),
|
3567 + | language: ::std::option::Option::None,
|
3568 + | farewell: ::std::option::Option::None,
|
3569 + | },
|
3570 + | );
|
3571 + | ret.insert(
|
3572 + | "partialEmptyDialog".to_owned(),
|
3573 + | crate::model::Dialog {
|
3574 + | greeting: "".to_owned(),
|
3575 + | language: ::std::option::Option::Some("en".to_owned()),
|
3576 + | farewell: ::std::option::Option::Some(crate::model::Farewell {
|
3577 + | phrase: "".to_owned(),
|
3578 + | }),
|
3579 + | },
|
3580 + | );
|
3581 + | ret.insert(
|
3582 + | "nonEmptyDialog".to_owned(),
|
3583 + | crate::model::Dialog {
|
3584 + | greeting: "konnichiwa".to_owned(),
|
3585 + | farewell: ::std::option::Option::Some(crate::model::Farewell {
|
3586 + | phrase: "sayonara".to_owned(),
|
3587 + | }),
|
3588 + | language: ::std::option::Option::None,
|
3589 + | },
|
3590 + | );
|
3591 + | ret
|
3592 + | },
|
3593 + | };
|
3415 3594 | use ::aws_smithy_http_server::response::IntoResponse;
|
3416 3595 | let http_response = output.into_response();
|
3417 3596 | ::pretty_assertions::assert_eq!(
|
3418 3597 | ::http_1x::StatusCode::from_u16(200).expect("invalid expected HTTP status code"),
|
3419 3598 | http_response.status()
|
3420 3599 | );
|
3421 3600 | let expected_headers = [("Content-Type", "application/x-amz-json-1.0")];
|
3422 3601 | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_headers(
|
3423 3602 | http_response.headers(),
|
3424 3603 | expected_headers,
|
3425 3604 | ));
|
3426 3605 | use ::http_body_util::BodyExt;
|
3427 3606 | let body = http_response
|
3428 3607 | .into_body()
|
3429 3608 | .collect()
|
3430 3609 | .await
|
3431 3610 | .expect("unable to collect body")
|
3432 3611 | .to_bytes();
|
3433 - | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_body(
|
3434 - | &body,
|
3435 - | "{}",
|
3436 - | ::aws_smithy_protocol_test::MediaType::from("application/json"),
|
3437 - | ));
|
3612 + | ::aws_smithy_protocol_test::assert_ok(
|
3613 + | ::aws_smithy_protocol_test::validate_body(&body, "{\n \"dialog\": {\n \"language\": \"en\",\n \"greeting\": \"hi\"\n },\n \"dialogList\": [\n {\n \"greeting\": \"hi\"\n },\n {\n \"greeting\": \"hi\",\n \"farewell\": {\n \"phrase\": \"bye\"\n }\n },\n {\n \"language\": \"it\",\n \"greeting\": \"ciao\",\n \"farewell\": {\n \"phrase\": \"arrivederci\"\n }\n }\n ],\n \"dialogMap\": {\n \"emptyDialog\": {\n \"greeting\": \"hi\"\n },\n \"partialEmptyDialog\": {\n \"language\": \"en\",\n \"greeting\": \"hi\",\n \"farewell\": {\n \"phrase\": \"bye\"\n }\n },\n \"nonEmptyDialog\": {\n \"greeting\": \"konnichiwa\",\n \"farewell\": {\n \"phrase\": \"sayonara\"\n }\n }\n }\n}", ::aws_smithy_protocol_test::MediaType::from("application/json"))
|
3614 + | );
|
3438 3615 | }
|
3439 3616 | }
|
3440 3617 |
|
3441 3618 | ::pin_project_lite::pin_project! {
|
3442 3619 | /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the
|
3443 - | /// [`NoInputAndOutputInput`](crate::input::NoInputAndOutputInput) using modelled bindings.
|
3444 - | pub struct NoInputAndOutputInputFuture {
|
3445 - | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::NoInputAndOutputInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
3620 + | /// [`OperationWithRequiredMembersWithDefaultsInput`](crate::input::OperationWithRequiredMembersWithDefaultsInput) using modelled bindings.
|
3621 + | pub struct OperationWithRequiredMembersWithDefaultsInputFuture {
|
3622 + | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::OperationWithRequiredMembersWithDefaultsInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
3446 3623 | }
|
3447 3624 | }
|
3448 3625 |
|
3449 - | impl std::future::Future for NoInputAndOutputInputFuture {
|
3626 + | impl std::future::Future for OperationWithRequiredMembersWithDefaultsInputFuture {
|
3450 3627 | type Output = Result<
|
3451 - | crate::input::NoInputAndOutputInput,
|
3628 + | crate::input::OperationWithRequiredMembersWithDefaultsInput,
|
3452 3629 | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError,
|
3453 3630 | >;
|
3454 3631 |
|
3455 3632 | fn poll(
|
3456 3633 | self: std::pin::Pin<&mut Self>,
|
3457 3634 | cx: &mut std::task::Context<'_>,
|
3458 3635 | ) -> std::task::Poll<Self::Output> {
|
3459 3636 | let this = self.project();
|
3460 3637 | this.inner.as_mut().poll(cx)
|
3461 3638 | }
|
3462 3639 | }
|
3463 3640 |
|
3464 3641 | impl<B>
|
3465 3642 | ::aws_smithy_http_server::request::FromRequest<
|
3466 3643 | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
3467 3644 | B,
|
3468 - | > for crate::input::NoInputAndOutputInput
|
3645 + | > for crate::input::OperationWithRequiredMembersWithDefaultsInput
|
3469 3646 | where
|
3470 3647 | B: ::aws_smithy_http_server::body::HttpBody + Send,
|
3471 3648 | B: 'static,
|
3472 3649 |
|
3473 3650 | B::Data: Send,
|
3474 3651 | ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection:
|
3475 3652 | From<<B as ::aws_smithy_http_server::body::HttpBody>::Error>,
|
3476 3653 | {
|
3477 3654 | type Rejection = ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError;
|
3478 - | type Future = NoInputAndOutputInputFuture;
|
3655 + | type Future = OperationWithRequiredMembersWithDefaultsInputFuture;
|
3479 3656 |
|
3480 3657 | fn from_request(request: ::http_1x::Request<B>) -> Self::Future {
|
3481 3658 | let fut = async move {
|
3482 3659 | if !::aws_smithy_http_server::protocol::accept_header_classifier(
|
3483 3660 | request.headers(),
|
3484 3661 | &crate::mimes::CONTENT_TYPE_APPLICATION_X_AMZ_JSON_1_0,
|
3485 3662 | ) {
|
3486 3663 | return Err(::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection::NotAcceptable);
|
3487 3664 | }
|
3488 - | crate::protocol_serde::shape_no_input_and_output::de_no_input_and_output_http_request(
|
3489 - | request,
|
3490 - | )
|
3665 + | crate::protocol_serde::shape_operation_with_required_members_with_defaults::de_operation_with_required_members_with_defaults_http_request(request)
|
3491 3666 | .await
|
3492 3667 | };
|
3493 3668 | use ::futures_util::future::TryFutureExt;
|
3494 3669 | let fut = fut.map_err(
|
3495 3670 | |e: ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection| {
|
3496 3671 | ::tracing::debug!(error = %e, "failed to deserialize request");
|
3497 3672 | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e)
|
3498 3673 | },
|
3499 3674 | );
|
3500 - | NoInputAndOutputInputFuture {
|
3675 + | OperationWithRequiredMembersWithDefaultsInputFuture {
|
3501 3676 | inner: Box::pin(fut),
|
3502 3677 | }
|
3503 3678 | }
|
3504 3679 | }
|
3505 3680 | impl
|
3506 3681 | ::aws_smithy_http_server::response::IntoResponse<
|
3507 3682 | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
3508 - | > for crate::output::NoInputAndOutputOutput
|
3683 + | > for crate::output::OperationWithRequiredMembersWithDefaultsOutput
|
3509 3684 | {
|
3510 3685 | fn into_response(self) -> ::aws_smithy_http_server::response::Response {
|
3511 - | match crate::protocol_serde::shape_no_input_and_output::ser_no_input_and_output_http_response(self) {
|
3686 + | match crate::protocol_serde::shape_operation_with_required_members_with_defaults::ser_operation_with_required_members_with_defaults_http_response(self) {
|
3512 3687 | Ok(response) => response,
|
3513 3688 | Err(e) => {
|
3514 3689 | ::tracing::error!(error = %e, "failed to serialize response");
|
3515 3690 | ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0>::into_response(::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e))
|
3516 3691 | }
|
3517 3692 | }
|
3518 3693 | }
|
3519 3694 | }
|
3520 3695 |
|
3521 - | #[allow(unreachable_code, unused_variables)]
|
3522 - | #[cfg(test)]
|
3523 - | mod no_input_and_output_test {
|
3524 - |
|
3525 - | /// A client should always send and empty JSON object payload.
|
3526 - | /// Test ID: AwsJson10NoInputAndOutput
|
3527 - | #[::tokio::test]
|
3528 - | #[::tracing_test::traced_test]
|
3529 - | async fn aws_json10_no_input_and_output_request() {
|
3530 - | #[allow(unused_mut)]
|
3531 - | let mut http_request = ::http_1x::Request::builder()
|
3532 - | .uri("/")
|
3533 - | .method("POST")
|
3534 - | .header("Content-Type", "application/x-amz-json-1.0")
|
3535 - | .header("X-Amz-Target", "JsonRpc10.NoInputAndOutput")
|
3536 - | .body(::aws_smithy_http_server::body::boxed(
|
3537 - | ::http_body_util::Full::new(::bytes::Bytes::copy_from_slice(
|
3538 - | &::aws_smithy_protocol_test::decode_body_data(
|
3539 - | "{}".as_bytes(),
|
3540 - | ::aws_smithy_protocol_test::MediaType::from("application/json"),
|
3541 - | ),
|
3542 - | )),
|
3543 - | ))
|
3544 - | .unwrap();
|
3545 - | #[allow(unused_mut)]
|
3546 - | let (sender, mut receiver) = ::tokio::sync::mpsc::channel(1);
|
3547 - | let config = crate::service::JsonRpc10Config::builder().build();
|
3548 - | let service =
|
3549 - | crate::service::JsonRpc10::builder::<::aws_smithy_http_server::body::BoxBody, _, _, _>(
|
3550 - | config,
|
3551 - | )
|
3552 - | .no_input_and_output(move |input: crate::input::NoInputAndOutputInput| {
|
3553 - | let sender = sender.clone();
|
3554 - | async move {
|
3555 - | let result = {
|
3556 - | let expected = crate::input::NoInputAndOutputInput {};
|
3557 - | ::pretty_assertions::assert_eq!(input, expected);
|
3558 - | let output = crate::output::NoInputAndOutputOutput {};
|
3559 - | output
|
3560 - | };
|
3561 - | sender.send(()).await.expect("receiver dropped early");
|
3562 - | result
|
3563 - | }
|
3564 - | })
|
3565 - | .build_unchecked();
|
3566 - | let http_response = ::tower::ServiceExt::oneshot(service, http_request)
|
3567 - | .await
|
3568 - | .expect("unable to make an HTTP request");
|
3569 - | assert!(
|
3570 - | receiver.recv().await.is_some(),
|
3571 - | "we expected operation handler to be invoked but it was not entered"
|
3572 - | );
|
3573 - | }
|
3574 - |
|
3575 - | /// Empty output always serializes an empty object payload.
|
3576 - | /// Test ID: AwsJson10NoInputAndOutput
|
3577 - | #[::tokio::test]
|
3578 - | #[::tracing_test::traced_test]
|
3579 - | async fn aws_json10_no_input_and_output_response() {
|
3580 - | let output = crate::output::NoInputAndOutputOutput {};
|
3581 - | use ::aws_smithy_http_server::response::IntoResponse;
|
3582 - | let http_response = output.into_response();
|
3583 - | ::pretty_assertions::assert_eq!(
|
3584 - | ::http_1x::StatusCode::from_u16(200).expect("invalid expected HTTP status code"),
|
3585 - | http_response.status()
|
3586 - | );
|
3587 - | let expected_headers = [("Content-Type", "application/x-amz-json-1.0")];
|
3588 - | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_headers(
|
3589 - | http_response.headers(),
|
3590 - | expected_headers,
|
3591 - | ));
|
3592 - | use ::http_body_util::BodyExt;
|
3593 - | let body = http_response
|
3594 - | .into_body()
|
3595 - | .collect()
|
3596 - | .await
|
3597 - | .expect("unable to collect body")
|
3598 - | .to_bytes();
|
3599 - | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_body(
|
3600 - | &body,
|
3601 - | "{}",
|
3602 - | ::aws_smithy_protocol_test::MediaType::from("application/json"),
|
3603 - | ));
|
3604 - | }
|
3605 - | }
|
3606 - |
|
3607 3696 | ::pin_project_lite::pin_project! {
|
3608 3697 | /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the
|
3609 - | /// [`NoInputAndNoOutputInput`](crate::input::NoInputAndNoOutputInput) using modelled bindings.
|
3610 - | pub struct NoInputAndNoOutputInputFuture {
|
3611 - | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::NoInputAndNoOutputInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
3698 + | /// [`QueryIncompatibleOperationInput`](crate::input::QueryIncompatibleOperationInput) using modelled bindings.
|
3699 + | pub struct QueryIncompatibleOperationInputFuture {
|
3700 + | inner: std::pin::Pin<Box<dyn std::future::Future<Output = Result<crate::input::QueryIncompatibleOperationInput, ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError>> + Send>>
|
3612 3701 | }
|
3613 3702 | }
|
3614 3703 |
|
3615 - | impl std::future::Future for NoInputAndNoOutputInputFuture {
|
3704 + | impl std::future::Future for QueryIncompatibleOperationInputFuture {
|
3616 3705 | type Output = Result<
|
3617 - | crate::input::NoInputAndNoOutputInput,
|
3706 + | crate::input::QueryIncompatibleOperationInput,
|
3618 3707 | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError,
|
3619 3708 | >;
|
3620 3709 |
|
3621 3710 | fn poll(
|
3622 3711 | self: std::pin::Pin<&mut Self>,
|
3623 3712 | cx: &mut std::task::Context<'_>,
|
3624 3713 | ) -> std::task::Poll<Self::Output> {
|
3625 3714 | let this = self.project();
|
3626 3715 | this.inner.as_mut().poll(cx)
|
3627 3716 | }
|
3628 3717 | }
|
3629 3718 |
|
3630 3719 | impl<B>
|
3631 3720 | ::aws_smithy_http_server::request::FromRequest<
|
3632 3721 | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
3633 3722 | B,
|
3634 - | > for crate::input::NoInputAndNoOutputInput
|
3723 + | > for crate::input::QueryIncompatibleOperationInput
|
3635 3724 | where
|
3636 3725 | B: ::aws_smithy_http_server::body::HttpBody + Send,
|
3637 3726 | B: 'static,
|
3638 3727 |
|
3639 3728 | B::Data: Send,
|
3640 3729 | ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection:
|
3641 3730 | From<<B as ::aws_smithy_http_server::body::HttpBody>::Error>,
|
3642 3731 | {
|
3643 3732 | type Rejection = ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError;
|
3644 - | type Future = NoInputAndNoOutputInputFuture;
|
3733 + | type Future = QueryIncompatibleOperationInputFuture;
|
3645 3734 |
|
3646 3735 | fn from_request(request: ::http_1x::Request<B>) -> Self::Future {
|
3647 3736 | let fut = async move {
|
3648 3737 | if !::aws_smithy_http_server::protocol::accept_header_classifier(
|
3649 3738 | request.headers(),
|
3650 3739 | &crate::mimes::CONTENT_TYPE_APPLICATION_X_AMZ_JSON_1_0,
|
3651 3740 | ) {
|
3652 3741 | return Err(::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection::NotAcceptable);
|
3653 3742 | }
|
3654 - | crate::protocol_serde::shape_no_input_and_no_output::de_no_input_and_no_output_http_request(request)
|
3743 + | crate::protocol_serde::shape_query_incompatible_operation::de_query_incompatible_operation_http_request(request)
|
3655 3744 | .await
|
3656 3745 | };
|
3657 3746 | use ::futures_util::future::TryFutureExt;
|
3658 3747 | let fut = fut.map_err(
|
3659 3748 | |e: ::aws_smithy_http_server::protocol::aws_json::rejection::RequestRejection| {
|
3660 3749 | ::tracing::debug!(error = %e, "failed to deserialize request");
|
3661 3750 | ::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e)
|
3662 3751 | },
|
3663 3752 | );
|
3664 - | NoInputAndNoOutputInputFuture {
|
3753 + | QueryIncompatibleOperationInputFuture {
|
3665 3754 | inner: Box::pin(fut),
|
3666 3755 | }
|
3667 3756 | }
|
3668 3757 | }
|
3669 3758 | impl
|
3670 3759 | ::aws_smithy_http_server::response::IntoResponse<
|
3671 3760 | ::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0,
|
3672 - | > for crate::output::NoInputAndNoOutputOutput
|
3761 + | > for crate::output::QueryIncompatibleOperationOutput
|
3673 3762 | {
|
3674 3763 | fn into_response(self) -> ::aws_smithy_http_server::response::Response {
|
3675 - | match crate::protocol_serde::shape_no_input_and_no_output::ser_no_input_and_no_output_http_response(self) {
|
3764 + | match crate::protocol_serde::shape_query_incompatible_operation::ser_query_incompatible_operation_http_response(self) {
|
3676 3765 | Ok(response) => response,
|
3677 3766 | Err(e) => {
|
3678 3767 | ::tracing::error!(error = %e, "failed to serialize response");
|
3679 3768 | ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::aws_json_10::AwsJson1_0>::into_response(::aws_smithy_http_server::protocol::aws_json::runtime_error::RuntimeError::from(e))
|
3680 3769 | }
|
3681 3770 | }
|
3682 3771 | }
|
3683 3772 | }
|
3684 3773 |
|
3685 3774 | #[allow(unreachable_code, unused_variables)]
|
3686 3775 | #[cfg(test)]
|
3687 - | mod no_input_and_no_output_test {
|
3776 + | mod query_incompatible_operation_test {
|
3688 3777 |
|
3689 - | /// Clients must always send an empty JSON object payload for
|
3690 - | /// operations with no input (that is, `{}`). While AWS service
|
3691 - | /// implementations support requests with no payload or requests
|
3692 - | /// that send `{}`, always sending `{}` from the client is
|
3693 - | /// preferred for forward compatibility in case input is ever
|
3694 - | /// added to an operation.
|
3695 - | /// Test ID: AwsJson10MustAlwaysSendEmptyJsonPayload
|
3778 + | /// The query mode header MUST NOT be set on non-query-compatible services.
|
3779 + | /// Test ID: NonQueryCompatibleAwsJson10ForbidsQueryModeHeader
|
3696 3780 | #[::tokio::test]
|
3697 3781 | #[::tracing_test::traced_test]
|
3698 - | async fn aws_json10_must_always_send_empty_json_payload_request() {
|
3782 + | async fn non_query_compatible_aws_json10_forbids_query_mode_header_request() {
|
3699 3783 | #[allow(unused_mut)]
|
3700 3784 | let mut http_request = ::http_1x::Request::builder()
|
3701 3785 | .uri("/")
|
3702 3786 | .method("POST")
|
3703 3787 | .header("Content-Type", "application/x-amz-json-1.0")
|
3704 - | .header("X-Amz-Target", "JsonRpc10.NoInputAndNoOutput")
|
3788 + | .header("X-Amz-Target", "JsonRpc10.QueryIncompatibleOperation")
|
3705 3789 | .body(::aws_smithy_http_server::body::boxed(
|
3706 3790 | ::http_body_util::Full::new(::bytes::Bytes::copy_from_slice(
|
3707 3791 | &::aws_smithy_protocol_test::decode_body_data(
|
3708 3792 | "{}".as_bytes(),
|
3709 3793 | ::aws_smithy_protocol_test::MediaType::from("application/json"),
|
3710 3794 | ),
|
3711 3795 | )),
|
3712 3796 | ))
|
3713 3797 | .unwrap();
|
3714 3798 | #[allow(unused_mut)]
|
3715 3799 | let (sender, mut receiver) = ::tokio::sync::mpsc::channel(1);
|
3716 3800 | let config = crate::service::JsonRpc10Config::builder().build();
|
3717 3801 | let service =
|
3718 3802 | crate::service::JsonRpc10::builder::<::aws_smithy_http_server::body::BoxBody, _, _, _>(
|
3719 3803 | config,
|
3720 3804 | )
|
3721 - | .no_input_and_no_output(move |input: crate::input::NoInputAndNoOutputInput| {
|
3805 + | .query_incompatible_operation(
|
3806 + | move |input: crate::input::QueryIncompatibleOperationInput| {
|
3722 3807 | let sender = sender.clone();
|
3723 3808 | async move {
|
3724 3809 | let result = {
|
3725 - | let expected = crate::input::NoInputAndNoOutputInput {};
|
3810 + | let expected = crate::input::QueryIncompatibleOperationInput {};
|
3726 3811 | ::pretty_assertions::assert_eq!(input, expected);
|
3727 - | let output = crate::output::NoInputAndNoOutputOutput {};
|
3812 + | let output = crate::output::QueryIncompatibleOperationOutput {};
|
3728 3813 | output
|
3729 3814 | };
|
3730 3815 | sender.send(()).await.expect("receiver dropped early");
|
3731 3816 | result
|
3732 3817 | }
|
3733 - | })
|
3734 - | .build_unchecked();
|
3735 - | let http_response = ::tower::ServiceExt::oneshot(service, http_request)
|
3736 - | .await
|
3737 - | .expect("unable to make an HTTP request");
|
3738 - | assert!(
|
3739 - | receiver.recv().await.is_some(),
|
3740 - | "we expected operation handler to be invoked but it was not entered"
|
3741 - | );
|
3742 - | }
|
3743 - |
|
3744 - | /// Service implementations must support no payload or an empty
|
3745 - | /// object payload for operations that define no input. However,
|
3746 - | /// despite the lack of a payload, a Content-Type header is still
|
3747 - | /// required in order for the service to properly detect the
|
3748 - | /// protocol.
|
3749 - | /// Test ID: AwsJson10ServiceSupportsNoPayloadForNoInput
|
3750 - | #[::tokio::test]
|
3751 - | #[::tracing_test::traced_test]
|
3752 - | async fn aws_json10_service_supports_no_payload_for_no_input_request() {
|
3753 - | #[allow(unused_mut)]
|
3754 - | let mut http_request = ::http_1x::Request::builder()
|
3755 - | .uri("/")
|
3756 - | .method("POST")
|
3757 - | .header("Content-Type", "application/x-amz-json-1.0")
|
3758 - | .header("X-Amz-Target", "JsonRpc10.NoInputAndNoOutput")
|
3759 - | .body(::aws_smithy_http_server::body::boxed(
|
3760 - | ::http_body_util::Full::new(::bytes::Bytes::copy_from_slice(
|
3761 - | &::aws_smithy_protocol_test::decode_body_data(
|
3762 - | "".as_bytes(),
|
3763 - | ::aws_smithy_protocol_test::MediaType::from("unknown"),
|
3764 - | ),
|
3765 - | )),
|
3766 - | ))
|
3767 - | .unwrap();
|
3768 - | #[allow(unused_mut)]
|
3769 - | let (sender, mut receiver) = ::tokio::sync::mpsc::channel(1);
|
3770 - | let config = crate::service::JsonRpc10Config::builder().build();
|
3771 - | let service =
|
3772 - | crate::service::JsonRpc10::builder::<::aws_smithy_http_server::body::BoxBody, _, _, _>(
|
3773 - | config,
|
3818 + | },
|
3774 3819 | )
|
3775 - | .no_input_and_no_output(move |input: crate::input::NoInputAndNoOutputInput| {
|
3776 - | let sender = sender.clone();
|
3777 - | async move {
|
3778 - | let result = {
|
3779 - | let expected = crate::input::NoInputAndNoOutputInput {};
|
3780 - | ::pretty_assertions::assert_eq!(input, expected);
|
3781 - | let output = crate::output::NoInputAndNoOutputOutput {};
|
3782 - | output
|
3783 - | };
|
3784 - | sender.send(()).await.expect("receiver dropped early");
|
3785 - | result
|
3786 - | }
|
3787 - | })
|
3788 3820 | .build_unchecked();
|
3789 3821 | let http_response = ::tower::ServiceExt::oneshot(service, http_request)
|
3790 3822 | .await
|
3791 3823 | .expect("unable to make an HTTP request");
|
3792 3824 | assert!(
|
3793 3825 | receiver.recv().await.is_some(),
|
3794 3826 | "we expected operation handler to be invoked but it was not entered"
|
3795 3827 | );
|
3796 3828 | }
|
3797 - |
|
3798 - | /// When no output is defined, the service is expected to return
|
3799 - | /// an empty payload. Despite the lack of a payload, the service
|
3800 - | /// is expected to always send a Content-Type header. Clients must
|
3801 - | /// handle cases where a service returns a JSON object and where
|
3802 - | /// a service returns no JSON at all.
|
3803 - | /// Test ID: AwsJson10ServiceRespondsWithNoPayload
|
3804 - | #[::tokio::test]
|
3805 - | #[::tracing_test::traced_test]
|
3806 - | async fn aws_json10_service_responds_with_no_payload_response() {
|
3807 - | let output = crate::output::NoInputAndNoOutputOutput {};
|
3808 - | use ::aws_smithy_http_server::response::IntoResponse;
|
3809 - | let http_response = output.into_response();
|
3810 - | ::pretty_assertions::assert_eq!(
|
3811 - | ::http_1x::StatusCode::from_u16(200).expect("invalid expected HTTP status code"),
|
3812 - | http_response.status()
|
3813 - | );
|
3814 - | let expected_headers = [("Content-Type", "application/x-amz-json-1.0")];
|
3815 - | ::aws_smithy_protocol_test::assert_ok(::aws_smithy_protocol_test::validate_headers(
|
3816 - | http_response.headers(),
|
3817 - | expected_headers,
|
3818 - | ));
|
3819 - | use ::http_body_util::BodyExt;
|
3820 - | let body = http_response
|
3821 - | .into_body()
|
3822 - | .collect()
|
3823 - | .await
|
3824 - | .expect("unable to collect body")
|
3825 - | .to_bytes();
|
3826 - | // No body.
|
3827 - | ::pretty_assertions::assert_eq!(&body, &bytes::Bytes::new());
|
3828 - | }
|
3829 3829 | }
|