AWS SDK

AWS SDK

rev. c77e2dcb46fd81a57ba78278c5efd6755aa011c1 (ignoring whitespace)

Files changed:

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-legacy-http/src/label.rs

@@ -0,1 +0,64 @@
           1  +
/*
           2  +
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
           3  +
 * SPDX-License-Identifier: Apache-2.0
           4  +
 */
           5  +
           6  +
//! Formatting values as Smithy
           7  +
//! [httpLabel](https://smithy.io/2.0/spec/http-bindings.html#httplabel-trait)
           8  +
           9  +
use crate::urlencode::BASE_SET;
          10  +
use aws_smithy_types::date_time::{DateTimeFormatError, Format};
          11  +
use aws_smithy_types::DateTime;
          12  +
use percent_encoding::AsciiSet;
          13  +
          14  +
const GREEDY: &AsciiSet = &BASE_SET.remove(b'/');
          15  +
          16  +
/// The encoding strategy used when parsing an `httpLabel`.
          17  +
#[non_exhaustive]
          18  +
#[derive(Clone, Debug, Eq, PartialEq)]
          19  +
pub enum EncodingStrategy {
          20  +
    /// The default strategy when parsing an `httpLabel`. Only one path segment will be matched.
          21  +
    Default,
          22  +
    /// When parsing an `httpLabel`, this strategy will attempt to parse as many path segments as possible.
          23  +
    Greedy,
          24  +
}
          25  +
          26  +
/// Format a given `httpLabel` as a string according to an [`EncodingStrategy`]
          27  +
pub fn fmt_string<T: AsRef<str>>(t: T, strategy: EncodingStrategy) -> String {
          28  +
    let uri_set = if strategy == EncodingStrategy::Greedy {
          29  +
        GREEDY
          30  +
    } else {
          31  +
        BASE_SET
          32  +
    };
          33  +
    percent_encoding::utf8_percent_encode(t.as_ref(), uri_set).to_string()
          34  +
}
          35  +
          36  +
/// Format a given [`DateTime`] as a string according to an [`EncodingStrategy`]
          37  +
pub fn fmt_timestamp(t: &DateTime, format: Format) -> Result<String, DateTimeFormatError> {
          38  +
    Ok(fmt_string(t.fmt(format)?, EncodingStrategy::Default))
          39  +
}
          40  +
          41  +
#[cfg(test)]
          42  +
mod test {
          43  +
    use crate::label::{fmt_string, EncodingStrategy};
          44  +
    use http_02x::Uri;
          45  +
    use proptest::proptest;
          46  +
          47  +
    #[test]
          48  +
    fn greedy_params() {
          49  +
        assert_eq!(fmt_string("a/b", EncodingStrategy::Default), "a%2Fb");
          50  +
        assert_eq!(fmt_string("a/b", EncodingStrategy::Greedy), "a/b");
          51  +
    }
          52  +
          53  +
    proptest! {
          54  +
        #[test]
          55  +
        fn test_encode_request(s: String) {
          56  +
            let _: Uri = format!("http://host.example.com/{}", fmt_string(&s, EncodingStrategy::Default))
          57  +
                .parse()
          58  +
                .expect("all strings should be encoded properly");
          59  +
            let _: Uri = format!("http://host.example.com/{}", fmt_string(&s, EncodingStrategy::Greedy))
          60  +
                .parse()
          61  +
                .expect("all strings should be encoded properly");
          62  +
        }
          63  +
    }
          64  +
}

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-legacy-http/src/lib.rs

@@ -0,1 +0,46 @@
           1  +
/*
           2  +
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
           3  +
 * SPDX-License-Identifier: Apache-2.0
           4  +
 */
           5  +
           6  +
/* Automatically managed default lints */
           7  +
#![cfg_attr(docsrs, feature(doc_cfg))]
           8  +
/* End of automatically managed default lints */
           9  +
#![warn(
          10  +
    missing_docs,
          11  +
    rustdoc::missing_crate_level_docs,
          12  +
    unreachable_pub,
          13  +
    rust_2018_idioms
          14  +
)]
          15  +
          16  +
//! Core HTTP primitives for service clients generated by [smithy-rs](https://github.com/smithy-lang/smithy-rs) including:
          17  +
//! - HTTP Body implementation
          18  +
