Add / fix smithy-client docs (#855)

* Add / fix smithy-client docs

* Rework hyper impls to be a regular public module instead of pub use

* clarify comments, fix changelog

* cleanup code in docs

* Add doc linking

* Update rust-runtime/aws-smithy-client/src/hyper_ext.rs

Co-authored-by: John DiSanti <jdisanti@amazon.com>

* fix changelog

* SDK changelog docs

Co-authored-by: John DiSanti <jdisanti@amazon.com>
This commit is contained in:
Russell Cohen 2021-11-19 15:41:25 -05:00 committed by GitHub
parent 1df4c12621
commit cab7de3faf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 96 additions and 37 deletions

View File

@ -1,8 +1,11 @@
vNext (Month Day, Year)
=======================
**TODO Next Release:**
- Update README & aws-sdk-rust CI for MSRV upgrade to 1.54
**New this release**
- Improve docs on `aws-smithy-client` (smithy-rs#855)
**Breaking Changes**
- (aws-smithy-client): Extraneous `pub use SdkSuccess` removed from `aws_smithy_client::hyper_ext`. (smithy-rs#855)
v0.29.0-alpha (November 11th, 2021)
===================================

View File

@ -1,6 +1,16 @@
vNext (Month Day, Year)
=======================
**New this release**
- Improve docs on `aws-smithy-client` (smithy-rs#855)
**Breaking Changes**
- (aws-smithy-client): Extraneous `pub use SdkSuccess` removed from `aws_smithy_client::hyper_ext`. (smithy-rs#855)
v0.0.26-alpha (TBD)
=======================
**TODO Upon release**
- Update README & aws-sdk-rust CI for MSRV upgrade to 1.54

View File

@ -52,7 +52,7 @@ impl<M, R> Builder<(), M, R> {
/// be able to use a custom connector instead, such as to mock the network for tests.
///
/// If you just want to specify a function from request to response instead, use
/// [`Builder::map_connector`].
/// [`Builder::connector_fn`].
pub fn connector<C>(self, connector: C) -> Builder<C, M, R> {
Builder {
connector,

View File

@ -2,6 +2,41 @@
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
//! Implementation of [`SmithyConnector`](crate::bounds::SmithyConnector) for Hyper
//!
//! The module provides [`Adapter`] which enables using a [`hyper::Client`] as the connector for a Smithy
//! [`Client`](crate::Client).
//!
//! # Examples
//! ### Construct a Smithy Client with Hyper and Rustls
//! In the basic case, customers should not need to use this module. A default implementation of Hyper
//! with `rustls` will be constructed during client creation. However, if you are creating a Smithy
//! [`Client`](crate::Client), directly, use the `https()` method to match the default behavior:
//! ```rust
//! use aws_smithy_client::Client;
//! use aws_smithy_client::erase::DynConnector;
//!
//! // TODO: replace this with your middleware
//! type MyMiddleware = tower::layer::util::Identity;
//! let client = Client::<DynConnector, MyMiddleware>::https();
//! ```
//!
//! ### Create a Hyper client with a custom timeout
//! One common use case for constructing a connector directly is setting `CONNECT` timeouts. Since the
//! internal connector is cheap to clone, you can also use this to share a connector between multiple services.
//! ```rust
//! use std::time::Duration;
//! use aws_smithy_client::{Client, conns, hyper_ext};
//! use aws_smithy_client::erase::DynConnector;
//! use aws_smithy_client::timeout::Settings;
//!
//! let timeout = Settings::new().with_connect_timeout(Duration::from_secs(1));
//! let connector = hyper_ext::Adapter::builder().timeout(&timeout).build(conns::https());
//! // TODO: replace this with your middleware
//! type MyMiddleware = tower::layer::util::Identity;
//! // once you have a connector, use it to construct a Smithy client:
//! let client = Client::<DynConnector, MyMiddleware>::new(DynConnector::new(connector));
//! ```
use std::sync::Arc;
@ -14,22 +49,22 @@ use tower::{BoxError, Service};
use aws_smithy_async::rt::sleep::{default_async_sleep, AsyncSleep};
use aws_smithy_http::body::SdkBody;
use aws_smithy_http::result::ConnectorError;
pub use aws_smithy_http::result::{SdkError, SdkSuccess};
use std::error::Error;
use crate::hyper_impls::timeout_middleware::{ConnectTimeout, HttpReadTimeout, TimeoutError};
use crate::hyper_ext::timeout_middleware::{ConnectTimeout, HttpReadTimeout, TimeoutError};
use crate::{timeout, Builder as ClientBuilder};
use aws_smithy_async::future::timeout::TimedOutError;
use aws_smithy_types::retry::ErrorKind;
/// Adapter from a [`hyper::Client`] to a connector usable by a [`Client`](crate::Client).
/// Adapter from a [`hyper::Client`](hyper::Client) to a connector usable by a Smithy [`Client`](crate::Client).
///
/// This adapter also enables TCP connect and HTTP read timeouts via [`HyperAdapter::builder`]
/// This adapter also enables TCP `CONNECT` and HTTP `READ` timeouts via [`Adapter::builder`]. For examples
/// see [the module documentation](crate::hyper_ext).
#[derive(Clone, Debug)]
#[non_exhaustive]
pub struct HyperAdapter<C>(HttpReadTimeout<hyper::Client<ConnectTimeout<C>, SdkBody>>);
pub struct Adapter<C>(HttpReadTimeout<hyper::Client<ConnectTimeout<C>, SdkBody>>);
impl<C> Service<http::Request<SdkBody>> for HyperAdapter<C>
impl<C> Service<http::Request<SdkBody>> for Adapter<C>
where
C: Clone + Send + Sync + 'static,
C: tower::Service<Uri>,
@ -58,10 +93,10 @@ where
}
}
impl HyperAdapter<()> {
impl Adapter<()> {
/// Builder for a Hyper Adapter
///
/// Generally, end users should not need to construct a HyperAdapter manually: a hyper adapter
/// Generally, end users should not need to construct an [`Adapter`] manually: a hyper adapter
/// will be constructed automatically during client creation.
pub fn builder() -> Builder {
Builder::default()
@ -121,7 +156,26 @@ fn find_source<'a, E: Error + 'static>(err: &'a (dyn Error + 'static)) -> Option
}
#[derive(Default, Debug)]
/// Builder for [`HyperAdapter`]
/// Builder for [`hyper_ext::Adapter`](Adapter)
///
/// Unlike a Smithy client, the [`tower::Service`] inside a [`hyper_ext::Adapter`](Adapter) is actually a service that
/// accepts a `Uri` and returns a TCP stream. Two default implementations of this are provided, one
/// that encrypts the stream with `rustls`, the other that encrypts the stream with `native-tls`.
///
/// # Examples
/// Construct a HyperAdapter with the default HTTP implementation (rustls). This can be useful when you want to share a Hyper connector
/// between multiple Smithy clients.
///
/// ```rust
/// use tower::layer::util::Identity;
/// use aws_smithy_client::{conns, hyper_ext};
/// use aws_smithy_client::erase::DynConnector;
///
/// let hyper_connector = hyper_ext::Adapter::builder().build(conns::https());
/// // this client can then be used when constructing a Smithy Client
/// // TODO: replace `Identity` with your middleware implementation
/// let client = aws_smithy_client::Client::<DynConnector, Identity>::new(DynConnector::new(hyper_connector));
/// ```
pub struct Builder {
timeout: timeout::Settings,
sleep: Option<Arc<dyn AsyncSleep>>,
@ -130,7 +184,7 @@ pub struct Builder {
impl Builder {
/// Create a HyperAdapter from this builder and a given connector
pub fn build<C>(self, connector: C) -> HyperAdapter<C>
pub fn build<C>(self, connector: C) -> Adapter<C>
where
C: Clone + Send + Sync + 'static,
C: tower::Service<Uri>,
@ -161,7 +215,7 @@ impl Builder {
),
None => HttpReadTimeout::no_timeout(base),
};
HyperAdapter(http_timeout)
Adapter(http_timeout)
}
/// Set the async sleep implementation used for timeouts
@ -226,15 +280,15 @@ where
#[cfg(feature = "rustls")]
impl<M, R> ClientBuilder<(), M, R> {
/// Connect to the service over HTTPS using Rustls.
pub fn rustls(self) -> ClientBuilder<HyperAdapter<crate::conns::Https>, M, R> {
self.connector(HyperAdapter::builder().build(crate::conns::https()))
pub fn rustls(self) -> ClientBuilder<Adapter<crate::conns::Https>, M, R> {
self.connector(Adapter::builder().build(crate::conns::https()))
}
/// Connect to the service over HTTPS using Rustls.
///
/// This is exactly equivalent to [`Builder::rustls`](ClientBuilder::rustls). If you instead wish to use `native_tls`,
/// use `Builder::native_tls`.
pub fn https(self) -> ClientBuilder<HyperAdapter<crate::conns::Https>, M, R> {
pub fn https(self) -> ClientBuilder<Adapter<crate::conns::Https>, M, R> {
self.rustls()
}
}
@ -243,9 +297,8 @@ impl<M, R> ClientBuilder<(), M, R> {
/// Connect to the service over HTTPS using the native TLS library on your platform.
pub fn native_tls(
self,
) -> ClientBuilder<HyperAdapter<hyper_tls::HttpsConnector<hyper::client::HttpConnector>>, M, R>
{
self.connector(HyperAdapter::builder().build(crate::conns::native_tls()))
) -> ClientBuilder<Adapter<hyper_tls::HttpsConnector<hyper::client::HttpConnector>>, M, R> {
self.connector(Adapter::builder().build(crate::conns::native_tls()))
}
}
@ -454,7 +507,7 @@ mod timeout_middleware {
#[cfg(test)]
mod test {
use crate::hyper_impls::HyperAdapter;
use crate::hyper_ext::Adapter;
use crate::never::{NeverConnected, NeverReplies};
use crate::timeout;
use aws_smithy_async::rt::sleep::TokioSleep;
@ -490,7 +543,7 @@ mod timeout_middleware {
async fn connect_timeout_works() {
let inner = NeverConnected::new();
let timeout = timeout::Settings::new().with_connect_timeout(Duration::from_secs(1));
let mut hyper = HyperAdapter::builder()
let mut hyper = Adapter::builder()
.timeout(&timeout)
.sleep_impl(TokioSleep::new())
.build(inner);
@ -519,7 +572,7 @@ mod timeout_middleware {
let timeout = timeout::Settings::new()
.with_connect_timeout(Duration::from_secs(1))
.with_read_timeout(Duration::from_secs(2));
let mut hyper = HyperAdapter::builder()
let mut hyper = Adapter::builder()
.timeout(&timeout)
.sleep_impl(TokioSleep::new())
.build(inner);
@ -542,7 +595,7 @@ mod timeout_middleware {
#[cfg(test)]
mod test {
use crate::hyper_impls::HyperAdapter;
use crate::hyper_ext::Adapter;
use http::Uri;
use hyper::client::connect::{Connected, Connection};
@ -559,7 +612,7 @@ mod test {
let connector = TestConnection {
inner: HangupStream,
};
let mut adapter = HyperAdapter::builder().build(connector);
let mut adapter = Adapter::builder().build(connector);
use tower::Service;
let err = adapter
.call(

View File

@ -25,14 +25,7 @@ pub mod dvr;
pub mod test_connection;
#[cfg(feature = "hyper")]
mod hyper_impls;
/// Re-export HyperAdapter
#[cfg(feature = "hyper")]
pub mod hyper_ext {
pub use crate::hyper_impls::Builder;
pub use crate::hyper_impls::HyperAdapter as Adapter;
}
pub mod hyper_ext;
// The types in this module are only used to write the bounds in [`Client::check`]. Customers will
// not need them. But the module and its types must be public so that we can call `check` from
@ -40,6 +33,7 @@ pub mod hyper_ext {
#[doc(hidden)]
pub mod static_tests;
#[cfg(feature = "hyper")]
pub mod never;
pub mod timeout;
@ -74,9 +68,8 @@ pub mod conns {
pub type NativeTls = hyper_tls::HttpsConnector<hyper::client::HttpConnector>;
#[cfg(feature = "rustls")]
pub type Rustls = crate::hyper_impls::HyperAdapter<
hyper_rustls::HttpsConnector<hyper::client::HttpConnector>,
>;
pub type Rustls =
crate::hyper_ext::Adapter<hyper_rustls::HttpsConnector<hyper::client::HttpConnector>>;
}
use aws_smithy_http::body::SdkBody;

View File

@ -56,7 +56,7 @@ fn sanity_retry() {
// Statically check that a hyper client can actually be used to build a Client.
#[allow(dead_code)]
#[cfg(all(test, feature = "hyper"))]
fn sanity_hyper(hc: crate::hyper_impls::HyperAdapter<hyper::client::HttpConnector>) {
fn sanity_hyper(hc: crate::hyper_ext::Adapter<hyper::client::HttpConnector>) {
Builder::new()
.middleware(tower::layer::util::Identity::new())
.connector(hc)