Skip to content

Commit 4c852b1

Browse files
author
Zelda Hessler
authored
Add operation metadata to property bag just before sending request through middleware (#1920)
* update: add operation metadata to property bag during `make_operation` add: test ensuring metadata is added to property bag add: CHANGELOG.next.toml entry * update: use new strategy for op metadata insertion update: a new strategy requires a new test update: CHANGELOG.next.toml * format: run cargo fmt
1 parent c5c87be commit 4c852b1

File tree

4 files changed

+55
-4
lines changed

4 files changed

+55
-4
lines changed

CHANGELOG.next.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,12 @@ message = "Fix bug that can cause panics in paginators"
5252
references = ["smithy-rs#1903", "smithy-rs#1902"]
5353
meta = { "breaking" = false, "tada" = false, "bug" = true, "target" = "client"}
5454
author = "rcoh"
55+
56+
[[smithy-rs]]
57+
message = """
58+
Operation metadata is now added to the property bag before sending requests allowing middlewares to behave
59+
differently depending on the operation being sent.
60+
"""
61+
references = ["smithy-rs#1919"]
62+
meta = { "breaking" = false, "tada" = false, "bug" = false, "target" = "client"}
63+
author = "Velfi"

aws/rust-runtime/aws-inlineable/tests/middleware_e2e_test.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use aws_http::retry::AwsResponseRetryClassifier;
1919
use aws_http::user_agent::AwsUserAgent;
2020
use aws_inlineable::middleware::DefaultMiddleware;
2121
use aws_sig_auth::signer::OperationSigningConfig;
22+
use aws_smithy_client::erase::DynConnector;
2223

2324
use aws_smithy_client::test_connection::TestConnection;
2425
use aws_smithy_http::body::SdkBody;
@@ -112,6 +113,7 @@ fn test_operation() -> Operation<TestOperationParser, AwsResponseRetryClassifier
112113
.unwrap();
113114
Operation::new(req, TestOperationParser)
114115
.with_retry_classifier(AwsResponseRetryClassifier::new())
116+
.with_metadata(operation::Metadata::new("test-op", "test-service"))
115117
}
116118

117119
#[cfg(any(feature = "native-tls", feature = "rustls"))]
@@ -148,3 +150,39 @@ async fn e2e_test() {
148150

149151
conn.assert_requests_match(&[]);
150152
}
153+
154+
#[tokio::test]
155+
async fn test_operation_metadata_is_available_to_middlewares() {
156+
let conn = TestConnection::new(vec![(
157+
http::Request::builder()
158+
.header(USER_AGENT, "aws-sdk-rust/0.123.test os/windows/XPSP3 lang/rust/1.50.0")
159+
.header("x-amz-user-agent", "aws-sdk-rust/0.123.test api/test-service/0.123 os/windows/XPSP3 lang/rust/1.50.0")
160+
.header(AUTHORIZATION, "AWS4-HMAC-SHA256 Credential=access_key/20210215/test-region/test-service-signing/aws4_request, SignedHeaders=host;x-amz-date;x-amz-user-agent, Signature=da249491d7fe3da22c2e09cbf910f37aa5b079a3cedceff8403d0b18a7bfab75")
161+
.header("x-amz-date", "20210215T184017Z")
162+
.uri(Uri::from_static("https://test-service.test-region.amazonaws.com/"))
163+
.body(SdkBody::from("request body")).unwrap(),
164+
http::Response::builder()
165+
.status(200)
166+
.body("response body")
167+
.unwrap(),
168+
)]);
169+
let client = aws_smithy_client::Client::builder()
170+
.middleware_fn(|req| {
171+
let metadata = req
172+
.properties()
173+
.get::<operation::Metadata>()
174+
.cloned()
175+
.unwrap();
176+
177+
assert_eq!("test-op", metadata.name());
178+
assert_eq!("test-service", metadata.service());
179+
180+
req
181+
})
182+
.connector(DynConnector::new(conn))
183+
.build();
184+
185+
let resp = client.call(test_operation()).await;
186+
let resp = resp.expect("successful operation");
187+
assert_eq!(resp, "Hello!");
188+
}

codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/protocol/MakeOperationGenerator.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ open class MakeOperationGenerator(
7171
) {
7272
val operationName = symbolProvider.toSymbol(shape).name
7373
val baseReturnType = buildOperationType(implBlockWriter, shape, customizations)
74-
val returnType = "std::result::Result<$baseReturnType, ${implBlockWriter.format(runtimeConfig.operationBuildError())}>"
74+
val returnType =
75+
"std::result::Result<$baseReturnType, ${implBlockWriter.format(runtimeConfig.operationBuildError())}>"
7576
val outputSymbol = symbolProvider.toSymbol(shape)
7677

7778
val takesOwnership = bodyGenerator.payloadMetadata(shape).takesOwnership
@@ -82,8 +83,10 @@ open class MakeOperationGenerator(
8283

8384
implBlockWriter.docs("Consumes the builder and constructs an Operation<#D>", outputSymbol)
8485
Attribute.AllowUnusedMut.render(implBlockWriter) // For codegen simplicity
85-
Attribute.Custom("allow(clippy::let_and_return)").render(implBlockWriter) // For codegen simplicity, allow `let x = ...; x`
86-
Attribute.Custom("allow(clippy::needless_borrow)").render(implBlockWriter) // Allows builders that don’t consume the input borrow
86+
Attribute.Custom("allow(clippy::let_and_return)")
87+
.render(implBlockWriter) // For codegen simplicity, allow `let x = ...; x`
88+
Attribute.Custom("allow(clippy::needless_borrow)")
89+
.render(implBlockWriter) // Allows builders that don’t consume the input borrow
8790
implBlockWriter.rustBlockTemplate(
8891
"$fnType $functionName($self, _config: &#{config}::Config) -> $returnType",
8992
*codegenScope,

rust-runtime/aws-smithy-http-tower/src/parse_response.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ where
8888
}
8989

9090
fn call(&mut self, req: Operation<ResponseHandler, RetryPolicy>) -> Self::Future {
91-
let (req, parts) = req.into_request_response();
91+
let (mut req, parts) = req.into_request_response();
9292
let handler = parts.response_handler;
9393
// send_operation records the full request-response lifecycle.
9494
// NOTE: For operations that stream output, only the setup is captured in this span.
@@ -103,6 +103,7 @@ where
103103
if let Some(metadata) = parts.metadata {
104104
span.record("operation", &metadata.name());
105105
span.record("service", &metadata.service());
106+
req.properties_mut().insert(metadata);
106107
}
107108
let resp = self.inner.call(req);
108109
let fut = async move {

0 commit comments

Comments
 (0)