//! - Endpoint support
          19  +
//! - HTTP header deserialization
          20  +
//! - Event streams
          21  +
//!
          22  +
//! | Feature        | Description |
          23  +
//! |----------------|-------------|
          24  +
//! | `rt-tokio`     | Provides features that are dependent on `tokio` including the `ByteStream::from_path` util |
          25  +
//! | `event-stream` | Provides Sender/Receiver implementations for Event Stream codegen. |
          26  +
          27  +
#![allow(clippy::derive_partial_eq_without_eq)]
          28  +
          29  +
pub mod endpoint;
          30  +
// Marked as `doc(hidden)` because a type in the module is used both by this crate and by the code
          31  +
// generator, but not by external users. Also, by the module being `doc(hidden)` instead of it being
          32  +
// in `rust-runtime/inlineable`, each user won't have to pay the cost of running the module's tests
          33  +
// when compiling their generated SDK.
          34  +
#[doc(hidden)]
          35  +
pub mod futures_stream_adapter;
          36  +
pub mod header;
          37  +
pub mod label;
          38  +
pub mod operation;
          39  +
pub mod query;
          40  +
#[doc(hidden)]
          41  +
pub mod query_writer;
          42  +
          43  +
#[cfg(feature = "event-stream")]
          44  +
pub mod event_stream;
          45  +
          46  +
mod urlencode;

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-legacy-http/src/operation.rs

@@ -0,1 +0,13 @@
           1  +
/*
           2  +
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
           3  +
 * SPDX-License-Identifier: Apache-2.0
           4  +
 */
           5  +
           6  +
//! Deprecated metadata type.
           7  +
           8  +
/// Metadata added to the [`ConfigBag`](aws_smithy_types::config_bag::ConfigBag) that identifies the API being called.
           9  +
#[deprecated(
          10  +
    since = "0.60.2",
          11  +
    note = "Use aws_smithy_runtime_api::client::orchestrator::Metadata instead."
          12  +
)]
          13  +
pub type Metadata = aws_smithy_runtime_api::client::orchestrator::Metadata;

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-legacy-http/src/query.rs

@@ -0,1 +0,97 @@
           1  +
/*
           2  +
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
           3  +
 * SPDX-License-Identifier: Apache-2.0
           4  +
 */
           5  +
           6  +
//! Utilities for writing Smithy values into a query string.
           7  +
//!
           8  +
//! Formatting values into the query string as specified in
           9  +
//! [httpQuery](https://smithy.io/2.0/spec/http-bindings.html#httpquery-trait)
          10  +
          11  +
use crate::urlencode::BASE_SET;
          12  +
use aws_smithy_types::date_time::{DateTimeFormatError, Format};
          13  +
use aws_smithy_types::DateTime;
          14  +
use percent_encoding::utf8_percent_encode;
          15  +
          16  +
/// Format a given string as a query string.
          17  +
pub fn fmt_string<T: AsRef<str>>(t: T) -> String {
          18  +
    utf8_percent_encode(t.as_ref(), BASE_SET).to_string()
          19  +
}
          20  +
          21  +
/// Format a given [`DateTime`] as a query string.
          22  +
pub fn fmt_timestamp(t: &DateTime, format: Format) -> Result<String, DateTimeFormatError> {
          23  +
    Ok(fmt_string(t.fmt(format)?))
          24  +
}
          25  +
          26  +
/// Simple abstraction to enable appending params to a string as query params.
          27  +
///
          28  +
/// ```rust
          29  +
/// use aws_smithy_http::query::Writer;
          30  +
/// let mut s = String::from("www.example.com");
          31  +
/// let mut q = Writer::new(&mut s);
          32  +
/// q.push_kv("key", "value");
          33  +
/// q.push_v("another_value");
          34  +
/// assert_eq!(s, "www.example.com?key=value&another_value");
          35  +
/// ```
          36  +
#[allow(missing_debug_implementations)]
          37  +
pub struct Writer<'a> {
          38  +
    out: &'a mut String,
          39  +
    prefix: char,
          40  +
}
          41  +
          42  +
