-
Notifications
You must be signed in to change notification settings - Fork 188
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Fahad Zubair
committed
Oct 6, 2023
1 parent
d6e01db
commit f531651
Showing
23 changed files
with
722 additions
and
1,357 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
89 changes: 89 additions & 0 deletions
89
examples/pokemon-service-client-usage/examples/client-connector.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
use std::time::Duration; | ||
|
||
use aws_smithy_client::{http_connector::ConnectorSettings, hyper_ext}; | ||
/* | ||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
/// This example demonstrates how to create a Smithy Client and call an | ||
/// [operation](https://smithy.io/2.0/spec/idl.html?highlight=operation#operation-shape). | ||
/// | ||
/// The example assumes that the Pokemon service is running on the localhost on TCP port 13734. | ||
/// Refer to the [README.md](https://github.com/awslabs/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) | ||
/// file for instructions on how to launch the service locally. | ||
/// | ||
/// The example can be run using `cargo run --example dyn-client`. | ||
/// | ||
use tracing::info; | ||
|
||
use pokemon_service_client::Client as PokemonClient; | ||
|
||
static BASE_URL: &str = "http://localhost:13734"; | ||
|
||
/// Creates a new Smithy client that is configured to communicate with a locally running Pokemon | ||
/// service on TCP port 13734. | ||
/// | ||
/// # Examples | ||
/// | ||
/// Basic usage: | ||
/// ``` | ||
/// let client = create_client(); | ||
/// ``` | ||
fn create_client() -> PokemonClient { | ||
let https_connector = hyper_rustls::HttpsConnectorBuilder::new() | ||
.with_native_roots() | ||
// This can be changed to .https_only() to ensure that the client always uses https | ||
.https_or_http() | ||
.enable_http1() | ||
.enable_http2() | ||
.build(); | ||
|
||
let smithy_connector = hyper_ext::Adapter::builder() | ||
// Optionally set things like timeouts as well | ||
.connector_settings( | ||
ConnectorSettings::builder() | ||
.connect_timeout(Duration::from_secs(5)) | ||
.build(), | ||
) | ||
.build(https_connector); | ||
|
||
let config = pokemon_service_client::Config::builder() | ||
.endpoint_url(BASE_URL) | ||
.http_connector(smithy_connector) | ||
.build(); | ||
|
||
// Instantiate a client by applying the configuration. | ||
pokemon_service_client::Client::from_conf(config) | ||
} | ||
|
||
#[tokio::main] | ||
async fn main() { | ||
tracing_setup(); | ||
|
||
// Create a configured Smithy client. | ||
let client = create_client(); | ||
|
||
// Call an operation `get_server_statistics` on Pokemon service. | ||
let response = client | ||
.get_server_statistics() | ||
.send() | ||
.await | ||
.expect("Pokemon service does not seem to be running on localhost:13734"); | ||
|
||
// Print the response received from the service. | ||
info!(%BASE_URL, ?response, "Response received"); | ||
} | ||
|
||
fn tracing_setup() { | ||
if std::env::var("RUST_LIB_BACKTRACE").is_err() { | ||
std::env::set_var("RUST_LIB_BACKTRACE", "1"); | ||
} | ||
let _ = color_eyre::install(); | ||
|
||
if std::env::var("RUST_LOG").is_err() { | ||
std::env::set_var("RUST_LOG", "info"); | ||
} | ||
tracing_subscriber::fmt::fmt() | ||
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) | ||
.init(); | ||
} |
169 changes: 169 additions & 0 deletions
169
examples/pokemon-service-client-usage/examples/custom-header-using-interceptor.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
/* | ||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
/// In this example, a custom header x-amzn-client-ttl-seconds is set for all outgoing requests. | ||
/// It serves as a demonstration of how an operation name can be retrieved and utilized within | ||
/// the interceptor. | ||
/// | ||
/// The example assumes that the Pokemon service is running on the localhost on TCP port 13734. | ||
/// Refer to the [README.md](https://github.com/awslabs/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) | ||
/// file for instructions on how to launch the service locally. | ||
/// | ||
/// The example can be run using `cargo run --example custom-header-using-interceptor`. | ||
/// | ||
use std::{collections::HashMap, time::Duration}; | ||
|
||
use aws_smithy_types::config_bag::ConfigBag; | ||
use pokemon_service_client::Client as PokemonClient; | ||
use pokemon_service_client::{ | ||
config::{interceptors::BeforeTransmitInterceptorContextMut, Interceptor, RuntimeComponents}, | ||
error::BoxError, | ||
}; | ||
use tracing::info; | ||
|
||
// URL where example Pokemon service is running. | ||
static BASE_URL: &str = "http://localhost:13734"; | ||
// By default set the value of all operations to 6.0 | ||
static DEFAULT_TTL: Duration = Duration::from_secs(6); | ||
// Header to send with each operation. | ||
const HEADER_TO_SEND: hyper::header::HeaderName = | ||
hyper::header::HeaderName::from_static("x-amzn-client-ttl-seconds"); | ||
|
||
// The TtlHeaderInterceptor keeps a map of operation specific value to send | ||
// for the header. | ||
#[derive(Debug, Clone)] | ||
pub struct TtlHeaderInterceptor { | ||
/// Default time-to-live for an operation. | ||
default_ttl: hyper::http::HeaderValue, | ||
/// Operation specific time-to-live | ||
operation_ttl: HashMap<&'static str, hyper::http::HeaderValue>, | ||
} | ||
|
||
fn format_ttl_value(ttl: Duration) -> String { | ||
format!("{:.2}", ttl.as_secs_f64()) | ||
} | ||
|
||
impl TtlHeaderInterceptor { | ||
fn new(default_ttl: Duration) -> Self { | ||
let duration_str = format_ttl_value(default_ttl); | ||
let default_ttl_value = hyper::http::HeaderValue::from_str(duration_str.as_str()) | ||
.expect("could not create a header value for the default ttl"); | ||
|
||
Self { | ||
default_ttl: default_ttl_value, | ||
operation_ttl: Default::default(), | ||
} | ||
} | ||
|
||
/// Adds an operation name specific value to the map. | ||
fn add_operation_ttl(&mut self, operation_name: &'static str, ttl: Duration) { | ||
let duration_str = format_ttl_value(ttl); | ||
|
||
self.operation_ttl.insert( | ||
operation_name, | ||
hyper::http::HeaderValue::from_str(duration_str.as_str()) | ||
.expect("cannot create header value for the given ttl duration"), | ||
); | ||
} | ||
} | ||
|
||
/// | ||
impl Interceptor for TtlHeaderInterceptor { | ||
fn name(&self) -> &'static str { | ||
"TtlHeaderInterceptor" | ||
} | ||
|
||
/// Before the request is signed, add the header to the outgoing request. | ||
fn modify_before_signing( | ||
&self, | ||
context: &mut BeforeTransmitInterceptorContextMut<'_>, | ||
_runtime_components: &RuntimeComponents, | ||
cfg: &mut ConfigBag, | ||
) -> Result<(), BoxError> { | ||
let metadata = cfg | ||
.load::<aws_smithy_http::operation::Metadata>() | ||
.expect("metadata should exist"); | ||
let operation_name = metadata.name().to_string(); | ||
|
||
let ttl = match self.operation_ttl.get(operation_name.as_str()) { | ||
Some(ttl) => ttl, | ||
None => &self.default_ttl, | ||
}; | ||
|
||
context | ||
.request_mut() | ||
.headers_mut() | ||
.insert(&HEADER_TO_SEND, ttl.clone()); | ||
|
||
info!("{operation_name} header set to {ttl:?}"); | ||
|
||
Ok(()) | ||
} | ||
} | ||
|
||
/// Creates a new Smithy client that is configured to communicate with a locally running Pokemon service on TCP port 13734. | ||
/// | ||
/// # Examples | ||
/// | ||
/// Basic usage: | ||
/// | ||
/// ``` | ||
/// let client = create_client(); | ||
/// ``` | ||
fn create_client() -> PokemonClient { | ||
let mut ttl_headers_interceptor = TtlHeaderInterceptor::new(DEFAULT_TTL); | ||
ttl_headers_interceptor.add_operation_ttl("GetStorage", Duration::from_millis(3500)); | ||
|
||
// The generated client has a type config::Builder that can be used to build a Config, which | ||
// allows configuring endpoint-resolver, timeouts, retries etc. | ||
let config = pokemon_service_client::Config::builder() | ||
.endpoint_resolver(BASE_URL) | ||
.interceptor(ttl_headers_interceptor) | ||
.build(); | ||
|
||
pokemon_service_client::Client::from_conf(config) | ||
} | ||
|
||
#[tokio::main] | ||
async fn main() { | ||
tracing_setup(); | ||
|
||
// Create a configured Smithy client. | ||
let client = create_client(); | ||
|
||
// Call an operation `get_server_statistics` on Pokemon service. | ||
let response = client | ||
.get_server_statistics() | ||
.send() | ||
.await | ||
.expect("Pokemon service does not seem to be running on localhost:13734"); | ||
|
||
info!(%BASE_URL, ?response, "Response for get_server_statistics()"); | ||
|
||
// Call the operation `get_storage` on Pokemon service. The AddHeader middleware | ||
// will add a specific header name / value pair for this operation. | ||
let response = client | ||
.get_storage() | ||
.user("ash") | ||
.passcode("pikachu123") | ||
.send() | ||
.await | ||
.expect("Operation could not be called"); | ||
|
||
info!(%BASE_URL, ?response, "Response for get_storage()"); | ||
} | ||
|
||
fn tracing_setup() { | ||
if std::env::var("RUST_LIB_BACKTRACE").is_err() { | ||
std::env::set_var("RUST_LIB_BACKTRACE", "1"); | ||
} | ||
let _ = color_eyre::install(); | ||
|
||
if std::env::var("RUST_LOG").is_err() { | ||
std::env::set_var("RUST_LOG", "info"); | ||
} | ||
tracing_subscriber::fmt::fmt() | ||
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) | ||
.init(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.