impl<'a> Writer<'a> {
          43  +
    /// Create a new query string writer.
          44  +
    pub fn new(out: &'a mut String) -> Self {
          45  +
        Writer { out, prefix: '?' }
          46  +
    }
          47  +
          48  +
    /// Add a new key and value pair to this writer.
          49  +
    pub fn push_kv(&mut self, k: &str, v: &str) {
          50  +
        self.out.push(self.prefix);
          51  +
        self.out.push_str(k);
          52  +
        self.out.push('=');
          53  +
        self.out.push_str(v);
          54  +
        self.prefix = '&';
          55  +
    }
          56  +
          57  +
    /// Add a new value (which is its own key) to this writer.
          58  +
    pub fn push_v(&mut self, v: &str) {
          59  +
        self.out.push(self.prefix);
          60  +
        self.out.push_str(v);
          61  +
        self.prefix = '&';
          62  +
    }
          63  +
}
          64  +
          65  +
#[cfg(test)]
          66  +
mod test {
          67  +
    use crate::query::{fmt_string, Writer};
          68  +
    use http_02x::Uri;
          69  +
    use proptest::proptest;
          70  +
          71  +
    #[test]
          72  +
    fn url_encode() {
          73  +
        assert_eq!(fmt_string("y̆").as_str(), "y%CC%86");
          74  +
        assert_eq!(fmt_string(" ").as_str(), "%20");
          75  +
        assert_eq!(fmt_string("foo/baz%20").as_str(), "foo%2Fbaz%2520");
          76  +
        assert_eq!(fmt_string("&=").as_str(), "%26%3D");
          77  +
        assert_eq!(fmt_string("🐱").as_str(), "%F0%9F%90%B1");
          78  +
        // `:` needs to be encoded, but only for AWS services
          79  +
        assert_eq!(fmt_string("a:b"), "a%3Ab")
          80  +
    }
          81  +
          82  +
    #[test]
          83  +
    fn writer_sets_prefix_properly() {
          84  +
        let mut out = String::new();
          85  +
        let mut writer = Writer::new(&mut out);
          86  +
        writer.push_v("a");
          87  +
        writer.push_kv("b", "c");
          88  +
        assert_eq!(out, "?a&b=c");
          89  +
    }
          90  +
          91  +
    proptest! {
          92  +
        #[test]
          93  +
        fn test_encode_request(s: String) {
          94  +
            let _: Uri = format!("http://host.example.com/?{}", fmt_string(s)).parse().expect("all strings should be encoded properly");
          95  +
        }
          96  +
    }
          97  +
}

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-legacy-http/src/query_writer.rs

@@ -0,1 +0,177 @@
           1  +
/*
           2  +
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
           3  +
 * SPDX-License-Identifier: Apache-2.0
           4  +
 */
           5  +
           6  +
use crate::query::fmt_string as percent_encode_query;
           7  +
use http_02x::uri::InvalidUri;
           8  +
use http_02x::Uri;
           9  +
          10  +
/// Utility for updating the query string in a [`Uri`].
          11  +
#[allow(missing_debug_implementations)]
          12  +
pub struct QueryWriter {
          13  +
    base_uri: Uri,
          14  +
    new_path_and_query: String,
          15  +
    prefix: Option<char>,
          16  +
}
          17  +
          18  +
impl QueryWriter {
          19  +
    /// Creates a new `QueryWriter` from a string
          20  +
    pub fn new_from_string(uri: &str) -> Result<Self, InvalidUri> {
          21  +
        Ok(Self::new(&Uri::try_from(uri)?))
          22  +
    }
          23  +
          24  +
    /// Creates a new `QueryWriter` based off the given `uri`.
          25  +
    pub fn new(uri: &Uri) -> Self {
          26  +
        let new_path_and_query = uri
          27  +
            .path_and_query()
          28  +
            .map(|pq| pq.to_string())
          29  +
            .unwrap_or_default();
          30  +
        let prefix = if uri.query().is_none() {
          31  +
            Some('?')
          32  +
        } else if !uri.query().unwrap_or_default().is_empty() {
          33  +
            Some('&')
          34  +
        } else {
          35  +
            None
          36  +
        };
          37  +
        QueryWriter {
          38  +
            base_uri: uri.clone(),
          39  +
            new_path_and_query,
          40  +
            prefix,
          41  +
        }
          42  +
    }
          43  +
          44  +
    /// Clears all query parameters.
          45  +
    pub fn clear_params(&mut self) {
          46  +
        if let Some(index) = self.new_path_and_query.find('?') {
          47  +
            self.new_path_and_query.truncate(index);
          48  +
            self.prefix = Some('?');
          49  +
        }
          50  +
    }
          51  +
          52  +
    /// Inserts a new query parameter. The key and value are percent encoded
          53  +
    /// by `QueryWriter`. Passing in percent encoded values will result in double encoding.
          54  +
    pub fn insert(&mut self, k: &str, v: &str) {
          55  +
        self.insert_encoded(&percent_encode_query(k), &percent_encode_query(v));
          56  +
    }
          57  +
          58  +
    /// Inserts a new already encoded query parameter. The key and value will be inserted
          59  +
    /// as is.
          60  +
    pub fn insert_encoded(&mut self, encoded_k: &str, encoded_v: &str) {
          61  +
        if let Some(prefix) = self.prefix {
          62  +
            self.new_path_and_query.push(prefix);
          63  +
        }
          64  +
        self.prefix = Some('&');
          65  +
        self.new_path_and_query.push_str(encoded_k);
          66  +
        self.new_path_and_query.push('=');
          67  +
        self.new_path_and_query.push_str(encoded_v)
          68  +
    }
          69  +
          70  +
    /// Returns just the built query string.
          71  +
    pub fn build_query(self) -> String {
          72  +
        self.build_uri().query().unwrap_or_default().to_string()
          73  +
    }
          74  +
          75  +
    /// Returns a full [`Uri`] with the query string updated.
          76  +
    pub fn build_uri(self) -> Uri {
          77  +
        let mut parts = self.base_uri.into_parts();
          78  +
        parts.path_and_query = Some(
          79  +
            self.new_path_and_query
          80  +
                .parse()
          81  +
                .expect("adding query should not invalidate URI"),
          82  +
        );
          83  +
        Uri::from_parts(parts).expect("a valid URL in should always produce a valid URL out")
          84  +
    }
          85  +
}
          86  +
          87  +
#[cfg(test)]
          88  +
mod test {
          89  +
    use super::QueryWriter;
          90  +
    use http_02x::Uri;
          91  +
          92  +
    #[test]
          93  +
    fn empty_uri() {
          94  +
        let uri = Uri::from_static("http://www.example.com");
          95  +
        let mut query_writer = QueryWriter::new(&uri);
          96  +
        query_writer.insert("key", "val%ue");
          97  +
        query_writer.insert("another", "value");
          98  +
        assert_eq!(
          99  +
            query_writer.build_uri(),
         100  +
            Uri::from_static("http://www.example.com?key=val%25ue&another=value")
         101  +
        );
         102  +
    }
         103  +
         104  +
    #[test]
         105  +
    fn uri_with_path() {
         106  +
        let uri = Uri::from_static("http://www.example.com/path");
         107  +
        let mut query_writer = QueryWriter::new(&uri);
         108  +
        query_writer.insert("key", "val%ue");
         109  +
        query_writer.insert("another", "value");
         110  +
        assert_eq!(
         111  +
            query_writer.build_uri(),
         112  +
            Uri::from_static("http://www.example.com/path?key=val%25ue&another=value")
         113  +
        );
         114  +
    }
         115  +
         116  +
    #[test]
         117  +
    fn uri_with_path_and_query() {
         118  +
        let uri = Uri::from_static("http://www.example.com/path?original=here");
         119  +
        let mut query_writer = QueryWriter::new(&uri);
         120  +
        query_writer.insert("key", "val%ue");
         121  +
        query_writer.insert("another", "value");
         122  +
        assert_eq!(
         123  +
            query_writer.build_uri(),
         124  +
            Uri::from_static(
         125  +
                "http://www.example.com/path?original=here&key=val%25ue&another=value"
         126  +
            )
         127  +
        );
         128  +
    }
         129  +
         130  +
    #[test]
         131  +
    fn build_query() {
         132  +
        let uri = Uri::from_static("http://www.example.com");
         133  +
        let mut query_writer = QueryWriter::new(&uri);
         134  +
        query_writer.insert("key", "val%ue");
         135  +
        query_writer.insert("ano%ther", "value");
         136  +
        assert_eq!("key=val%25ue&ano%25ther=value", query_writer.build_query());
         137  +
    }
         138  +
         139  +
    #[test]
         140  +
    // This test ensures that the percent encoding applied to queries always produces a valid URI if
         141  +
    // the starting URI is valid
         142  +
    fn doesnt_panic_when_adding_query_to_valid_uri() {
         143  +
        let uri = Uri::from_static("http://www.example.com");
         144  +
         145  +
        let mut problematic_chars = Vec::new();
         146  +
         147  +
        for byte in u8::MIN..=u8::MAX {
         148  +
            match std::str::from_utf8(&[byte]) {
         149  +
                // If we can't make a str from the byte then we certainly can't make a URL from it
         150  +
                Err(_) => {
         151  +
                    continue;
         152  +
                }
         153  +
                Ok(value) => {
         154  +
                    let mut query_writer = QueryWriter::new(&uri);
         155  +
                    query_writer.insert("key", value);
         156  +
         157  +
                    if std::panic::catch_unwind(|| query_writer.build_uri()).is_err() {
         158  +
                        problematic_chars.push(char::from(byte));
         159  +
                    };
         160  +
                }
         161  +
            }
         162  +
        }
         163  +
         164  +
        if !problematic_chars.is_empty() {
         165  +
            panic!("we got some bad bytes here: {:#?}", problematic_chars)
         166  +
        }
         167  +
    }
         168  +
         169  +
    #[test]
         170  +
    fn clear_params() {
         171  +
        let uri = Uri::from_static("http://www.example.com/path?original=here&foo=1");
         172  +
        let mut query_writer = QueryWriter::new(&uri);
         173  +
        query_writer.clear_params();
         174  +
        query_writer.insert("new", "value");
         175  +
        assert_eq!("new=value", query_writer.build_query());
         176  +
    }
         177  +
}

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-legacy-http/src/urlencode.rs

@@ -0,1 +0,61 @@
           1  +
/*
           2  +
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
           3  +
 * SPDX-License-Identifier: Apache-2.0
           4  +
 */
           5  +
           6  +
use percent_encoding::{AsciiSet, CONTROLS};
           7  +
           8  +
/// base set of characters that must be URL encoded
           9  +
pub(crate) const BASE_SET: &AsciiSet = &CONTROLS
          10  +
    .add(b' ')
          11  +
    .add(b'/')
          12  +
    // RFC-3986 §3.3 allows sub-delims (defined in section2.2) to be in the path component.
          13  +
    // This includes both colon ':' and comma ',' characters.
          14  +
    // Smithy protocol tests & AWS services percent encode these expected values. Signing
          15  +
    // will fail if these values are not percent encoded
          16  +
    .add(b':')
          17  +
    .add(b',')
          18  +
    .add(b'?')
          19  +
    .add(b'#')
          20  +
    .add(b'[')
          21  +
    .add(b']')
          22  +
    .add(b'{')
          23  +
    .add(b'}')
          24  +
    .add(b'|')
          25  +
    .add(b'@')
          26  +
    .add(b'!')
          27  +
    .add(b'$')
          28  +
    .add(b'&')
          29  +
    .add(b'\'')
          30  +
    .add(b'(')
          31  +
    .add(b')')
          32  +
    .add(b'*')
          33  +
    .add(b'+')
          34  +
    .add(b';')
          35  +
    .add(b'=')
          36  +
    .add(b'%')
          37  +
    .add(b'<')
          38  +
    .add(b'>')
          39  +
    .add(b'"')
          40  +
    .add(b'^')
          41  +
    .add(b'`')
          42  +
    .add(b'\\');
          43  +
          44  +
#[cfg(test)]
          45  +
mod test {
          46  +
    use crate::urlencode::BASE_SET;
          47  +
    use percent_encoding::utf8_percent_encode;
          48  +
          49  +
    #[test]
          50  +
    fn set_includes_mandatory_characters() {
          51  +
        let chars = ":/?#[]@!$&'()*+,;=%";
          52  +
        let escaped = utf8_percent_encode(chars, BASE_SET).to_string();
          53  +
        assert_eq!(
          54  +
            escaped,
          55  +
            "%3A%2F%3F%23%5B%5D%40%21%24%26%27%28%29%2A%2B%2C%3B%3D%25"
          56  +
        );
          57  +
          58  +
        // sanity check that every character is escaped
          59  +
        assert_eq!(escaped.len(), chars.len() * 3);
          60  +
    }
          61  +
}