├── .github ├── issue_template.md └── pull_request_template.md ├── .gitignore ├── .mvn └── wrapper │ └── maven-wrapper.properties ├── CHANGES.md ├── LICENSE ├── README.md ├── UPGRADE.md ├── VERSION_PREFIX ├── build ├── doc ├── package ├── release ├── revision ├── src │ └── cognitect │ │ └── aws │ │ └── version_updater.clj └── version ├── deps.edn ├── dev └── resources │ └── log4j.properties ├── doc ├── testing.md ├── types.md └── versioning.md ├── examples ├── README.md ├── assume_role_example.clj ├── autoscaling.clj ├── dynamodb_examples.clj ├── ec2_examples.clj ├── iam_examples.clj ├── lambda_examples.clj ├── resources │ └── dynamodb │ │ ├── Forum.json │ │ ├── Reply.json │ │ └── Thread.json ├── s3_examples.clj └── ssm_examples.clj ├── latest-releases.edn ├── mvnw ├── mvnw.cmd ├── pom.xml ├── src └── cognitect │ └── aws │ ├── client │ ├── api.clj │ ├── api │ │ └── async.clj │ ├── impl.clj │ ├── protocol.clj │ ├── shared.clj │ ├── test_double.clj │ └── validation.clj │ ├── config.clj │ ├── credentials.clj │ ├── dynaload.clj │ ├── ec2_metadata_utils.clj │ ├── endpoint.clj │ ├── http.clj │ ├── http │ ├── cognitect.clj │ ├── default.clj │ └── java.clj │ ├── interceptors.clj │ ├── protocols.clj │ ├── protocols │ ├── ec2.clj │ ├── json.clj │ ├── query.clj │ ├── rest.clj │ ├── rest_json.clj │ └── rest_xml.clj │ ├── region.clj │ ├── resources.clj │ ├── retry.clj │ ├── service.clj │ ├── shape.clj │ ├── signers.clj │ └── util.clj └── test ├── resources ├── .aws │ ├── config │ └── credentials ├── aws-sig-v4-test-suite │ ├── get-header-key-duplicate │ │ ├── get-header-key-duplicate.authz │ │ ├── get-header-key-duplicate.creq │ │ ├── get-header-key-duplicate.req │ │ ├── get-header-key-duplicate.sreq │ │ └── get-header-key-duplicate.sts │ ├── get-header-value-multiline │ │ ├── get-header-value-multiline.authz │ │ ├── get-header-value-multiline.creq │ │ ├── get-header-value-multiline.req │ │ ├── get-header-value-multiline.sreq │ │ └── get-header-value-multiline.sts │ ├── get-header-value-order │ │ ├── get-header-value-order.authz │ │ ├── get-header-value-order.creq │ │ ├── get-header-value-order.req │ │ ├── get-header-value-order.sreq │ │ └── get-header-value-order.sts │ ├── get-header-value-trim │ │ ├── get-header-value-trim.authz │ │ ├── get-header-value-trim.creq │ │ ├── get-header-value-trim.req │ │ ├── get-header-value-trim.sreq │ │ └── get-header-value-trim.sts │ ├── get-unreserved │ │ ├── get-unreserved.authz │ │ ├── get-unreserved.creq │ │ ├── get-unreserved.req │ │ ├── get-unreserved.sreq │ │ └── get-unreserved.sts │ ├── get-utf8 │ │ ├── get-utf8.authz │ │ ├── get-utf8.creq │ │ ├── get-utf8.req │ │ ├── get-utf8.sreq │ │ └── get-utf8.sts │ ├── get-vanilla-empty-query-key │ │ ├── get-vanilla-empty-query-key.authz │ │ ├── get-vanilla-empty-query-key.creq │ │ ├── get-vanilla-empty-query-key.req │ │ ├── get-vanilla-empty-query-key.sreq │ │ └── get-vanilla-empty-query-key.sts │ ├── get-vanilla-query-order-key-case │ │ ├── get-vanilla-query-order-key-case.authz │ │ ├── get-vanilla-query-order-key-case.creq │ │ ├── get-vanilla-query-order-key-case.req │ │ ├── get-vanilla-query-order-key-case.sreq │ │ └── get-vanilla-query-order-key-case.sts │ ├── get-vanilla-query-order-key │ │ ├── get-vanilla-query-order-key.authz │ │ ├── get-vanilla-query-order-key.creq │ │ ├── get-vanilla-query-order-key.req │ │ ├── get-vanilla-query-order-key.sreq │ │ └── get-vanilla-query-order-key.sts │ ├── get-vanilla-query-order-value │ │ ├── get-vanilla-query-order-value.authz │ │ ├── get-vanilla-query-order-value.creq │ │ ├── get-vanilla-query-order-value.req │ │ ├── get-vanilla-query-order-value.sreq │ │ └── get-vanilla-query-order-value.sts │ ├── get-vanilla-query-unreserved │ │ ├── get-vanilla-query-unreserved.authz │ │ ├── get-vanilla-query-unreserved.creq │ │ ├── get-vanilla-query-unreserved.req │ │ ├── get-vanilla-query-unreserved.sreq │ │ └── get-vanilla-query-unreserved.sts │ ├── get-vanilla-query │ │ ├── get-vanilla-query.authz │ │ ├── get-vanilla-query.creq │ │ ├── get-vanilla-query.req │ │ ├── get-vanilla-query.sreq │ │ └── get-vanilla-query.sts │ ├── get-vanilla-utf8-query │ │ ├── get-vanilla-utf8-query.authz │ │ ├── get-vanilla-utf8-query.creq │ │ ├── get-vanilla-utf8-query.req │ │ ├── get-vanilla-utf8-query.sreq │ │ └── get-vanilla-utf8-query.sts │ ├── get-vanilla │ │ ├── get-vanilla.authz │ │ ├── get-vanilla.creq │ │ ├── get-vanilla.req │ │ ├── get-vanilla.sreq │ │ └── get-vanilla.sts │ ├── normalize-path │ │ ├── get-relative-relative │ │ │ ├── get-relative-relative.authz │ │ │ ├── get-relative-relative.creq │ │ │ ├── get-relative-relative.req │ │ │ ├── get-relative-relative.sreq │ │ │ └── get-relative-relative.sts │ │ ├── get-relative │ │ │ ├── get-relative.authz │ │ │ ├── get-relative.creq │ │ │ ├── get-relative.req │ │ │ ├── get-relative.sreq │ │ │ └── get-relative.sts │ │ ├── get-slash-dot-slash │ │ │ ├── get-slash-dot-slash.authz │ │ │ ├── get-slash-dot-slash.creq │ │ │ ├── get-slash-dot-slash.req │ │ │ ├── get-slash-dot-slash.sreq │ │ │ └── get-slash-dot-slash.sts │ │ ├── get-slash-pointless-dot │ │ │ ├── get-slash-pointless-dot.authz │ │ │ ├── get-slash-pointless-dot.creq │ │ │ ├── get-slash-pointless-dot.req │ │ │ ├── get-slash-pointless-dot.sreq │ │ │ └── get-slash-pointless-dot.sts │ │ ├── get-slash │ │ │ ├── get-slash.authz │ │ │ ├── get-slash.creq │ │ │ ├── get-slash.req │ │ │ ├── get-slash.sreq │ │ │ └── get-slash.sts │ │ ├── get-slashes │ │ │ ├── get-slashes.authz │ │ │ ├── get-slashes.creq │ │ │ ├── get-slashes.req │ │ │ ├── get-slashes.sreq │ │ │ └── get-slashes.sts │ │ ├── get-space │ │ │ ├── get-space.authz │ │ │ ├── get-space.creq │ │ │ ├── get-space.req │ │ │ ├── get-space.sreq │ │ │ └── get-space.sts │ │ └── normalize-path.txt │ ├── post-header-key-case │ │ ├── post-header-key-case.authz │ │ ├── post-header-key-case.creq │ │ ├── post-header-key-case.req │ │ ├── post-header-key-case.sreq │ │ └── post-header-key-case.sts │ ├── post-header-key-sort │ │ ├── post-header-key-sort.authz │ │ ├── post-header-key-sort.creq │ │ ├── post-header-key-sort.req │ │ ├── post-header-key-sort.sreq │ │ └── post-header-key-sort.sts │ ├── post-header-value-case │ │ ├── post-header-value-case.authz │ │ ├── post-header-value-case.creq │ │ ├── post-header-value-case.req │ │ ├── post-header-value-case.sreq │ │ └── post-header-value-case.sts │ ├── post-sts-token │ │ ├── post-sts-header-after │ │ │ ├── post-sts-header-after.authz │ │ │ ├── post-sts-header-after.creq │ │ │ ├── post-sts-header-after.req │ │ │ ├── post-sts-header-after.sreq │ │ │ └── post-sts-header-after.sts │ │ ├── post-sts-header-before │ │ │ ├── post-sts-header-before.authz │ │ │ ├── post-sts-header-before.creq │ │ │ ├── post-sts-header-before.req │ │ │ ├── post-sts-header-before.sreq │ │ │ └── post-sts-header-before.sts │ │ └── readme.txt │ ├── post-vanilla-empty-query-value │ │ ├── post-vanilla-empty-query-value.authz │ │ ├── post-vanilla-empty-query-value.creq │ │ ├── post-vanilla-empty-query-value.req │ │ ├── post-vanilla-empty-query-value.sreq │ │ └── post-vanilla-empty-query-value.sts │ ├── post-vanilla-query │ │ ├── post-vanilla-query.authz │ │ ├── post-vanilla-query.creq │ │ ├── post-vanilla-query.req │ │ ├── post-vanilla-query.sreq │ │ └── post-vanilla-query.sts │ ├── post-vanilla │ │ ├── post-vanilla.authz │ │ ├── post-vanilla.creq │ │ ├── post-vanilla.req │ │ ├── post-vanilla.sreq │ │ └── post-vanilla.sts │ ├── post-x-www-form-urlencoded-parameters │ │ ├── post-x-www-form-urlencoded-parameters.authz │ │ ├── post-x-www-form-urlencoded-parameters.creq │ │ ├── post-x-www-form-urlencoded-parameters.req │ │ ├── post-x-www-form-urlencoded-parameters.sreq │ │ └── post-x-www-form-urlencoded-parameters.sts │ └── post-x-www-form-urlencoded │ │ ├── post-x-www-form-urlencoded.authz │ │ ├── post-x-www-form-urlencoded.creq │ │ ├── post-x-www-form-urlencoded.req │ │ ├── post-x-www-form-urlencoded.sreq │ │ └── post-x-www-form-urlencoded.sts ├── botocore │ └── protocols │ │ ├── input │ │ ├── ec2.json │ │ ├── json.json │ │ ├── query.json │ │ ├── rest-json.json │ │ └── rest-xml.json │ │ └── output │ │ ├── ec2.json │ │ ├── event-stream.json │ │ ├── json.json │ │ ├── query.json │ │ ├── rest-json.json │ │ └── rest-xml.json └── cognitect │ └── protocols │ ├── input │ ├── query.json │ └── rest-xml.json │ └── output │ ├── json.json │ ├── rest-json.json │ └── rest-xml.json └── src └── cognitect ├── aws ├── api_test.clj ├── client │ └── shared_test.clj ├── config_test.clj ├── credentials_test.clj ├── ec2_metadata_utils_test.clj ├── endpoint_test.clj ├── generators.clj ├── http │ ├── default_test.clj │ └── java_test.clj ├── http_test.clj ├── integration │ ├── error_codes_test.clj │ ├── fixtures.clj │ └── s3_test.clj ├── interceptors_test.clj ├── jdk.clj ├── protocols │ └── rest_test.clj ├── protocols_test.clj ├── region_test.clj ├── retry_test.clj ├── shape_test.clj ├── signers_test.clj ├── test │ ├── ec2_metadata_utils_server.clj │ └── utils.clj └── util_test.clj └── client ├── impl_test.clj └── test_double_test.clj /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | Thank you for your interest in helping to improve Cognitect's aws-api! 2 | 3 | ## Dependencies 4 | 5 | Be sure to list the precise libs and versions you are using ("the 6 | latest" might change by the time we're looking at your issue). 7 | 8 | e.g. 9 | 10 | ``` clojure 11 | {:deps {com.cognitect.aws/api {:mvn/version "0.8.292"} 12 | com.cognitect.aws/endpoints {:mvn/version "1.1.11.532"} 13 | com.cognitect.aws/s3 {:mvn/version "714.2.430.0"}}} 14 | ``` 15 | 16 | ## Description with failing test case 17 | 18 | Please describe what you are trying to do, what you expect to see, and 19 | what you're seeing instead. 20 | 21 | *Important*: Please include a complete minimal code example that we 22 | can paste as/is into a REPL, execute, and watch fail. 23 | 24 | ## Stack traces 25 | 26 | If you're including a strack trace, please be sure to format it using 27 | markdown formatting (wrap it in "```"). 28 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | Thank you for your interest in contributing to Cognitect's aws-api! 2 | 3 | As we incorporate this library into products and client projects, we 4 | do not accept pull requests or patches. 5 | 6 | We do, however, want to know how we can make it better, so please file 7 | an issue at https://github.com/cognitect-labs/aws-api/issues. 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .cpcache 2 | target 3 | logs 4 | log 5 | .nrepl-port 6 | VERSION_SUFFIX 7 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | wrapperVersion=3.3.2 18 | distributionType=only-script 19 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip 20 | -------------------------------------------------------------------------------- /UPGRADE.md: -------------------------------------------------------------------------------- 1 | # Upgrade Notes 2 | 3 | ## 0.8.711 / 2024-12-03 4 | 5 | ### New Java-native HTTP client 6 | 7 | This release provides a new `java.net.http`-based HTTP client. 8 | 9 | This release changes the default type of http client to be the new Java 10 | native client, when the version of Java is recent enough (11 or newer). 11 | 12 | With this release, the `com.cognitect/http-client` is no longer 13 | a required dependency for this library. If you need to run on Java 8 14 | (which predates the `java.net.http` module), you must add an explicit 15 | dependency on `com.cognitect/http-client` in your project, to make the 16 | previous HTTP client implementation available again - it will be 17 | automatically used when running on Java 8, as long as it is in the 18 | classpath. 19 | 20 | If you only need to run on java 11+, the new HTTP client is now the 21 | default, and the change should be transparent. In case you want to 22 | revert to the previous HTTP client implementation, please see the 23 | README section about [overriding the http 24 | client](README.md#overriding-the-http-client). 25 | 26 | This fixes issues 27 | [181](https://github.com/cognitect-labs/aws-api/issues/181) and 28 | [250](https://github.com/cognitect-labs/aws-api/issues/250). 29 | 30 | ## 0.8.430 31 | 32 | This release changed the behavior of the following functions: 33 | 34 | ### com.cognitect.aws.api/client 35 | 36 | As of 0.8.430, each aws-api client uses a single shared http-client by 37 | default. Before this release, each aws-client got its own instance of 38 | http-client by default, which caused the number of threads consumed to 39 | increase linearly in relation to the number of aws-clients created. 40 | To reduce resource consumption in the case of many aws-clients, we 41 | recommended that you create a single instance of the http-client and 42 | explicitly share it across all aws-clients. This is no longer 43 | necessary. 44 | 45 | ### com.cognitect.aws.api/stop 46 | 47 | With the introduction of a shared http-client, this function was 48 | updated so that it has no effect when using the shared http-client, 49 | but will continue to call `cognitect.aws.http/stop` on any other 50 | http-client instance. 51 | 52 | ### effects 53 | 54 | These changes have the following effects: 55 | 56 | Programs that were creating multiple aws-clients without supplying 57 | an http-client, and without ever calling stop, will see a reduction 58 | in resource consumption. 59 | 60 | Programs that were creating an instance of 61 | `cognitect.aws.client.api/default-http-client` and sharing it across 62 | aws-clients should see no change. You can, however, safely stop doing 63 | that. 64 | 65 | For programs that were using the default aws-client constructor and 66 | calling stop on each aws-client, the shared http-client will not be 67 | shut down. This should have no negative impact on resource consumption, 68 | as there is only one http-client in this case, and its resources are 69 | managed by aws-api. 70 | 71 | For programs that were creating multiple aws-clients in order to get 72 | around an ["Ops limit reached" 73 | error](https://github.com/cognitect-labs/aws-api/issues/98), this is a 74 | breaking change. For this case, we recommend, for now, that you supply 75 | a new http-client for each aws-client. 76 | -------------------------------------------------------------------------------- /VERSION_PREFIX: -------------------------------------------------------------------------------- 1 | 0.8 2 | -------------------------------------------------------------------------------- /build/doc: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | echo "Building docs...\n" 6 | rm -rf ./target/autodoc 7 | ./mvnw -Pautodoc clojure:autodoc 8 | 9 | echo -e "Checking out gh-pages branch\n" 10 | rm -rf gh-pages 11 | git clone --quiet --branch=gh-pages git@github.com:cognitect-labs/aws-api.git gh-pages > /dev/null 12 | cd gh-pages 13 | 14 | echo -e "Replacing old gh-pages content with new docs\n" 15 | git rm -rf ./* 16 | cp -Rf ../target/autodoc/* ./ 17 | git add -f . 18 | git commit -m "Updating gh-pages with new api docs" 19 | git push -fq origin gh-pages > /dev/null 20 | cd .. 21 | 22 | echo -e "Cleaning up\n" 23 | rm -rf gh-pages 24 | -------------------------------------------------------------------------------- /build/package: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | echo "Cleaning..." 6 | rm -rf ./target 7 | 8 | echo "Calculating version..." 9 | version=`build/version` 10 | echo $version 11 | 12 | target_name=api-${version} 13 | 14 | echo "Packaging..." 15 | ./mvnw versions:set -DnewVersion=${version} 16 | ./mvnw clean install -DcreateChecksum=true 17 | ./mvnw versions:revert 18 | 19 | echo "Package done!" 20 | -------------------------------------------------------------------------------- /build/release: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | echo "Cleaning..." 6 | rm -rf ./target 7 | 8 | echo "Aligning pom.xml with deps.edn ..." 9 | clj -Srepro -Spom 10 | if [ "$(git diff pom.xml)" = "" ]; then 11 | echo "nothing to change" 12 | else 13 | git add pom.xml 14 | git commit -m "Update deps in pom.xml" 15 | fi 16 | 17 | echo "Calculating version..." 18 | version=`build/version` 19 | echo $version 20 | 21 | echo "Releasing..." 22 | ./mvnw versions:set -DnewVersion=${version} 23 | ./mvnw clean deploy 24 | ./mvnw versions:revert 25 | 26 | echo "Tagging..." 27 | git tag -a v${version} -m "Release ${version}" 28 | git push ${AWS_API_REMOTE:-origin} v${version} 29 | 30 | echo "Updating README.md, CHANGES.md, UPGRADE.md, and latest-releases.edn with ${version}" 31 | clj -A:update-versions --update-latest-releases --update-changelog --update-readme 32 | git commit -m "Update README.md, CHANGES.md, UPGRADE.md, and latest-releases.edn with ${version}" \ 33 | README.md CHANGES.md UPGRADE.md latest-releases.edn 34 | git push 35 | 36 | echo "Updating gh-pages with new api docs" 37 | build/doc 38 | 39 | echo "Release done!" 40 | -------------------------------------------------------------------------------- /build/revision: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Returns the revision number used for deployment. 4 | 5 | set -e 6 | 7 | REVISION=`git --no-replace-objects describe --tags --match rev0` 8 | 9 | # Extract the version number from the string. Do this in two steps so 10 | # it is a little easier to understand. 11 | REVISION=${REVISION:5} # drop the first 5 characters 12 | REVISION=${REVISION:0:${#REVISION}-9} # drop the last 9 characters 13 | 14 | echo $REVISION 15 | -------------------------------------------------------------------------------- /build/src/cognitect/aws/version_updater.clj: -------------------------------------------------------------------------------- 1 | (ns cognitect.aws.version-updater 2 | (:require [clojure.java.io :as io] 3 | [clojure.string :as str] 4 | [clojure.edn :as edn] 5 | [clojure.pprint] 6 | [clojure.java.shell :as shell]) 7 | (:import (java.io BufferedWriter) 8 | (java.util Date))) 9 | 10 | (set! *warn-on-reflection* true) 11 | (set! *print-namespace-maps* false) 12 | 13 | (defn release-log-map [] 14 | (sorted-map-by (fn [a b] 15 | (cond 16 | ; equals compare equals 17 | (= a b) 0 18 | ; api artifact must come first 19 | (= "api" (name a)) -1 20 | (= "api" (name b)) 1 21 | ; endpoints must come next 22 | (= "endpoints" (name a)) -1 23 | (= "endpoints" (name b)) 1 24 | ; everything else is sorted alphabetically 25 | :else (compare a b))))) 26 | 27 | (defn version-prefix [] 28 | (read-string (slurp (io/file "VERSION_PREFIX")))) 29 | 30 | (defn git-revision [] 31 | (-> (:out (shell/sh "build/revision")) 32 | (str/split #"\n") 33 | first)) 34 | 35 | (defn version [] 36 | (-> (:out (shell/sh "build/version")) 37 | (str/split #"\n") 38 | first)) 39 | 40 | (defn update-file [fname* xform] 41 | (let [[fname ext] (str/split fname* #"\.") 42 | f (io/file fname*) 43 | cp (java.io.File/createTempFile fname (str "." ext))] 44 | (io/copy f cp) 45 | (with-open [r (io/reader cp) 46 | ^BufferedWriter w (io/writer f)] 47 | (doseq [l (line-seq r)] 48 | (.write w ^String (xform l)) 49 | (.newLine w))))) 50 | 51 | (defn latest-releases [] 52 | (-> (io/file "latest-releases.edn") 53 | slurp 54 | edn/read-string)) 55 | 56 | (defn update-version-in [fname latest libname] 57 | (let [version (get-in latest [(symbol "com.cognitect.aws" libname) :mvn/version])] 58 | (update-file fname 59 | #(if (re-find (re-pattern (str "com.cognitect.aws\\/" libname "\\s+\\{:mvn\\/version")) %) 60 | (str/replace-first % (re-pattern "\\d+(.\\d+)+") version) 61 | %)))) 62 | 63 | (defn update-versions-in-readme [] 64 | (let [latest (latest-releases)] 65 | (doseq [svc ["api" "endpoints" "s3"]] 66 | (update-version-in "README.md" latest svc)))) 67 | 68 | (defn update-versions-in-deps [] 69 | (let [latest (latest-releases)] 70 | (doseq [svc (map name (keys latest))] 71 | (update-version-in "deps.edn" latest svc)))) 72 | 73 | (defn update-changelog [version] 74 | (doseq [fname ["CHANGES.md" "UPGRADE.md"]] 75 | (update-file fname 76 | #(if (re-find (re-pattern "## DEV") %) 77 | (str/replace-first % 78 | (re-pattern "DEV") 79 | (str version " / " (.format (java.text.SimpleDateFormat. "yyyy-MM-dd") (Date.)))) 80 | %)))) 81 | 82 | (defn update-api-version-in-latest-releases [version] 83 | (let [f (io/file "latest-releases.edn") 84 | data (edn/read-string (slurp f))] 85 | (binding [*print-namespace-maps* false 86 | *print-length* 500] 87 | (spit f 88 | (with-out-str 89 | (clojure.pprint/pprint 90 | (into (release-log-map) 91 | (assoc-in data ['com.cognitect.aws/api :mvn/version] version)))))))) 92 | 93 | (defn -main [& argv] 94 | (let [args (set argv) 95 | v (version)] 96 | (when (contains? args "--update-latest-releases") 97 | (prn "Updating api version in latest releases") 98 | (update-api-version-in-latest-releases v)) 99 | (when (contains? args "--update-changelog") 100 | (println "Updating changelog") 101 | (update-changelog v)) 102 | (when (contains? args "--update-readme") 103 | (println "Updating README") 104 | (update-versions-in-readme)) 105 | (when (contains? args "--update-deps") 106 | (println "Updating deps.edn") 107 | (update-versions-in-deps))) 108 | (System/exit 0)) 109 | 110 | (comment 111 | (version) 112 | 113 | (git-revision) 114 | 115 | ) 116 | -------------------------------------------------------------------------------- /build/version: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Calculates the full version string for a release 4 | # Optionally includes a version suffix (such as for a beta release) if a VERSION_SUFFIX file exists. 5 | 6 | set -e 7 | 8 | prefix=`cat VERSION_PREFIX` 9 | suffix=`build/revision` 10 | 11 | if [ -f "VERSION_SUFFIX" ]; then 12 | suffix=$suffix`cat VERSION_SUFFIX` 13 | fi 14 | 15 | version=$prefix.$suffix 16 | 17 | echo $version 18 | -------------------------------------------------------------------------------- /deps.edn: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | {:paths ["src"] 5 | :deps {org.clojure/clojure {:mvn/version "1.12.0"} 6 | org.clojure/core.async {:mvn/version "1.8.741"} 7 | org.clojure/tools.logging {:mvn/version "1.3.0"} 8 | org.clojure/data.json {:mvn/version "2.5.1"} 9 | org.clojure/data.xml {:mvn/version "0.2.0-alpha9"}} 10 | :aliases {:update-versions {:extra-paths ["build/src"] 11 | :main-opts ["-m" "cognitect.aws.version-updater"]} 12 | :dev {:extra-paths ["dev/src" "dev/resources" "test/src" "test/resources" "examples" "examples/resources"] 13 | :extra-deps {commons-io/commons-io {:mvn/version "2.18.0"} 14 | org.clojure/test.check {:mvn/version "1.1.1"} 15 | org.slf4j/slf4j-reload4j {:mvn/version "2.0.16"} 16 | http-kit/http-kit {:mvn/version "2.8.0"} 17 | com.amazonaws/aws-java-sdk-s3 {:mvn/version "1.12.779"} 18 | com.cognitect/http-client {:mvn/version "1.0.127"} 19 | com.cognitect.aws/endpoints {:mvn/version "871.2.31.23"} 20 | com.cognitect.aws/autoscaling {:mvn/version "871.2.29.35"} 21 | com.cognitect.aws/dynamodb {:mvn/version "871.2.31.23"} 22 | com.cognitect.aws/ec2 {:mvn/version "871.2.31.23"} 23 | com.cognitect.aws/iam {:mvn/version "871.2.30.22"} 24 | com.cognitect.aws/lambda {:mvn/version "871.2.31.23"} 25 | com.cognitect.aws/s3 {:mvn/version "871.2.31.23"} 26 | com.cognitect.aws/ssm {:mvn/version "871.2.31.23"} 27 | com.cognitect.aws/sts {:mvn/version "871.2.29.52"}}} 28 | :test {:extra-deps {io.github.cognitect-labs/test-runner {:git/tag "v0.5.1" :git/sha "dfb30dd"}} 29 | :main-opts ["-m" "cognitect.test-runner" 30 | "-e" "integration"]} 31 | :test-integration {:extra-deps {io.github.cognitect-labs/test-runner {:git/tag "v0.5.1" :git/sha "dfb30dd"}} 32 | :main-opts ["-m" "cognitect.test-runner" 33 | "-i" "integration"]}}} 34 | -------------------------------------------------------------------------------- /dev/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootLogger=DEBUG, file 2 | 3 | log4j.appender.file=org.apache.log4j.RollingFileAppender 4 | log4j.appender.file.File=log/aws-api.log 5 | log4j.appender.file.maxFileSize=20MB 6 | log4j.appender.file.layout=org.apache.log4j.PatternLayout 7 | log4j.appender.file.layout.ConversionPattern=%5p [%c] %m%n 8 | -------------------------------------------------------------------------------- /doc/testing.md: -------------------------------------------------------------------------------- 1 | # Test support 2 | 3 | aws-api provides a [test double](http://xunitpatterns.com/Test%20Double.html) 4 | implementation to test code that uses aws-api offline and even with no AWS 5 | account. To use it, instrument a handler fn or literal response for every 6 | op that will be invoked (via `aws/invoke` or `aws/invoke-async`) during a 7 | test, e.g. 8 | 9 | ```clojure 10 | (require '[cognitect.aws.client.test-double :as test] 11 | '[cognitect.aws.client.api :as aws]) 12 | 13 | ;; implementation being tested 14 | (defn do-something [s3-client] 15 | (let [res (aws/invoke s3-client {:op :CreateBucket 16 | :request {:Bucket "a-bucket"}})] 17 | ;; do stuff with res 18 | )) 19 | 20 | ;; test using a handler function 21 | (let [test-s3-client 22 | (test/client {:api :s3 23 | :ops {:ListBuckets (fn [{:keys [op request] :as op-map}] 24 | ;; do stuff based on op-map 25 | ;; then, return a value 26 | {:Location "def"})}})] 27 | (let [res (do-something test-s3-client)] 28 | ;; make assertions about res 29 | )) 30 | 31 | ;; test using a literal response 32 | (let [test-s3-client 33 | (test/client {:api :s3 34 | :ops {:CreateBucket {:Location "a-location"}}})] 35 | (let [res (do-something test-s3-client)] 36 | ;; make assertions about res 37 | )) 38 | 39 | ;; instrument test client after initialization 40 | (let [test-s3-client (test/client {:api :s3})] 41 | (test/instrument test-s3-client {:CreateBucket {:Location "a-location"}}) 42 | (let [res (do-something test-s3-client)] 43 | ;; make assertions about res 44 | ) 45 | (test/instrument test-s3-client {:CreateBucket {:Location "another-location"}}) 46 | (let [res (do-something test-s3-client)] 47 | ;; make assertions about res 48 | )) 49 | ``` 50 | 51 | ### Test Doubles 52 | 53 | [Test Double](http://xunitpatterns.com/Test%20Double.html) is a general term for an object 54 | that doubles for a "real" object in a test. There are many types of test doubles and plenty 55 | of discussion about the costs/benefits of each, however, aside from explicitly supporting 56 | [test stubs](http://xunitpatterns.com/Test%20Stub.html), we are not supporting any other 57 | type of test double directly. Handler functions, however, give you leverage to implement 58 | any other type of test double. 59 | 60 | ### Features 61 | 62 | - bind literal values or handler functions to keys in a map bound to :ops 63 | - literal values will be returned as/is 64 | - handlers should be functions of the op-map passed to invoke and return a value valid 65 | for the op 66 | 67 | ### Helpful Feedback 68 | 69 | `client` will throw when you instrument an op that is not supported by the service 70 | 71 | `invoke` will return an anomaly when 72 | - you invoke an op that is not supported by the service 73 | - you invoke an op that was not instrumented in the client 74 | - you invoke with an invalid :request payload 75 | 76 | `invoke-async` will put an anomaly on the channel it returns, following 77 | the same conditions as `invoke` 78 | 79 | ### Limitations 80 | 81 | - the test client only supports the `invoke`, `invoke-async`, and `stop` functions supported 82 | by the normal aws api client 83 | - as much as we'd love to, we have no reliable way to validate or generate responses that 84 | mimic those produced by AWS, therefore 85 | - you must instrument a handler or response map for every op that will be invoked during a test 86 | - `client` will not validate the response payloads you provide 87 | -------------------------------------------------------------------------------- /doc/types.md: -------------------------------------------------------------------------------- 1 | # Data Types 2 | 3 | AWS service descriptions define a number of data types for use in `:request` maps passed to `cognitect.aws.client.api/invoke` and responses. aws-api supports them as follows: 4 | 5 | | AWS type | Clojure/java input type | Clojure/java output type (if different) | 6 | |-----------|-----------------------------------|-----------------------------------------| 7 | | structure | map with keyword keys | | 8 | | map | map with arbitrary types for keys | | 9 | | list | sequence | | 10 | | string | string | | 11 | | character | character | | 12 | | boolean | boolean | | 13 | | double | double | | 14 | | float | double | | 15 | | long | long | | 16 | | integer | long | | 17 | | blob | byte[] or java.io.InputStream* | java.io.InputStream | 18 | | timestamp | java.util.Date | | 19 | 20 | * for the time being, if you submit a `java.io.InputStream` for a `blob`, 21 | it must fit in memory. 22 | 23 | You can validate that your request maps conform to these types by enabling `clojure.spec`-backed request validation during development: 24 | 25 | ``` clojure 26 | (cognitect.aws.client.api/validate-requests client true) 27 | ``` 28 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # aws-api examples 2 | 3 | This directory contains examples of usage of aws-api. To explore, 4 | clone this repo and start a repl in your preferred environment 5 | using the deps.edn in the project root, e.g. 6 | 7 | ``` 8 | clj -A:dev 9 | ``` 10 | 11 | Then you can open any of the xxx_examples.clj files and start evaluating forms. In each example 12 | namespace, forms are contained within a `comment` block to prevent their accidental side-effectful 13 | evaluation. 14 | -------------------------------------------------------------------------------- /examples/assume_role_example.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns assume-role-example 5 | (:require [clojure.data.json :as json] 6 | [cognitect.aws.client.api :as aws] 7 | [cognitect.aws.credentials :as credentials])) 8 | 9 | (defn assumed-role-credentials-provider 10 | "make a credentials provider that can assume a role" 11 | [role-arn] 12 | (let [sts (aws/client {:api :sts})] 13 | (credentials/cached-credentials-with-auto-refresh 14 | (reify credentials/CredentialsProvider 15 | (fetch [_] 16 | (when-let [creds (:Credentials 17 | (aws/invoke sts 18 | {:op :AssumeRole 19 | :request {:RoleArn role-arn 20 | :RoleSessionName (str (gensym "example-session-"))}}))] 21 | {:aws/access-key-id (:AccessKeyId creds) 22 | :aws/secret-access-key (:SecretAccessKey creds) 23 | :aws/session-token (:SessionToken creds) 24 | ::credentials/ttl (credentials/calculate-ttl creds)})))))) 25 | 26 | (comment 27 | 28 | (def iam (aws/client {:api :iam})) 29 | 30 | (->> (aws/invoke iam {:op :ListRoles}) :Roles (map :RoleName)) 31 | 32 | ;; who am I? 33 | (aws/invoke iam {:op :GetUser}) 34 | 35 | (def me (:User *1)) 36 | 37 | ;; make a role to use for this example 38 | (aws/invoke iam {:op :CreateRole 39 | :request {:RoleName "aws-api-example-role" 40 | :AssumeRolePolicyDocument 41 | (json/json-str 42 | {"Version" "2012-10-17", 43 | "Statement" [{"Effect" "Allow" 44 | "Principal" {"AWS" [(:Arn me)]} 45 | "Action" ["sts:AssumeRole"]}]})}}) 46 | 47 | (def new-role (:Role (aws/invoke iam {:op :GetRole 48 | :request {:RoleName "aws-api-example-role"}}))) 49 | 50 | ;; make a policy to use for this example 51 | (aws/invoke iam {:op :CreatePolicy 52 | :request {:PolicyName "IAMGetMe" 53 | :PolicyDocument 54 | (json/json-str 55 | {"Version" "2012-10-17", 56 | "Statement" [{"Effect" "Allow" 57 | "Action" ["iam:GetUser"] 58 | "Resource" [(:Arn me)]}]})}}) 59 | 60 | (def policy (->> (aws/invoke iam {:op :ListPolicies}) 61 | :Policies 62 | (filter #(re-find #"IAMGetMe" (:Arn %))) 63 | first)) 64 | 65 | ;; attach the new policy to the new role 66 | (aws/invoke iam {:op :AttachRolePolicy :request {:RoleName (:RoleName new-role) 67 | :PolicyArn (:Arn policy)}}) 68 | 69 | 70 | (def provider (assumed-role-credentials-provider (:Arn new-role))) 71 | 72 | ;; make a client using the assumed role credentials provider 73 | (def iam-with-assumed-role (aws/client {:api :iam :credentials-provider provider})) 74 | 75 | ;; use it! 76 | (aws/invoke iam-with-assumed-role {:op :GetUser :request {:UserName (:UserName me)}}) 77 | 78 | ;; clean up 79 | (aws/invoke iam {:op :DetachRolePolicy :request {:RoleName (:RoleName new-role) :PolicyArn (:Arn policy)}}) 80 | (aws/invoke iam {:op :DeletePolicy :request {:PolicyArn (:Arn policy)}}) 81 | (aws/invoke iam {:op :DeleteRole :request {:RoleName "aws-api-example-role"}}) 82 | 83 | ) 84 | -------------------------------------------------------------------------------- /examples/autoscaling.clj: -------------------------------------------------------------------------------- 1 | (ns autoscaling 2 | (:require [cognitect.aws.client.api :as aws])) 3 | 4 | (comment 5 | 6 | (def client (aws/client {:api :autoscaling})) 7 | (aws/invoke client {:op :DescribeAutoScalingGroups 8 | :request {}}) 9 | 10 | ) 11 | -------------------------------------------------------------------------------- /examples/ec2_examples.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns ec2-examples 5 | (:require [cognitect.aws.client.api :as aws])) 6 | 7 | (comment 8 | 9 | (def ec2 (aws/client {:api :ec2})) 10 | 11 | (aws/ops ec2) 12 | 13 | (-> (aws/ops ec2) keys sort) 14 | 15 | (aws/doc ec2 :DescribeAvailabilityZones) 16 | 17 | (aws/invoke ec2 {:op :DescribeAvailabilityZones}) 18 | 19 | ) 20 | -------------------------------------------------------------------------------- /examples/iam_examples.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns iam-examples 5 | (:require [cognitect.aws.client.api :as aws])) 6 | 7 | (comment 8 | 9 | ;; make a client 10 | (def iam (aws/client {:api :iam})) 11 | 12 | (aws/ops iam) 13 | 14 | (-> (aws/ops iam) keys sort) 15 | 16 | (aws/doc iam :ListRoles) 17 | 18 | (aws/invoke iam {:op :ListRoles}) 19 | 20 | ) 21 | -------------------------------------------------------------------------------- /examples/lambda_examples.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns lambda-examples 5 | (:require [cognitect.aws.client.api :as aws])) 6 | 7 | (comment 8 | 9 | (def lambda (aws/client {:api :lambda})) 10 | 11 | (aws/ops lambda) 12 | 13 | (-> (aws/ops lambda) keys sort) 14 | 15 | (aws/doc lambda :ListFunctions) 16 | 17 | (aws/invoke lambda {:op :ListFunctions}) 18 | 19 | ) 20 | -------------------------------------------------------------------------------- /examples/resources/dynamodb/Forum.json: -------------------------------------------------------------------------------- 1 | { 2 | "Forum": [ 3 | { 4 | "PutRequest": { 5 | "Item": { 6 | "Name": {"S":"Amazon DynamoDB"}, 7 | "Category": {"S":"Amazon Web Services"}, 8 | "Threads": {"N":"2"}, 9 | "Messages": {"N":"4"}, 10 | "Views": {"N":"1000"} 11 | } 12 | } 13 | }, 14 | { 15 | "PutRequest": { 16 | "Item": { 17 | "Name": {"S":"Amazon S3"}, 18 | "Category": {"S":"Amazon Web Services"} 19 | } 20 | } 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /examples/resources/dynamodb/Reply.json: -------------------------------------------------------------------------------- 1 | { 2 | "Reply": [ 3 | { 4 | "PutRequest": { 5 | "Item": { 6 | "Id": { 7 | "S": "Amazon DynamoDB#DynamoDB Thread 1" 8 | }, 9 | "ReplyDateTime": { 10 | "S": "2015-09-15T19:58:22.947Z" 11 | }, 12 | "Message": { 13 | "S": "DynamoDB Thread 1 Reply 1 text" 14 | }, 15 | "PostedBy": { 16 | "S": "User A" 17 | } 18 | } 19 | } 20 | }, 21 | { 22 | "PutRequest": { 23 | "Item": { 24 | "Id": { 25 | "S": "Amazon DynamoDB#DynamoDB Thread 1" 26 | }, 27 | "ReplyDateTime": { 28 | "S": "2015-09-22T19:58:22.947Z" 29 | }, 30 | "Message": { 31 | "S": "DynamoDB Thread 1 Reply 2 text" 32 | }, 33 | "PostedBy": { 34 | "S": "User B" 35 | } 36 | } 37 | } 38 | }, 39 | { 40 | "PutRequest": { 41 | "Item": { 42 | "Id": { 43 | "S": "Amazon DynamoDB#DynamoDB Thread 2" 44 | }, 45 | "ReplyDateTime": { 46 | "S": "2015-09-29T19:58:22.947Z" 47 | }, 48 | "Message": { 49 | "S": "DynamoDB Thread 2 Reply 1 text" 50 | }, 51 | "PostedBy": { 52 | "S": "User A" 53 | } 54 | } 55 | } 56 | }, 57 | { 58 | "PutRequest": { 59 | "Item": { 60 | "Id": { 61 | "S": "Amazon DynamoDB#DynamoDB Thread 2" 62 | }, 63 | "ReplyDateTime": { 64 | "S": "2015-10-05T19:58:22.947Z" 65 | }, 66 | "Message": { 67 | "S": "DynamoDB Thread 2 Reply 2 text" 68 | }, 69 | "PostedBy": { 70 | "S": "User A" 71 | } 72 | } 73 | } 74 | } 75 | ] 76 | } -------------------------------------------------------------------------------- /examples/resources/dynamodb/Thread.json: -------------------------------------------------------------------------------- 1 | { 2 | "Thread": [ 3 | { 4 | "PutRequest": { 5 | "Item": { 6 | "ForumName": { 7 | "S": "Amazon DynamoDB" 8 | }, 9 | "Subject": { 10 | "S": "DynamoDB Thread 1" 11 | }, 12 | "Message": { 13 | "S": "DynamoDB thread 1 message" 14 | }, 15 | "LastPostedBy": { 16 | "S": "User A" 17 | }, 18 | "LastPostedDateTime": { 19 | "S": "2015-09-22T19:58:22.514Z" 20 | }, 21 | "Views": { 22 | "N": "0" 23 | }, 24 | "Replies": { 25 | "N": "0" 26 | }, 27 | "Answered": { 28 | "N": "0" 29 | }, 30 | "Tags": { 31 | "L": [ 32 | { 33 | "S": "index" 34 | }, 35 | { 36 | "S": "primarykey" 37 | }, 38 | { 39 | "S": "table" 40 | } 41 | ] 42 | } 43 | } 44 | } 45 | }, 46 | { 47 | "PutRequest": { 48 | "Item": { 49 | "ForumName": { 50 | "S": "Amazon DynamoDB" 51 | }, 52 | "Subject": { 53 | "S": "DynamoDB Thread 2" 54 | }, 55 | "Message": { 56 | "S": "DynamoDB thread 2 message" 57 | }, 58 | "LastPostedBy": { 59 | "S": "User A" 60 | }, 61 | "LastPostedDateTime": { 62 | "S": "2015-09-15T19:58:22.514Z" 63 | }, 64 | "Views": { 65 | "N": "0" 66 | }, 67 | "Replies": { 68 | "N": "0" 69 | }, 70 | "Answered": { 71 | "N": "0" 72 | }, 73 | "Tags": { 74 | "L": [ 75 | { 76 | "S": "items" 77 | }, 78 | { 79 | "S": "attributes" 80 | }, 81 | { 82 | "S": "throughput" 83 | } 84 | ] 85 | } 86 | } 87 | } 88 | }, 89 | { 90 | "PutRequest": { 91 | "Item": { 92 | "ForumName": { 93 | "S": "Amazon S3" 94 | }, 95 | "Subject": { 96 | "S": "S3 Thread 1" 97 | }, 98 | "Message": { 99 | "S": "S3 thread 1 message" 100 | }, 101 | "LastPostedBy": { 102 | "S": "User A" 103 | }, 104 | "LastPostedDateTime": { 105 | "S": "2015-09-29T19:58:22.514Z" 106 | }, 107 | "Views": { 108 | "N": "0" 109 | }, 110 | "Replies": { 111 | "N": "0" 112 | }, 113 | "Answered": { 114 | "N": "0" 115 | }, 116 | "Tags": { 117 | "L": [ 118 | { 119 | "S": "largeobjects" 120 | }, 121 | { 122 | "S": "multipart upload" 123 | } 124 | ] 125 | } 126 | } 127 | } 128 | } 129 | ] 130 | } -------------------------------------------------------------------------------- /examples/s3_examples.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns s3-examples 5 | (:require [clojure.core.async :as a] 6 | [clojure.spec.alpha :as s] 7 | [clojure.spec.gen.alpha :as gen] 8 | [clojure.java.io :as io] 9 | [clojure.repl :as repl] 10 | [cognitect.aws.client.api :as aws])) 11 | 12 | (comment 13 | 14 | ;; make a client 15 | (def s3 (aws/client {:api :s3})) 16 | 17 | ;; guard against invalid :request map 18 | (aws/validate-requests s3 true) 19 | 20 | ;; what can it do? 21 | (aws/ops s3) 22 | ;; op names 23 | (-> (aws/ops s3) keys sort) 24 | 25 | ;; op doc-data 26 | (-> (aws/ops s3) :CreateBucket) 27 | ;; a little more friendly 28 | (aws/doc s3 :CreateBucket) 29 | 30 | ;; specs 31 | (aws/request-spec-key s3 :CreateBucket) 32 | (s/describe (aws/request-spec-key s3 :CreateBucket)) 33 | (gen/sample (s/gen (aws/request-spec-key s3 :CreateBucket))) 34 | 35 | (aws/response-spec-key s3 :CreateBucket) 36 | (s/describe (aws/response-spec-key s3 :CreateBucket)) 37 | (gen/sample (s/gen (aws/response-spec-key s3 :CreateBucket))) 38 | 39 | ;; * use this bucket-name to avoid collisions with other devs 40 | ;; * don't forget to delete the bucket when done exploring! 41 | (def bucket-name (str "cognitect-aws-test-" (.getEpochSecond (java.time.Instant/now)))) 42 | 43 | ;; see how submit works 44 | (repl/doc aws/invoke) 45 | 46 | ;; doit 47 | (aws/invoke s3 {:op :ListBuckets}) 48 | 49 | ;; http-request and http-response are in metadata 50 | (meta *1) 51 | 52 | (aws/invoke s3 {:op :CreateBucket :request {:Bucket bucket-name}}) 53 | 54 | ;; now you should see the bucket you just added 55 | (aws/invoke s3 {:op :ListBuckets}) 56 | 57 | ;; no objects yet ... 58 | (aws/invoke s3 {:op :ListObjectsV2 :request {:Bucket bucket-name}}) 59 | 60 | ;; Body is blob type, for which we accept a byte-array or an InputStream 61 | (aws/invoke s3 {:op :PutObject :request {:Bucket bucket-name :Key "hello.txt" 62 | :Body (.getBytes "Oh hai!")}}) 63 | 64 | (aws/invoke s3 {:op :PutObject :request {:Bucket bucket-name :Key "hello.txt" 65 | :Body (io/input-stream (.getBytes "Oh hai!"))}}) 66 | 67 | ;; now you should see the object you just added 68 | (aws/invoke s3 {:op :ListObjectsV2 :request {:Bucket bucket-name}}) 69 | 70 | ;; Body is a blob type, which always returns an InputStream 71 | (aws/invoke s3 {:op :GetObject :request {:Bucket bucket-name :Key "hello.txt"}}) 72 | 73 | ;; check it! 74 | (slurp (:Body *1)) 75 | 76 | (aws/invoke s3 {:op :DeleteObject :request {:Bucket bucket-name :Key "hello.txt"}}) 77 | 78 | (aws/invoke s3 {:op :DeleteObjects, :request {:Delete {:Objects [{:Key "hello.txt"}]}, :Bucket bucket-name}}) 79 | 80 | ;; poof, the object is gone! 81 | (aws/invoke s3 {:op :ListObjectsV2 :request {:Bucket bucket-name}}) 82 | 83 | (aws/invoke s3 {:op :DeleteBucket :request {:Bucket bucket-name}}) 84 | 85 | ;; poof, the bucket is gone! 86 | (aws/invoke s3 {:op :ListBuckets}) 87 | 88 | ;;;;;;;;;;;;;;;;;;;;;;; 89 | 90 | ;; see how submit works w/ async 91 | (clojure.repl/doc aws/invoke-async) 92 | 93 | ;; async! 94 | (def c (aws/invoke-async s3 {:op :ListBuckets})) 95 | 96 | (a/ (aws/ops ssm-client) keys sort) 20 | 21 | ;; print docs 22 | (aws/doc ssm-client :PutParameter) 23 | 24 | ;; or describe args as data 25 | (pp/pprint (s/describe (aws/request-spec-key ssm-client :PutParameter))) 26 | 27 | ;; describe an op param 28 | (s/form :cognitect.aws.ssm.PutParameterRequest/Type) 29 | 30 | ;; jam! 31 | (aws/invoke ssm-client {:op :PutParameter 32 | :request {:Name "aws-api-example" 33 | :Value "example-value" 34 | :Type "SecureString"}}) 35 | 36 | ;; see spec fail 37 | (aws/invoke ssm-client {:op :PutParameter 38 | :request {:Value "example-value" 39 | :Type "SecureString"}}) 40 | 41 | ) 42 | -------------------------------------------------------------------------------- /src/cognitect/aws/client/api/async.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns ^:skip-wiki cognitect.aws.client.api.async 5 | "DEPRECATED" 6 | (:require 7 | [cognitect.aws.client.protocol :as client.protocol])) 8 | 9 | (defn ^:deprecated invoke 10 | "DEPRECATED: use cognitect.aws.client.api/invoke-async instead" 11 | [client op-map] 12 | (client.protocol/-invoke-async client op-map)) -------------------------------------------------------------------------------- /src/cognitect/aws/client/protocol.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns ^:skip-wiki cognitect.aws.client.protocol 5 | "Impl, don't call directly.") 6 | 7 | (defprotocol Client 8 | (-get-info [_] "Used by fns in cognitect.aws.client.api. Implementors must supply 9 | :service, and may also supply anything else needed by the other 10 | protocol functions. 11 | 12 | The cognitect.aws.client.api/client uses the following: 13 | :retriable? 14 | :backoff 15 | :http-client 16 | :endpoint-provider 17 | :region-provider 18 | :credentials-provider 19 | :validate-requests?") 20 | (-invoke [this op-map] "Packages and ships a request and returns a response") 21 | (-invoke-async [this op-map] "Packages and ships a request and returns a channel that will contain a response") 22 | (-stop [this] "Release resources managed by this client")) -------------------------------------------------------------------------------- /src/cognitect/aws/client/shared.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns cognitect.aws.client.shared 5 | "Default, globally shared resources which are by default shared among all AWS clients and whose 6 | lifecycles and resources are automatically managed." 7 | (:require [cognitect.aws.http :as http] 8 | [cognitect.aws.credentials :as credentials] 9 | [cognitect.aws.region :as region])) 10 | 11 | (set! *warn-on-reflection* true) 12 | 13 | (declare http-client) 14 | 15 | (def ^:private shared-http-client 16 | (delay (http/resolve-http-client nil))) 17 | 18 | (def ^:private shared-credentials-provider 19 | (delay (credentials/default-credentials-provider (http-client)))) 20 | 21 | (def ^:private shared-region-provider 22 | (delay (region/default-region-provider (http-client)))) 23 | 24 | (defn http-client 25 | "Returns the globally shared instance of http-client (created on the 26 | first call). 27 | 28 | Alpha. Subject to change." 29 | [] 30 | @shared-http-client) 31 | 32 | (defn credentials-provider 33 | "Returns the globally shared instance of credentials-provider, which 34 | uses the globally shared instance of http-client. 35 | 36 | Alpha. Subject to change." 37 | [] 38 | @shared-credentials-provider) 39 | 40 | (defn region-provider 41 | "Returns the globally shared instance of region-provider, which 42 | uses the globally shared instance of http-client. 43 | 44 | Alpha. Subject to change." 45 | [] 46 | @shared-region-provider) 47 | 48 | #_:clj-kondo/ignore 49 | (defn ^:private shared-http-client? 50 | "For internal use. 51 | 52 | Alpha. Subject to change." 53 | [candidate-http-client] 54 | (identical? candidate-http-client 55 | (and (realized? shared-http-client) @shared-http-client))) 56 | -------------------------------------------------------------------------------- /src/cognitect/aws/client/test_double.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns cognitect.aws.client.test-double 5 | "Provides a test implementation of the aws client, which can be passed 6 | to the functions in the cognitect.aws.client.api ns." 7 | (:require [clojure.core.async :as a] 8 | [cognitect.aws.client.protocol :as client.protocol] 9 | [cognitect.aws.client.validation :as validation] 10 | [cognitect.aws.service :as service]) 11 | (:import (clojure.lang ILookup))) 12 | 13 | (set! *warn-on-reflection* true) 14 | 15 | (defn ^:private no-handler-provided-anomaly [op] 16 | {:cognitect.anomalies/category :cognitect.anomalies/incorrect 17 | :cognitect.anomalies/message "No handler or response provided for op" 18 | :op op}) 19 | 20 | (defprotocol TestDoubleClient 21 | (-instrument [c ops])) 22 | 23 | (deftype Client [info handlers] 24 | ILookup 25 | (valAt [this k] 26 | (.valAt this k nil)) 27 | 28 | (valAt [_this k default] 29 | (case k 30 | :api 31 | (-> info :service :metadata :cognitect.aws/service-name) 32 | :service 33 | (:service info) 34 | default)) 35 | 36 | client.protocol/Client 37 | (-get-info [_] info) 38 | 39 | (-invoke [this {:keys [op request] :as op-map}] 40 | (let [spec (validation/request-spec (:service info) op) 41 | handler (get @handlers op)] 42 | (cond 43 | (not (get-in info [:service :operations op])) 44 | (validation/unsupported-op-anomaly (:service info) op) 45 | 46 | (and (validation/validate-requests? this) 47 | spec 48 | (not (validation/valid? spec request))) 49 | (validation/invalid-request-anomaly spec request) 50 | 51 | (not handler) 52 | (no-handler-provided-anomaly op) 53 | 54 | :else 55 | (handler op-map)))) 56 | 57 | (-invoke-async [this {:keys [ch] :as op-map}] 58 | (let [response-chan (or ch (a/promise-chan))] 59 | (a/go 60 | (let [resp (.-invoke this op-map)] 61 | (a/>! response-chan resp))) 62 | response-chan)) 63 | 64 | (-stop [_aws-client]) 65 | 66 | TestDoubleClient 67 | (-instrument [client ops] 68 | (swap! (.handlers client) 69 | (fn [handlers] 70 | (reduce-kv 71 | (fn [m op handler] 72 | (when-not (some-> client :service :operations op) 73 | (throw (ex-info "Operation not supported" 74 | (validation/unsupported-op-anomaly (-> client :service) op)))) 75 | (assoc m op (if (fn? handler) handler (constantly handler)))) 76 | handlers 77 | ops))))) 78 | 79 | ;; ->Client is intended for internal use 80 | (alter-meta! #'->Client assoc :skip-wiki true) 81 | (alter-meta! #'TestDoubleClient assoc :skip-wiki true) 82 | 83 | (defn instrument 84 | "Given a test double client and a `:ops` map of operations to handlers, 85 | instruments the client with handlers. See `client` for more info about 86 | `:ops`." 87 | [client ops] 88 | (-instrument client ops)) 89 | 90 | (defn client 91 | "Given a map with :api and :ops (optional), returns a test double client that 92 | you can pass to `cognitect.aws.client.api/invoke` and `cognitect.aws.client.api/stop` 93 | in implementation code. 94 | 95 | You can provide :ops on creation or use `instrument` to add them later. 96 | 97 | :ops should be a map of operation (keyword) to one of 98 | - a function of op-map that returns a response map 99 | - a literal response map 100 | 101 | Notes: 102 | - you must instrument every op that will be invoked during a test 103 | - every op must be supported 104 | - See (keys (cognitect.aws.client.api/ops )) 105 | - will validate request payloads passed to `invoke` by default 106 | - you can disable request validation with (cognitect.aws.client.api/validate-requests client false) 107 | - will not validate response payloads" 108 | [{:keys [api ops]}] 109 | (let [service (service/service-description (name api))] 110 | (doto (->Client {:service service :validate-requests? (atom true)} (atom {})) 111 | (instrument ops)))) 112 | -------------------------------------------------------------------------------- /src/cognitect/aws/client/validation.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns ^:skip-wiki cognitect.aws.client.validation 5 | "For internal use. Don't call directly." 6 | (:require [cognitect.aws.client.protocol :as client.protocol] 7 | [cognitect.aws.dynaload :as dynaload] 8 | [cognitect.aws.service :as service])) 9 | 10 | (set! *warn-on-reflection* true) 11 | 12 | (defn validate-requests? 13 | "For internal use. Don't call directly." 14 | [client] 15 | (some-> client client.protocol/-get-info :validate-requests? deref)) 16 | 17 | (def ^:private registry-ref (delay (dynaload/load-var 'clojure.spec.alpha/registry))) 18 | (defn registry 19 | "For internal use. Don't call directly." 20 | [& args] (apply @registry-ref args)) 21 | 22 | (def ^:private valid?-ref (delay (dynaload/load-var 'clojure.spec.alpha/valid?))) 23 | (defn valid? 24 | "For internal use. Don't call directly." 25 | [& args] (apply @valid?-ref args)) 26 | 27 | (def ^:private explain-data-ref (delay (dynaload/load-var 'clojure.spec.alpha/explain-data))) 28 | (defn explain-data 29 | "For internal use. Don't call directly." 30 | [& args] (apply @explain-data-ref args)) 31 | 32 | (defn request-spec 33 | "For internal use. Don't call directly." 34 | [service op] 35 | (when-let [spec (service/request-spec-key service op)] 36 | (when (contains? (-> (registry) keys set) spec) 37 | spec))) 38 | 39 | (defn invalid-request-anomaly 40 | "For internal use. Don't call directly." 41 | [spec request] 42 | (assoc (explain-data spec request) 43 | :cognitect.anomalies/category :cognitect.anomalies/incorrect)) 44 | 45 | (defn unsupported-op-anomaly 46 | "For internal use. Don't call directly." 47 | [service op] 48 | {:cognitect.anomalies/category :cognitect.anomalies/unsupported 49 | :cognitect.anomalies/message "Operation not supported" 50 | :service (keyword (service/service-name service)) 51 | :op op}) -------------------------------------------------------------------------------- /src/cognitect/aws/config.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns ^:skip-wiki cognitect.aws.config 5 | (:require [clojure.string :as str])) 6 | 7 | (set! *warn-on-reflection* true) 8 | 9 | ;;; predicates 10 | 11 | (defn comment? [s] 12 | (str/starts-with? s "#")) 13 | 14 | (defn start-profile? [s] 15 | (str/starts-with? s "[")) 16 | 17 | (defn start-nested? [s] 18 | (re-find #"^[\w-_\.]+\s*=$" s)) 19 | 20 | (defn add-profile-kv? [s] 21 | (re-find #"^[\w-_\.]+\s*=.*\w+" s)) 22 | 23 | (defn add-nested-kv? [s] 24 | (re-find #"^\s+[\w-_\.]+\s*=.*\w+" s)) 25 | 26 | ;;; helpers 27 | 28 | (defn split-lines [s] 29 | (into [] 30 | (comp (map str/trimr) 31 | (remove str/blank?) 32 | (remove comment?)) 33 | (str/split-lines s))) 34 | 35 | (defn split-kv [s] 36 | (->> (str/split s #"=" 2) 37 | (map str/trim))) 38 | 39 | ;;; actions 40 | 41 | (defn set-profile-path [m line] 42 | (assoc m :path [:profiles (second (re-find #"\[(?:profile)?\s*(.+)\]" line))])) 43 | 44 | (defn ensure-profile-path [m] 45 | (update m :path (comp vec (partial take 2)))) 46 | 47 | (defn set-nested-path [m line] 48 | (update m :path #(conj (vec (take 2 %)) 49 | (-> line (str/replace #"=" "") (str/trim))))) 50 | 51 | (defn add-profile-kv [m line] 52 | (let [[k v] (split-kv line)] 53 | (update-in m (take 2 (:path m)) assoc k v))) 54 | 55 | (defn add-nested-kv [m line] 56 | (let [[k v] (split-kv line)] 57 | (update-in m (:path m) assoc k v))) 58 | 59 | ;;; main 60 | 61 | (defn parse 62 | "Return the profiles in the configuration file." 63 | [file] 64 | (->> file 65 | slurp 66 | split-lines 67 | (reduce (fn [m ^String line] 68 | (cond (start-profile? line) 69 | (set-profile-path m line) 70 | 71 | (start-nested? line) 72 | (set-nested-path m line) 73 | 74 | (add-profile-kv? line) 75 | (-> m 76 | (add-profile-kv line) 77 | (ensure-profile-path)) 78 | 79 | (add-nested-kv? line) 80 | (add-nested-kv m line) 81 | 82 | :else 83 | (throw (ex-info "Invalid format in config" {:file file})))) 84 | {:profiles {}}) 85 | :profiles)) 86 | -------------------------------------------------------------------------------- /src/cognitect/aws/dynaload.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns ^:skip-wiki cognitect.aws.dynaload) 5 | 6 | (set! *warn-on-reflection* true) 7 | 8 | (defonce ^:private dynalock (Object.)) 9 | 10 | (defn load-ns [ns] 11 | (locking dynalock 12 | (require (symbol ns)))) 13 | 14 | (defn load-var 15 | [s] 16 | (let [ns (namespace s)] 17 | (assert ns) 18 | (load-ns ns) 19 | (or (resolve s) 20 | (throw (RuntimeException. (str "Var " s " is not on the classpath")))))) 21 | -------------------------------------------------------------------------------- /src/cognitect/aws/endpoint.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns ^:skip-wiki cognitect.aws.endpoint 5 | "Impl, don't call directly." 6 | (:refer-clojure :exclude [resolve]) 7 | (:require [clojure.edn :as edn] 8 | [clojure.string :as str] 9 | [cognitect.aws.resources :as resources] 10 | [cognitect.aws.service :as service])) 11 | 12 | (set! *warn-on-reflection* true) 13 | 14 | (defn descriptor-resource-path [] (format "%s/endpoints.edn" service/base-resource-path)) 15 | 16 | (defn read-endpoints-description [] 17 | (if-let [resource (resources/resource (descriptor-resource-path))] 18 | (edn/read-string (slurp resource)) 19 | (throw (ex-info (str "Cannot find resource " (descriptor-resource-path) ".") {})))) 20 | 21 | (defn resolver 22 | "Create a new endpoint resolver." 23 | [] 24 | (read-endpoints-description)) 25 | 26 | (defn render-uri 27 | "Given a template, e.g. \"{a}.{b}.{c}\", and a map of replacements 28 | with keys matching those in the template, replaces {a} with the 29 | value bound to :a in replacements, then {b}, then {c}." 30 | [replacements template] 31 | (str/replace template 32 | #"\{([^}]+)\}" 33 | #(get replacements (second %)))) 34 | 35 | (defn service-resolve 36 | "Resolve the endpoint for the given service." 37 | [partition service-name service region-key] 38 | (let [endpoint (get-in service [:endpoints region-key]) 39 | region (name region-key) 40 | result (merge (:defaults partition) 41 | (:defaults service) 42 | endpoint 43 | {:partition (:partition partition) 44 | :region region 45 | :dnsSuffix (:dnsSuffix partition)}) 46 | uri-parts {"service" service-name 47 | "region" region 48 | "dnsSuffix" (:dnsSuffix partition)}] 49 | (cond-> result 50 | (:hostname result) 51 | (update :hostname (partial render-uri uri-parts)) 52 | 53 | (:sslCommonName result) 54 | (update :sslCommonName (partial render-uri uri-parts))))) 55 | 56 | (defn partition-resolve 57 | [{:keys [services] :as partition} service-key region-key] 58 | (when (contains? (-> partition :regions keys set) region-key) 59 | (let [{:keys [partitionEndpoint isRegionalized] :as service} (get services service-key) 60 | endpoint-key (if (and partitionEndpoint (not isRegionalized)) 61 | (keyword partitionEndpoint) 62 | region-key)] 63 | (service-resolve partition (name service-key) service endpoint-key)))) 64 | 65 | (defn resolve* 66 | "Resolves an endpoint for a given service and region. 67 | 68 | service keyword Identify a AWS service (e.g. :s3) 69 | region keyword Identify a AWS region (e.g. :us-east-1). 70 | 71 | Return a map with the following keys: 72 | 73 | :partition The name of the partition. 74 | :region The region of the endpoint. 75 | :hostname The hostname to use. 76 | :sslCommonName The sslCommonName to use (optional). 77 | :credentialScope The Signature v4 credential scope (optional). 78 | :signatureVersions A list of possible signature versions (optional). 79 | :protocols A list of supported protocols." 80 | [service-key region] 81 | (some #(partition-resolve % service-key region) 82 | (:partitions (resolver)))) 83 | 84 | (def resolve (memoize resolve*)) 85 | 86 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 87 | 88 | (defprotocol EndpointProvider 89 | (-fetch [provider region])) 90 | 91 | (defn default-endpoint-provider [endpointPrefix endpoint-override] 92 | (reify EndpointProvider 93 | (-fetch [_ region] 94 | (if-let [ep (resolve (keyword endpointPrefix) (keyword region))] 95 | (merge ep (if (string? endpoint-override) 96 | {:hostname endpoint-override} 97 | endpoint-override)) 98 | {:cognitect.anomalies/category :cognitect.anomalies/fault 99 | :cognitect.anomalies/message "No known endpoint."})))) 100 | 101 | (defn fetch [provider region] 102 | (-fetch provider region)) 103 | -------------------------------------------------------------------------------- /src/cognitect/aws/http.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns ^:skip-wiki cognitect.aws.http 5 | "Impl, don't call directly." 6 | (:require [clojure.edn :as edn] 7 | [clojure.core.async :as a] 8 | [clojure.string :as str] 9 | [cognitect.aws.dynaload :as dynaload])) 10 | 11 | (set! *warn-on-reflection* true) 12 | 13 | (defprotocol HttpClient 14 | (-submit [_ request channel] 15 | "Submit an http request, channel will be filled with response. Returns ch. 16 | 17 | Request map: 18 | 19 | :scheme :http or :https 20 | :server-name string 21 | :server-port integer 22 | :uri string 23 | :query-string string, optional 24 | :request-method :get/:post/:put/:head/:delete 25 | :headers map from downcased string to string 26 | :body ByteBuffer, optional 27 | :timeout-msec opt, total request send/receive timeout 28 | :meta opt, data to be added to the response map 29 | 30 | content-type must be specified in the headers map 31 | content-length is derived from the ByteBuffer passed to body 32 | 33 | Response map: 34 | 35 | :status integer HTTP status code 36 | :body ByteBuffer, optional 37 | :headers map from downcased string to string 38 | :meta opt, data from the request 39 | 40 | On error, response map is per cognitect.anomalies. 41 | 42 | Alpha. This will absolutely change.") 43 | (-stop [_] "Stops the client, releasing resources")) 44 | 45 | (defn submit 46 | ([client request] 47 | (-submit client request (a/chan 1))) 48 | ([client request channel] 49 | (-submit client request channel))) 50 | 51 | (defn stop 52 | "Stops the client, releasing resources. 53 | 54 | Alpha. Subject to change." 55 | [client] 56 | (-stop client)) 57 | 58 | (defn client? 59 | [c] 60 | (satisfies? HttpClient c)) 61 | 62 | (defn read-config 63 | [url] 64 | (-> url slurp edn/read-string)) 65 | 66 | ;; TODO consider providing config arguments to http constructor 67 | (defn- configured-client 68 | "If a single `cognitect_aws_http.edn` is found on the classpath, 69 | returns the symbol bound to `:constructor-var`. 70 | 71 | If none are found, use this library's default. 72 | 73 | Throws if more than one `cognitect_aws_http.edn` files are found." 74 | [] 75 | (let [cl (.. Thread currentThread getContextClassLoader) 76 | cfgs (enumeration-seq (.getResources cl "cognitect_aws_http.edn"))] 77 | (case (count cfgs) 78 | 0 'cognitect.aws.http.default/create 79 | 1 (-> cfgs first read-config :constructor-var) 80 | 81 | (throw (ex-info "Found more than one cognitect_aws_http.edn file in the classpath. There must be at most one." {:config cfgs}))))) 82 | 83 | (defn resolve-http-client 84 | [http-client-or-sym] 85 | (let [c (or (when (symbol? http-client-or-sym) 86 | (let [ctor @(dynaload/load-var http-client-or-sym)] 87 | (ctor))) 88 | http-client-or-sym 89 | (let [ctor @(dynaload/load-var (configured-client))] 90 | (ctor)))] 91 | (when-not (client? c) 92 | (throw (ex-info "not an http client" {:provided http-client-or-sym 93 | :resolved c}))) 94 | c)) 95 | 96 | (defn uri-authority 97 | "Returns the normalized URI authority (RFC 3986 section 3.2) for the given URI components, 98 | good for building the full request URI, signing the request, and computing the Host header, 99 | according to RFC 9112 section 3.2: 100 | 101 | A client MUST send a Host header field in all HTTP/1.1 request messages. If the target URI 102 | includes an authority component, then a client MUST send a field value for Host that is identical 103 | to that authority component, excluding any userinfo subcomponent and its \"@\" delimiter. 104 | 105 | `uri-scheme` and `uri-host` are required. `uri-port` may be nil in case the default port 106 | for the scheme is used. 107 | 108 | Normalization follows RFC 9110 section 4.2.3 (default port for the scheme is omitted; 109 | scheme and host are normalized to lowercase). The userinfo component of the URI is 110 | always omitted as per RFC 9110 section 4.2.4. 111 | 112 | authority = host [ \":\" port ]" 113 | [uri-scheme uri-host uri-port] 114 | (let [scheme (str/lower-case (name uri-scheme)) 115 | host (str/lower-case uri-host) 116 | is-default-port (case scheme 117 | "http" (= uri-port 80) 118 | "https" (= uri-port 443) 119 | false) 120 | should-include-port (and (some? uri-port) 121 | (not is-default-port))] 122 | (str host (when should-include-port (str ":" uri-port))))) 123 | -------------------------------------------------------------------------------- /src/cognitect/aws/http/cognitect.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns ^:skip-wiki cognitect.aws.http.cognitect 5 | (:require [cognitect.http-client :as impl] 6 | [cognitect.aws.http :as aws])) 7 | 8 | (set! *warn-on-reflection* true) 9 | 10 | (defn create 11 | [] 12 | (let [c (impl/create {:follow-redirects false})] 13 | (reify aws/HttpClient 14 | (-submit [_ request channel] 15 | (impl/submit c request channel)) 16 | (-stop [_] 17 | (impl/stop c))))) 18 | -------------------------------------------------------------------------------- /src/cognitect/aws/http/default.clj: -------------------------------------------------------------------------------- 1 | (ns cognitect.aws.http.default 2 | (:require [cognitect.aws.dynaload :as dynaload])) 3 | 4 | (def ^:private native-client-available 5 | (delay (try (Class/forName "java.net.http.HttpClient") true 6 | (catch Exception _ false)))) 7 | 8 | (def ^:private cognitect-client-available 9 | (delay (try (require 'cognitect.http-client) true 10 | (catch Exception _ false)))) 11 | 12 | (defn ^:private load-and-create 13 | [sym] 14 | (let [f @(dynaload/load-var sym)] 15 | (f))) 16 | 17 | (defn create 18 | "Returns a new cognitect.aws.http/HttpClient. 19 | 20 | - If running JVM is JDK 11+, returns a client based on java.net.http.HttpClient. 21 | - If cognitect.http-client ns is available, returns a client based on it. 22 | 23 | If none of these requirements are met, throws." 24 | [] 25 | (cond 26 | @native-client-available 27 | (load-and-create 'cognitect.aws.http.java/create) 28 | 29 | @cognitect-client-available 30 | (load-and-create 'cognitect.aws.http.cognitect/create) 31 | 32 | :else 33 | (throw (ex-info "aws-api requires JDK 11+, or you must have an explicit dependency on com.cognitect/http-client in your project" 34 | {:details "See https://github.com/cognitect-labs/aws-api/blob/main/UPGRADE.md if you are upgrading from a previous aws-api version"})))) 35 | -------------------------------------------------------------------------------- /src/cognitect/aws/interceptors.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns ^:skip-wiki cognitect.aws.interceptors 5 | "Impl, don't call directly." 6 | (:require [cognitect.aws.service :as service] 7 | [cognitect.aws.util :as util])) 8 | 9 | (set! *warn-on-reflection* true) 10 | 11 | (defmulti modify-http-request (fn [service _op-map _http-request] 12 | (service/service-name service))) 13 | 14 | (defmethod modify-http-request :default [_service _op-map http-request] http-request) 15 | 16 | (def md5-blacklist 17 | "Set of ops that should not get the Content-MD5 header. 18 | 19 | See https://github.com/aws/aws-sdk-java-v2/blob/master/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/handlers/AddContentMd5HeaderInterceptor.java " 20 | #{:PutObject :UploadPart}) 21 | 22 | (defmethod modify-http-request "s3" [service op-map http-request] 23 | (if (and (= "md5" (get-in service [:metadata :checksumFormat])) 24 | (not (md5-blacklist (:op op-map))) 25 | (:body http-request)) 26 | (update http-request :headers assoc "Content-MD5" (-> http-request :body util/md5 util/base64-encode)) 27 | http-request)) 28 | 29 | (defmethod modify-http-request "apigatewaymanagementapi" [_service op-map http-request] 30 | (if (= :PostToConnection (:op op-map)) 31 | (update http-request :uri str (-> op-map :request :ConnectionId)) 32 | http-request)) 33 | 34 | ;; See https://github.com/aws/aws-sdk-java-v2/blob/985ec92c0dfac868b33791fe4623296c68e2feab/services/glacier/src/main/java/software/amazon/awssdk/services/glacier/internal/GlacierExecutionInterceptor.java#L40 35 | (defmethod modify-http-request "glacier" [service _op-map http-request] 36 | (assoc-in http-request 37 | [:headers "x-amz-glacier-version"] 38 | (get-in service [:metadata :apiVersion]))) -------------------------------------------------------------------------------- /src/cognitect/aws/protocols/ec2.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns ^:skip-wiki cognitect.aws.protocols.ec2 5 | "Impl, don't call directly." 6 | (:require [cognitect.aws.protocols :as aws.protocols] 7 | [cognitect.aws.protocols.query :as query] 8 | [cognitect.aws.shape :as shape] 9 | [cognitect.aws.util :as util])) 10 | 11 | (set! *warn-on-reflection* true) 12 | 13 | (defn serialized-name 14 | [shape default] 15 | (or (:queryName shape) 16 | (when-let [name (:locationName shape)] 17 | (apply str (Character/toUpperCase ^Character (first name)) (rest name))) 18 | default)) 19 | 20 | (defmulti serialize 21 | (fn [_shapes shape _args _serialized _prefix] (:type shape))) 22 | 23 | (defmethod serialize :default 24 | [shapes shape args serialized prefix] 25 | (query/serialize shapes shape args serialized prefix)) 26 | 27 | (defmethod serialize "structure" 28 | [shapes shape args serialized prefix] 29 | (let [args (util/with-defaults shape args)] 30 | (reduce (fn [serialized k] 31 | (let [member-shape (shape/resolve shapes (shape/structure-member-shape-ref shape k)) 32 | member-name (serialized-name member-shape (name k))] 33 | (if (contains? args k) 34 | (serialize shapes member-shape (k args) serialized (conj prefix member-name)) 35 | serialized))) 36 | serialized 37 | (keys (:members shape))))) 38 | 39 | (defmethod serialize "list" 40 | [shapes shape args serialized prefix] 41 | (let [member-shape (shape/resolve shapes (shape/list-member-shape-ref shape))] 42 | (reduce (fn [serialized [i member]] 43 | (serialize shapes member-shape member serialized (conj prefix (str i)))) 44 | serialized 45 | (map-indexed (fn [i member] [(inc i) member]) args)))) 46 | 47 | (defmethod aws.protocols/build-http-request "ec2" 48 | [service op-map] 49 | (query/build-query-http-request op-map service serialize)) 50 | 51 | (defmethod aws.protocols/parse-http-response "ec2" 52 | [service op-map http-response] 53 | (query/build-query-http-response service op-map http-response)) 54 | -------------------------------------------------------------------------------- /src/cognitect/aws/protocols/json.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns ^:skip-wiki cognitect.aws.protocols.json 5 | "Impl, don't call directly." 6 | (:require [cognitect.aws.protocols :as aws.protocols] 7 | [cognitect.aws.shape :as shape] 8 | [cognitect.aws.util :as util])) 9 | 10 | (set! *warn-on-reflection* true) 11 | 12 | (defmulti serialize 13 | (fn [_shapes shape _data] (:type shape))) 14 | 15 | (defmethod serialize :default 16 | [shapes shape data] 17 | (shape/json-serialize shapes shape data)) 18 | 19 | (defmethod serialize "structure" 20 | [shapes shape data] 21 | (->> (util/with-defaults shape data) 22 | (shape/json-serialize shapes shape))) 23 | 24 | (defmethod aws.protocols/build-http-request "json" 25 | [service {:keys [op request]}] 26 | (let [operation (get-in service [:operations op]) 27 | shapes (:shapes service) 28 | input-shape (shape/resolve shapes (:input operation))] 29 | {:request-method :post 30 | :scheme :https 31 | :server-port 443 32 | :uri "/" 33 | :headers (aws.protocols/headers service operation) 34 | :body (serialize shapes input-shape (or request {}))})) 35 | 36 | (defmethod aws.protocols/parse-http-response "json" 37 | [service {:keys [op]} {:keys [body]}] 38 | (let [operation (get-in service [:operations op]) 39 | shapes (:shapes service) 40 | output-shape (shape/resolve shapes (:output operation)) 41 | body-str (util/bbuf->str body)] 42 | (if output-shape 43 | (shape/json-parse shapes output-shape body-str) 44 | {}))) 45 | -------------------------------------------------------------------------------- /src/cognitect/aws/protocols/query.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns ^:skip-wiki cognitect.aws.protocols.query 5 | "Impl, don't call directly." 6 | (:require [clojure.string :as str] 7 | [cognitect.aws.protocols :as aws.protocols] 8 | [cognitect.aws.shape :as shape] 9 | [cognitect.aws.util :as util])) 10 | 11 | (set! *warn-on-reflection* true) 12 | 13 | ; ---------------------------------------------------------------------------------------- 14 | ;; Serializer 15 | ;; ---------------------------------------------------------------------------------------- 16 | 17 | (defn serialized-name 18 | [shape default] 19 | (or (:locationName shape) 20 | default)) 21 | 22 | (defn prefix-assoc 23 | [serialized prefix val] 24 | (assoc serialized (str/join "." prefix) val)) 25 | 26 | (defmulti serialize 27 | (fn [_shapes shape _args _serialized _prefix] (:type shape))) 28 | 29 | (defmethod serialize :default 30 | [_shapes _shape args serialized prefix] 31 | (prefix-assoc serialized prefix (str args))) 32 | 33 | (defmethod serialize "structure" 34 | [shapes shape args serialized prefix] 35 | (let [args (util/with-defaults shape args)] 36 | (reduce (fn [serialized k] 37 | (let [member-shape (shape/resolve shapes (shape/structure-member-shape-ref shape k)) 38 | member-name (serialized-name member-shape (name k))] 39 | (if (contains? args k) 40 | (serialize shapes member-shape (k args) serialized (conj prefix member-name)) 41 | serialized))) 42 | serialized 43 | (keys (:members shape))))) 44 | 45 | (defmethod serialize "list" 46 | [shapes shape args serialized prefix] 47 | (if (empty? args) 48 | (prefix-assoc serialized prefix "") 49 | (let [member-shape (shape/resolve shapes (shape/list-member-shape-ref shape)) 50 | list-prefix (if (:flattened shape) 51 | (conj (vec (butlast prefix)) (serialized-name member-shape (last prefix))) 52 | (conj prefix (serialized-name member-shape "member")))] 53 | (reduce (fn [serialized [i member]] 54 | (serialize shapes member-shape member serialized (conj list-prefix (str i)))) 55 | serialized 56 | (map-indexed (fn [i member] [(inc i) member]) args))))) 57 | 58 | (defmethod serialize "map" 59 | [shapes shape args serialized prefix] 60 | (let [map-prefix (if (:flattened shape) prefix (conj prefix "entry")) 61 | key-shape (shape/resolve shapes (shape/map-key-shape-ref shape)) 62 | key-suffix (serialized-name key-shape "key") 63 | value-shape (shape/resolve shapes (shape/map-value-shape-ref shape)) 64 | value-suffix (serialized-name value-shape "value")] 65 | (reduce (fn [serialized [i k v]] 66 | (as-> serialized $ 67 | (serialize shapes key-shape (name k) $ (conj map-prefix (str i) key-suffix)) 68 | (serialize shapes value-shape v $ (conj map-prefix (str i) value-suffix)))) 69 | serialized 70 | (map-indexed (fn [i [k v]] [(inc i) k v]) args)))) 71 | 72 | (defmethod serialize "blob" 73 | [_shapes _shape args serialized prefix] 74 | (prefix-assoc serialized prefix (util/base64-encode args))) 75 | 76 | (defmethod serialize "timestamp" 77 | [_shapes shape args serialized prefix] 78 | (prefix-assoc serialized prefix (shape/format-date shape 79 | args 80 | (partial util/format-date util/iso8601-date-format)))) 81 | 82 | (defmethod serialize "boolean" 83 | [_shapes _shape args serialized prefix] 84 | (prefix-assoc serialized prefix (if args "true" "false"))) 85 | 86 | (defn build-query-http-request 87 | [{:keys [op request]} service serialize] 88 | (let [operation (get-in service [:operations op]) 89 | shapes (:shapes service) 90 | input-shape (shape/resolve shapes (:input operation)) 91 | params {"Action" (name op) 92 | "Version" (get-in service [:metadata :apiVersion])}] 93 | {:request-method :post 94 | :scheme :https 95 | :server-port 443 96 | :uri "/" 97 | :headers (aws.protocols/headers service operation) 98 | :body (util/query-string 99 | (serialize shapes input-shape request params []))})) 100 | 101 | (defmethod aws.protocols/build-http-request "query" 102 | [service op-map] 103 | (build-query-http-request op-map service serialize)) 104 | 105 | (defn build-query-http-response 106 | [service {:keys [op]} {:keys [body]}] 107 | (let [operation (get-in service [:operations op]) 108 | shapes (:shapes service)] 109 | (if-let [output-shape (shape/resolve shapes (:output operation))] 110 | (shape/xml-parse shapes output-shape (util/bbuf->str body)) 111 | (util/xml->map (util/xml-read (util/bbuf->str body)))))) 112 | 113 | (defmethod aws.protocols/parse-http-response "query" 114 | [service op-map http-response] 115 | (build-query-http-response service op-map http-response)) 116 | -------------------------------------------------------------------------------- /src/cognitect/aws/protocols/rest_json.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns ^:skip-wiki cognitect.aws.protocols.rest-json 5 | "Impl, don't call directly." 6 | (:require [cognitect.aws.protocols :as aws.protocols] 7 | [cognitect.aws.protocols.rest :as rest] 8 | [cognitect.aws.shape :as shape] 9 | [cognitect.aws.util :as util])) 10 | 11 | (set! *warn-on-reflection* true) 12 | 13 | (defmulti serialize 14 | "json body args serializer passed to rest/build-http-request 15 | 16 | Obs: this fn doesn't use the 2nd arg, but the one in rest-xml 17 | does, and this function gets invoked by rest/build-http-request, 18 | which requires a 3 arg serialize fn." 19 | (fn [_shapes _ shape _data] (:type shape))) 20 | 21 | (defmethod serialize :default 22 | [shapes _ shape data] 23 | (shape/json-serialize shapes shape data)) 24 | 25 | (defmethod serialize "structure" 26 | [shapes _ shape data] 27 | (some->> (util/with-defaults shape data) 28 | not-empty 29 | (shape/json-serialize shapes shape))) 30 | 31 | (defmethod serialize "timestamp" 32 | [_shapes _ shape data] 33 | (shape/format-date shape data)) 34 | 35 | (defmethod aws.protocols/build-http-request "rest-json" 36 | [service op-map] 37 | (rest/build-http-request service op-map serialize)) 38 | 39 | (defmethod aws.protocols/parse-http-response "rest-json" 40 | [service op-map http-response] 41 | (rest/parse-http-response service 42 | op-map 43 | http-response 44 | shape/json-parse)) 45 | -------------------------------------------------------------------------------- /src/cognitect/aws/protocols/rest_xml.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns ^:skip-wiki cognitect.aws.protocols.rest-xml 5 | "Impl, don't call directly." 6 | (:require [cognitect.aws.protocols :as aws.protocols] 7 | [cognitect.aws.protocols.rest :as rest] 8 | [cognitect.aws.shape :as shape])) 9 | 10 | (set! *warn-on-reflection* true) 11 | 12 | (defn serialize 13 | "xml body args serializer passed to rest/build-http-request" 14 | [shapes shape-name shape data] 15 | (when data 16 | (shape/xml-serialize shapes 17 | shape 18 | data 19 | (or (:locationName shape) shape-name)))) 20 | 21 | (defmethod aws.protocols/build-http-request "rest-xml" 22 | [service op-map] 23 | (rest/build-http-request service op-map serialize)) 24 | 25 | (defmethod aws.protocols/parse-http-response "rest-xml" 26 | [service op-map http-response] 27 | (rest/parse-http-response service 28 | op-map 29 | http-response 30 | shape/xml-parse)) 31 | -------------------------------------------------------------------------------- /src/cognitect/aws/region.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns cognitect.aws.region 5 | "Region providers. Primarily for internal use, and subject to change." 6 | (:require [clojure.string :as str] 7 | [clojure.java.io :as io] 8 | [clojure.tools.logging :as log] 9 | [cognitect.aws.util :as u] 10 | [cognitect.aws.config :as config] 11 | [cognitect.aws.ec2-metadata-utils :as ec2]) 12 | (:import (java.io File))) 13 | 14 | (set! *warn-on-reflection* true) 15 | 16 | (defn ^:skip-wiki valid-region 17 | "For internal use. Don't call directly. 18 | 19 | Return the credential region if valid, otherwise nil." 20 | [region] 21 | ;; TODO: (dchelimsky 2018-07-27) maybe validate this against known regions? 22 | (when-not (str/blank? region) region)) 23 | 24 | (defprotocol RegionProvider 25 | (fetch [_] "Returns the region found by this provider, or nil.")) 26 | 27 | (defn chain-region-provider 28 | "Chain together multiple region providers. 29 | 30 | `fetch` calls each provider in order until one returns a non-nil result, 31 | or returns nil. 32 | 33 | Alpha. Subject to change." 34 | [providers] 35 | (reify RegionProvider 36 | (fetch [_] 37 | (or (valid-region (some fetch providers)) 38 | (throw (ex-info "No region found by any region provider." 39 | {:providers (map class providers)})))))) 40 | 41 | (defn environment-region-provider 42 | "Returns the region from the AWS_REGION env var, or nil if not present. 43 | 44 | Alpha. Subject to change." 45 | [] 46 | (reify RegionProvider 47 | (fetch [_] (valid-region (u/getenv "AWS_REGION"))))) 48 | 49 | (defn system-property-region-provider 50 | "Returns the region from the aws.region system property, or nil if not present. 51 | 52 | Alpha. Subject to change." 53 | [] 54 | (reify RegionProvider 55 | (fetch [_] (valid-region (u/getProperty "aws.region"))))) 56 | 57 | (defn profile-region-provider 58 | "Returns the region from an AWS configuration profile. 59 | 60 | Arguments: 61 | 62 | f File The profile configuration file. (default: ~/.aws/config) 63 | profile-name string The name of the profile in the file. (default: default) 64 | 65 | Parsed properties: 66 | 67 | region required 68 | 69 | Alpha. Subject to change." 70 | ([] 71 | (profile-region-provider (or (u/getenv "AWS_PROFILE") 72 | (u/getProperty "aws.profile") 73 | "default"))) 74 | ([profile-name] 75 | (profile-region-provider profile-name (or (io/file (u/getenv "AWS_CONFIG_FILE")) 76 | (io/file (u/getProperty "user.home") ".aws" "config")))) 77 | ([profile-name ^File f] 78 | (reify RegionProvider 79 | (fetch [_] 80 | (when (.exists f) 81 | (try 82 | (let [profile (get (config/parse f) profile-name)] 83 | (valid-region (get profile "region"))) 84 | (catch Throwable t 85 | (log/error t "Unable to fetch region from the AWS config file " (str f))))))))) 86 | 87 | (defn ^:deprecated instance-region-provider 88 | "Returns the region from the ec2 instance's metadata service, 89 | or nil if the service can not be found. 90 | 91 | DEPRECATED use `instance-region-IMDS-v2-provider` 92 | 93 | Alpha. Subject to change." 94 | [http-client] 95 | (let [cached-region (atom nil) 96 | imdsv2-token nil] 97 | (reify RegionProvider 98 | (fetch [_] 99 | (or @cached-region 100 | (reset! cached-region (valid-region (ec2/get-ec2-instance-region http-client imdsv2-token)))))))) 101 | 102 | (defn instance-region-IMDS-v2-provider 103 | "Returns the region from the ec2 instance's IMDS v2 metadata service, 104 | or nil if the service can not be found. 105 | 106 | Alpha. Subject to change." 107 | [http-client] 108 | (let [cached-region (atom nil)] 109 | (reify RegionProvider 110 | (fetch [_] 111 | (or @cached-region 112 | (reset! cached-region (valid-region (when-let [IMDSv2-token (ec2/IMDSv2-token http-client)] 113 | (ec2/get-ec2-instance-region http-client IMDSv2-token))))))))) 114 | 115 | (defn default-region-provider 116 | "Returns a chain-region-provider with, in order: 117 | 118 | environment-region-provider 119 | system-property-region-provider 120 | profile-region-provider 121 | instance-region-IMDS-v2-provider 122 | instance-region-provider 123 | 124 | Alpha. Subject to change." 125 | [http-client] 126 | (chain-region-provider 127 | [(environment-region-provider) 128 | (system-property-region-provider) 129 | (profile-region-provider) 130 | (instance-region-IMDS-v2-provider http-client) 131 | (instance-region-provider http-client)])) 132 | 133 | (defn fetch-async 134 | "Returns a channel that will produce the result of calling fetch on 135 | the provider. 136 | 137 | Alpha. Subject to change." 138 | [provider] 139 | (u/fetch-async fetch provider "region")) 140 | -------------------------------------------------------------------------------- /src/cognitect/aws/resources.clj: -------------------------------------------------------------------------------- 1 | (ns cognitect.aws.resources 2 | (:require [clojure.java.io :as io]) 3 | (:import (clojure.lang RT))) 4 | 5 | (def loader 6 | "Clojure's base class loader, used to load all resources. 7 | 8 | This ensures the same class loader is used, no matter which thread invokes `resource`. 9 | This is needed to guard against the scenario where the application is running in an 10 | environment that uses a non-default class loader, and the `resource` function is invoked 11 | from a thread that does not inherit the custom class loader (e.g. ForkJoinPool/commonPool threads). 12 | 13 | See https://github.com/cognitect-labs/aws-api/issues/265 for details" 14 | (RT/baseLoader)) 15 | 16 | (defn resource 17 | "Returns the URL for a named resource, always using Clojure's base class loader." 18 | [n] 19 | (io/resource n loader)) 20 | -------------------------------------------------------------------------------- /src/cognitect/aws/retry.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns cognitect.aws.retry 5 | (:require [clojure.core.async :as a])) 6 | 7 | (set! *warn-on-reflection* true) 8 | 9 | (defn ^:skip-wiki with-retry 10 | "For internal use. Do not call directly. 11 | 12 | Calls req-fn, a *non-blocking* function that wraps some operation 13 | and returns a channel. When the response to req-fn is retriable? 14 | and backoff returns an int, waits backoff ms and retries, otherwise 15 | puts response on resp-chan." 16 | [req-fn resp-chan retriable? backoff] 17 | (a/go-loop [retries 0] 18 | (let [resp (a/! resp-chan resp)) 25 | (a/>! resp-chan resp)))) 26 | resp-chan) 27 | 28 | (defn capped-exponential-backoff 29 | "Returns a function of the num-retries (so far), which returns the 30 | lesser of max-backoff and an exponentially increasing multiple of 31 | base, or nil when (>= num-retries max-retries). 32 | See with-retry to see how it is used. 33 | 34 | Alpha. Subject to change." 35 | [base max-backoff max-retries] 36 | (fn [num-retries] 37 | (when (< num-retries max-retries) 38 | (min max-backoff 39 | (* base (bit-shift-left 1 num-retries)))))) 40 | 41 | (def default-backoff 42 | "Returns (capped-exponential-backoff 100 20000 3). 43 | 44 | Alpha. Subject to change." 45 | (capped-exponential-backoff 100 20000 3)) 46 | 47 | (def default-retriable? 48 | "A fn of an http-response map which returns a truthy value 49 | if (:cognitect.anomalies/category http-response) is any of: 50 | - :cognitect.anomalies/busy 51 | - :cognitect.anomalies/interrupted 52 | - :cognitect.anomalies/unavailable 53 | 54 | Alpha. Subject to change." 55 | (comp #{:cognitect.anomalies/busy 56 | :cognitect.anomalies/interrupted 57 | :cognitect.anomalies/unavailable} 58 | :cognitect.anomalies/category)) 59 | -------------------------------------------------------------------------------- /src/cognitect/aws/service.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns ^:skip-wiki cognitect.aws.service 5 | "Impl, don't call directly." 6 | (:require [clojure.edn :as edn] 7 | [clojure.string :as str] 8 | [clojure.walk :as walk] 9 | [cognitect.aws.resources :as resources])) 10 | 11 | (set! *warn-on-reflection* true) 12 | 13 | (def base-ns "cognitect.aws") 14 | 15 | (def base-resource-path "cognitect/aws") 16 | 17 | (defn descriptor-resource-path [service-name] 18 | (str base-resource-path "/" service-name "/service.edn")) 19 | 20 | (defn descriptor-resource [service-name] 21 | (resources/resource (descriptor-resource-path service-name))) 22 | 23 | (defn read-service-description 24 | "Return service description readerable source (anything supported by 25 | clojure.java.io/reader)." 26 | [readerable] 27 | (edn/read-string (slurp readerable))) 28 | 29 | (defn service-description [service-name] 30 | (if-let [resource (descriptor-resource service-name)] 31 | (read-service-description resource) 32 | (throw (ex-info (str "Cannot find resource " (descriptor-resource-path service-name) ".") {})))) 33 | 34 | (defn endpoint-prefix 35 | [service] 36 | (get-in service [:metadata :endpointPrefix])) 37 | 38 | (defn signing-name 39 | [service] 40 | (get-in service [:metadata :signingName])) 41 | 42 | (defn service-name [service] 43 | (-> service :metadata :uid 44 | (str/replace #"-\d{4}-\d{2}-\d{2}" "") 45 | (str/replace #"\s" "-") 46 | (str/replace #"\." "-"))) 47 | 48 | (defn ns-prefix 49 | "Returns the namespace prefix to use when looking up resources." 50 | [service] 51 | (format "%s.%s" base-ns (service-name service))) 52 | 53 | (defn spec-ns 54 | "The namespace for specs for service." 55 | [service] 56 | (symbol (format "%s.specs" (ns-prefix service)))) 57 | 58 | (defn load-specs [service] 59 | (require (spec-ns service))) 60 | 61 | (defonce svc-docs (atom {})) 62 | 63 | (defn with-ref-meta [m op doc] 64 | (let [ref-atom (atom nil) 65 | refs (:refs doc) 66 | updated-doc (walk/postwalk 67 | (fn [n] 68 | (if (contains? refs n) 69 | (with-meta n 70 | {'clojure.core.protocols/datafy #(-> ref-atom deref %)}) 71 | n)) 72 | doc)] 73 | (reset! ref-atom (:refs updated-doc)) 74 | (assoc m op (into {:name (name op)} updated-doc)))) 75 | 76 | (defn docs 77 | "Returns the docs for this service" 78 | [service] 79 | (let [k (service-name service)] 80 | (if-let [doc (get @svc-docs k)] 81 | doc 82 | (-> (swap! svc-docs 83 | assoc 84 | k 85 | (reduce-kv with-ref-meta 86 | {} 87 | (clojure.edn/read-string 88 | (slurp 89 | (resources/resource (format "%s/%s/docs.edn" base-resource-path (service-name service))))))) 90 | (get k))))) 91 | 92 | (defn request-spec-key 93 | "Returns the key to look up in the spec registry for the spec for 94 | the request body of op." 95 | [service op] 96 | (load-specs service) 97 | (when-let [shape-key (some->> service :operations op :input :shape)] 98 | (keyword (ns-prefix service) shape-key))) 99 | 100 | (defn response-spec-key 101 | "Returns the key to look up in the spec registry for the spec for 102 | the response body of op." 103 | [service op] 104 | (load-specs service) 105 | (when-let [shape-key (some->> service :operations op :output :shape)] 106 | (keyword (ns-prefix service) shape-key))) 107 | -------------------------------------------------------------------------------- /test/resources/.aws/config: -------------------------------------------------------------------------------- 1 | [default] 2 | region = us-east-1 3 | 4 | [tardigrade] 5 | region = us-west-1 6 | 7 | [profile waterbear] 8 | region = eu-west-1 9 | credential_process=awsprocesscreds-saml -e 'https://url.com?with-query-string=true' -u some-user -a arn:aws:iam::1234:role/system/specialness 10 | 11 | [nested] 12 | s3 = 13 | max_concurrent_requests=10 14 | s3_key = s3_val 15 | region = eu-west-1 16 | s3 = 17 | max_queue_size=1000 18 | foo.bar = baz 19 | 20 | [temp-credentials] 21 | aws_session_token = FQoG/Ehj40mh/xf0TR+xLl+cp/xGWC+haIy+fJh6/fD+LFW= 22 | -------------------------------------------------------------------------------- /test/resources/.aws/credentials: -------------------------------------------------------------------------------- 1 | [default] 2 | aws_access_key_id = DEFAULT_AWS_ACCESS_KEY 3 | aws_secret_access_key = DEFAULT_AWS_SECRET_ACCESS_KEY 4 | 5 | [tardigrade] 6 | aws_access_key_id = TARDIGRADE_AWS_ACCESS_KEY 7 | aws_secret_access_key = TARDIGRADE_AWS_SECRET_ACCESS_KEY 8 | aws_session_token = TARDIGRADE_AWS_SESSION_TOKEN 9 | -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-header-key-duplicate/get-header-key-duplicate.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;my-header1;x-amz-date, Signature=c9d5ea9f3f72853aea855b47ea873832890dbdd183b4468f858259531a5138ea -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-header-key-duplicate/get-header-key-duplicate.creq: -------------------------------------------------------------------------------- 1 | GET 2 | / 3 | 4 | host:example.amazonaws.com 5 | my-header1:value2,value2,value1 6 | x-amz-date:20150830T123600Z 7 | 8 | host;my-header1;x-amz-date 9 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-header-key-duplicate/get-header-key-duplicate.req: -------------------------------------------------------------------------------- 1 | GET / HTTP/1.1 2 | Host:example.amazonaws.com 3 | My-Header1:value2 4 | My-Header1:value2 5 | My-Header1:value1 6 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-header-key-duplicate/get-header-key-duplicate.sreq: -------------------------------------------------------------------------------- 1 | GET / HTTP/1.1 2 | Host:example.amazonaws.com 3 | My-Header1:value2 4 | My-Header1:value2 5 | My-Header1:value1 6 | X-Amz-Date:20150830T123600Z 7 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;my-header1;x-amz-date, Signature=c9d5ea9f3f72853aea855b47ea873832890dbdd183b4468f858259531a5138ea -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-header-key-duplicate/get-header-key-duplicate.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | dc7f04a3abfde8d472b0ab1a418b741b7c67174dad1551b4117b15527fbe966c -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-header-value-multiline/get-header-value-multiline.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;my-header1;x-amz-date, Signature=ba17b383a53190154eb5fa66a1b836cc297cc0a3d70a5d00705980573d8ff790 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-header-value-multiline/get-header-value-multiline.creq: -------------------------------------------------------------------------------- 1 | GET 2 | / 3 | 4 | host:example.amazonaws.com 5 | my-header1:value1,value2,value3 6 | x-amz-date:20150830T123600Z 7 | 8 | host;my-header1;x-amz-date 9 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-header-value-multiline/get-header-value-multiline.req: -------------------------------------------------------------------------------- 1 | GET / HTTP/1.1 2 | Host:example.amazonaws.com 3 | My-Header1:value1 4 | value2 5 | value3 6 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-header-value-multiline/get-header-value-multiline.sreq: -------------------------------------------------------------------------------- 1 | GET / HTTP/1.1 2 | Host:example.amazonaws.com 3 | My-Header1:value1 4 | value2 5 | value3 6 | X-Amz-Date:20150830T123600Z 7 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;my-header1;x-amz-date, Signature=ba17b383a53190154eb5fa66a1b836cc297cc0a3d70a5d00705980573d8ff790 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-header-value-multiline/get-header-value-multiline.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | b7b6cbfd8a0430b78891e986784da2630c8a135a8595cec25b26ea94f926ee55 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-header-value-order/get-header-value-order.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;my-header1;x-amz-date, Signature=08c7e5a9acfcfeb3ab6b2185e75ce8b1deb5e634ec47601a50643f830c755c01 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-header-value-order/get-header-value-order.creq: -------------------------------------------------------------------------------- 1 | GET 2 | / 3 | 4 | host:example.amazonaws.com 5 | my-header1:value4,value1,value3,value2 6 | x-amz-date:20150830T123600Z 7 | 8 | host;my-header1;x-amz-date 9 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-header-value-order/get-header-value-order.req: -------------------------------------------------------------------------------- 1 | GET / HTTP/1.1 2 | Host:example.amazonaws.com 3 | My-Header1:value4 4 | My-Header1:value1 5 | My-Header1:value3 6 | My-Header1:value2 7 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-header-value-order/get-header-value-order.sreq: -------------------------------------------------------------------------------- 1 | GET / HTTP/1.1 2 | Host:example.amazonaws.com 3 | My-Header1:value4 4 | My-Header1:value1 5 | My-Header1:value3 6 | My-Header1:value2 7 | X-Amz-Date:20150830T123600Z 8 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;my-header1;x-amz-date, Signature=08c7e5a9acfcfeb3ab6b2185e75ce8b1deb5e634ec47601a50643f830c755c01 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-header-value-order/get-header-value-order.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | 31ce73cd3f3d9f66977ad3dd957dc47af14df92fcd8509f59b349e9137c58b86 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-header-value-trim/get-header-value-trim.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;my-header1;my-header2;x-amz-date, Signature=acc3ed3afb60bb290fc8d2dd0098b9911fcaa05412b367055dee359757a9c736 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-header-value-trim/get-header-value-trim.creq: -------------------------------------------------------------------------------- 1 | GET 2 | / 3 | 4 | host:example.amazonaws.com 5 | my-header1:value1 6 | my-header2:"a b c" 7 | x-amz-date:20150830T123600Z 8 | 9 | host;my-header1;my-header2;x-amz-date 10 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-header-value-trim/get-header-value-trim.req: -------------------------------------------------------------------------------- 1 | GET / HTTP/1.1 2 | Host:example.amazonaws.com 3 | My-Header1: value1 4 | My-Header2: "a b c" 5 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-header-value-trim/get-header-value-trim.sreq: -------------------------------------------------------------------------------- 1 | GET / HTTP/1.1 2 | Host:example.amazonaws.com 3 | My-Header1: value1 4 | My-Header2: "a b c" 5 | X-Amz-Date:20150830T123600Z 6 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;my-header1;my-header2;x-amz-date, Signature=acc3ed3afb60bb290fc8d2dd0098b9911fcaa05412b367055dee359757a9c736 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-header-value-trim/get-header-value-trim.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | a726db9b0df21c14f559d0a978e563112acb1b9e05476f0a6a1c7d68f28605c7 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-unreserved/get-unreserved.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=07ef7494c76fa4850883e2b006601f940f8a34d404d0cfa977f52a65bbf5f24f -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-unreserved/get-unreserved.creq: -------------------------------------------------------------------------------- 1 | GET 2 | /-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 3 | 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-unreserved/get-unreserved.req: -------------------------------------------------------------------------------- 1 | GET /-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-unreserved/get-unreserved.sreq: -------------------------------------------------------------------------------- 1 | GET /-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z 4 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=07ef7494c76fa4850883e2b006601f940f8a34d404d0cfa977f52a65bbf5f24f -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-unreserved/get-unreserved.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | 6a968768eefaa713e2a6b16b589a8ea192661f098f37349f4e2c0082757446f9 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-utf8/get-utf8.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=8318018e0b0f223aa2bbf98705b62bb787dc9c0e678f255a891fd03141be5d85 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-utf8/get-utf8.creq: -------------------------------------------------------------------------------- 1 | GET 2 | /%E1%88%B4 3 | 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-utf8/get-utf8.req: -------------------------------------------------------------------------------- 1 | GET /ሴ HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-utf8/get-utf8.sreq: -------------------------------------------------------------------------------- 1 | GET /ሴ HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z 4 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=8318018e0b0f223aa2bbf98705b62bb787dc9c0e678f255a891fd03141be5d85 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-utf8/get-utf8.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | 2a0a97d02205e45ce2e994789806b19270cfbbb0921b278ccf58f5249ac42102 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-empty-query-key/get-vanilla-empty-query-key.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=a67d582fa61cc504c4bae71f336f98b97f1ea3c7a6bfe1b6e45aec72011b9aeb -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-empty-query-key/get-vanilla-empty-query-key.creq: -------------------------------------------------------------------------------- 1 | GET 2 | / 3 | Param1=value1 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-empty-query-key/get-vanilla-empty-query-key.req: -------------------------------------------------------------------------------- 1 | GET /?Param1=value1 HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-empty-query-key/get-vanilla-empty-query-key.sreq: -------------------------------------------------------------------------------- 1 | GET /?Param1=value1 HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z 4 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=a67d582fa61cc504c4bae71f336f98b97f1ea3c7a6bfe1b6e45aec72011b9aeb -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-empty-query-key/get-vanilla-empty-query-key.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | 1e24db194ed7d0eec2de28d7369675a243488e08526e8c1c73571282f7c517ab -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-query-order-key-case/get-vanilla-query-order-key-case.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=b97d918cfa904a5beff61c982a1b6f458b799221646efd99d3219ec94cdf2500 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-query-order-key-case/get-vanilla-query-order-key-case.creq: -------------------------------------------------------------------------------- 1 | GET 2 | / 3 | Param1=value1&Param2=value2 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-query-order-key-case/get-vanilla-query-order-key-case.req: -------------------------------------------------------------------------------- 1 | GET /?Param2=value2&Param1=value1 HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-query-order-key-case/get-vanilla-query-order-key-case.sreq: -------------------------------------------------------------------------------- 1 | GET /?Param2=value2&Param1=value1 HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z 4 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=b97d918cfa904a5beff61c982a1b6f458b799221646efd99d3219ec94cdf2500 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-query-order-key-case/get-vanilla-query-order-key-case.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | 816cd5b414d056048ba4f7c5386d6e0533120fb1fcfa93762cf0fc39e2cf19e0 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-query-order-key/get-vanilla-query-order-key.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=eedbc4e291e521cf13422ffca22be7d2eb8146eecf653089df300a15b2382bd1 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-query-order-key/get-vanilla-query-order-key.creq: -------------------------------------------------------------------------------- 1 | GET 2 | / 3 | Param1=Value1&Param1=value2 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-query-order-key/get-vanilla-query-order-key.req: -------------------------------------------------------------------------------- 1 | GET /?Param1=value2&Param1=Value1 HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-query-order-key/get-vanilla-query-order-key.sreq: -------------------------------------------------------------------------------- 1 | GET /?Param1=value2&Param1=Value1 HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z 4 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=eedbc4e291e521cf13422ffca22be7d2eb8146eecf653089df300a15b2382bd1 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-query-order-key/get-vanilla-query-order-key.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | 704b4cef673542d84cdff252633f065e8daeba5f168b77116f8b1bcaf3d38f89 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-query-order-value/get-vanilla-query-order-value.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=5772eed61e12b33fae39ee5e7012498b51d56abc0abb7c60486157bd471c4694 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-query-order-value/get-vanilla-query-order-value.creq: -------------------------------------------------------------------------------- 1 | GET 2 | / 3 | Param1=value1&Param1=value2 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-query-order-value/get-vanilla-query-order-value.req: -------------------------------------------------------------------------------- 1 | GET /?Param1=value2&Param1=value1 HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-query-order-value/get-vanilla-query-order-value.sreq: -------------------------------------------------------------------------------- 1 | GET /?Param1=value2&Param1=value1 HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z 4 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=5772eed61e12b33fae39ee5e7012498b51d56abc0abb7c60486157bd471c4694 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-query-order-value/get-vanilla-query-order-value.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | c968629d70850097a2d8781c9bf7edcb988b04cac14cca9be4acc3595f884606 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-query-unreserved/get-vanilla-query-unreserved.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=9c3e54bfcdf0b19771a7f523ee5669cdf59bc7cc0884027167c21bb143a40197 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-query-unreserved/get-vanilla-query-unreserved.creq: -------------------------------------------------------------------------------- 1 | GET 2 | / 3 | -._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-query-unreserved/get-vanilla-query-unreserved.req: -------------------------------------------------------------------------------- 1 | GET /?-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-query-unreserved/get-vanilla-query-unreserved.sreq: -------------------------------------------------------------------------------- 1 | GET /?-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z 4 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=9c3e54bfcdf0b19771a7f523ee5669cdf59bc7cc0884027167c21bb143a40197 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-query-unreserved/get-vanilla-query-unreserved.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | c30d4703d9f799439be92736156d47ccfb2d879ddf56f5befa6d1d6aab979177 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-query/get-vanilla-query.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=5fa00fa31553b73ebf1942676e86291e8372ff2a2260956d9b8aae1d763fbf31 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-query/get-vanilla-query.creq: -------------------------------------------------------------------------------- 1 | GET 2 | / 3 | 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-query/get-vanilla-query.req: -------------------------------------------------------------------------------- 1 | GET / HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-query/get-vanilla-query.sreq: -------------------------------------------------------------------------------- 1 | GET / HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z 4 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=5fa00fa31553b73ebf1942676e86291e8372ff2a2260956d9b8aae1d763fbf31 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-query/get-vanilla-query.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | bb579772317eb040ac9ed261061d46c1f17a8133879d6129b6e1c25292927e63 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-utf8-query/get-vanilla-utf8-query.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=2cdec8eed098649ff3a119c94853b13c643bcf08f8b0a1d91e12c9027818dd04 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-utf8-query/get-vanilla-utf8-query.creq: -------------------------------------------------------------------------------- 1 | GET 2 | / 3 | %E1%88%B4=bar 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-utf8-query/get-vanilla-utf8-query.req: -------------------------------------------------------------------------------- 1 | GET /?ሴ=bar HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-utf8-query/get-vanilla-utf8-query.sreq: -------------------------------------------------------------------------------- 1 | GET /?ሴ=bar HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z 4 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=2cdec8eed098649ff3a119c94853b13c643bcf08f8b0a1d91e12c9027818dd04 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla-utf8-query/get-vanilla-utf8-query.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | eb30c5bed55734080471a834cc727ae56beb50e5f39d1bff6d0d38cb192a7073 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla/get-vanilla.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=5fa00fa31553b73ebf1942676e86291e8372ff2a2260956d9b8aae1d763fbf31 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla/get-vanilla.creq: -------------------------------------------------------------------------------- 1 | GET 2 | / 3 | 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla/get-vanilla.req: -------------------------------------------------------------------------------- 1 | GET / HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla/get-vanilla.sreq: -------------------------------------------------------------------------------- 1 | GET / HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z 4 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=5fa00fa31553b73ebf1942676e86291e8372ff2a2260956d9b8aae1d763fbf31 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/get-vanilla/get-vanilla.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | bb579772317eb040ac9ed261061d46c1f17a8133879d6129b6e1c25292927e63 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-relative-relative/get-relative-relative.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=5fa00fa31553b73ebf1942676e86291e8372ff2a2260956d9b8aae1d763fbf31 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-relative-relative/get-relative-relative.creq: -------------------------------------------------------------------------------- 1 | GET 2 | / 3 | 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-relative-relative/get-relative-relative.req: -------------------------------------------------------------------------------- 1 | GET /example1/example2/../.. HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-relative-relative/get-relative-relative.sreq: -------------------------------------------------------------------------------- 1 | GET /example1/example2/../.. HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z 4 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=5fa00fa31553b73ebf1942676e86291e8372ff2a2260956d9b8aae1d763fbf31 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-relative-relative/get-relative-relative.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | bb579772317eb040ac9ed261061d46c1f17a8133879d6129b6e1c25292927e63 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-relative/get-relative.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=5fa00fa31553b73ebf1942676e86291e8372ff2a2260956d9b8aae1d763fbf31 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-relative/get-relative.creq: -------------------------------------------------------------------------------- 1 | GET 2 | / 3 | 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-relative/get-relative.req: -------------------------------------------------------------------------------- 1 | GET /example/.. HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-relative/get-relative.sreq: -------------------------------------------------------------------------------- 1 | GET /example/.. HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z 4 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=5fa00fa31553b73ebf1942676e86291e8372ff2a2260956d9b8aae1d763fbf31 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-relative/get-relative.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | bb579772317eb040ac9ed261061d46c1f17a8133879d6129b6e1c25292927e63 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-slash-dot-slash/get-slash-dot-slash.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=5fa00fa31553b73ebf1942676e86291e8372ff2a2260956d9b8aae1d763fbf31 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-slash-dot-slash/get-slash-dot-slash.creq: -------------------------------------------------------------------------------- 1 | GET 2 | / 3 | 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-slash-dot-slash/get-slash-dot-slash.req: -------------------------------------------------------------------------------- 1 | GET /./ HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-slash-dot-slash/get-slash-dot-slash.sreq: -------------------------------------------------------------------------------- 1 | GET /./ HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z 4 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=5fa00fa31553b73ebf1942676e86291e8372ff2a2260956d9b8aae1d763fbf31 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-slash-dot-slash/get-slash-dot-slash.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | bb579772317eb040ac9ed261061d46c1f17a8133879d6129b6e1c25292927e63 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-slash-pointless-dot/get-slash-pointless-dot.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=ef75d96142cf21edca26f06005da7988e4f8dc83a165a80865db7089db637ec5 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-slash-pointless-dot/get-slash-pointless-dot.creq: -------------------------------------------------------------------------------- 1 | GET 2 | /example 3 | 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-slash-pointless-dot/get-slash-pointless-dot.req: -------------------------------------------------------------------------------- 1 | GET /./example HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-slash-pointless-dot/get-slash-pointless-dot.sreq: -------------------------------------------------------------------------------- 1 | GET /./example HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z 4 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=ef75d96142cf21edca26f06005da7988e4f8dc83a165a80865db7089db637ec5 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-slash-pointless-dot/get-slash-pointless-dot.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | 214d50c111a8edc4819da6a636336472c916b5240f51e9a51b5c3305180cf702 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-slash/get-slash.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=5fa00fa31553b73ebf1942676e86291e8372ff2a2260956d9b8aae1d763fbf31 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-slash/get-slash.creq: -------------------------------------------------------------------------------- 1 | GET 2 | / 3 | 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-slash/get-slash.req: -------------------------------------------------------------------------------- 1 | GET // HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-slash/get-slash.sreq: -------------------------------------------------------------------------------- 1 | GET // HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z 4 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=5fa00fa31553b73ebf1942676e86291e8372ff2a2260956d9b8aae1d763fbf31 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-slash/get-slash.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | bb579772317eb040ac9ed261061d46c1f17a8133879d6129b6e1c25292927e63 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-slashes/get-slashes.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=9a624bd73a37c9a373b5312afbebe7a714a789de108f0bdfe846570885f57e84 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-slashes/get-slashes.creq: -------------------------------------------------------------------------------- 1 | GET 2 | /example/ 3 | 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-slashes/get-slashes.req: -------------------------------------------------------------------------------- 1 | GET //example// HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-slashes/get-slashes.sreq: -------------------------------------------------------------------------------- 1 | GET //example// HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z 4 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=9a624bd73a37c9a373b5312afbebe7a714a789de108f0bdfe846570885f57e84 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-slashes/get-slashes.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | cb96b4ac96d501f7c5c15bc6d67b3035061cfced4af6585ad927f7e6c985c015 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-space/get-space.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=652487583200325589f1fba4c7e578f72c47cb61beeca81406b39ddec1366741 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-space/get-space.creq: -------------------------------------------------------------------------------- 1 | GET 2 | /example%20space/ 3 | 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-space/get-space.req: -------------------------------------------------------------------------------- 1 | GET /example space/ HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-space/get-space.sreq: -------------------------------------------------------------------------------- 1 | GET /example space/ HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z 4 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=652487583200325589f1fba4c7e578f72c47cb61beeca81406b39ddec1366741 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/get-space/get-space.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | 63ee75631ed7234ae61b5f736dfc7754cdccfedbff4b5128a915706ee9390d86 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/normalize-path/normalize-path.txt: -------------------------------------------------------------------------------- 1 | A note about signing requests to Amazon S3: 2 | 3 | In exception to this, you do not normalize URI paths for requests to Amazon S3. For example, if you have a bucket with an object named my-object//example//photo.user, use that path. Normalizing the path to my-object/example/photo.user will cause the request to fail. For more information, see Task 1: Create a Canonical Request in the Amazon Simple Storage Service API Reference: http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html#canonical-request -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-header-key-case/post-header-key-case.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=5da7c1a2acd57cee7505fc6676e4e544621c30862966e37dddb68e92efbe5d6b -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-header-key-case/post-header-key-case.creq: -------------------------------------------------------------------------------- 1 | POST 2 | / 3 | 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-header-key-case/post-header-key-case.req: -------------------------------------------------------------------------------- 1 | POST / HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-header-key-case/post-header-key-case.sreq: -------------------------------------------------------------------------------- 1 | POST / HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z 4 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=5da7c1a2acd57cee7505fc6676e4e544621c30862966e37dddb68e92efbe5d6b -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-header-key-case/post-header-key-case.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | 553f88c9e4d10fc9e109e2aeb65f030801b70c2f6468faca261d401ae622fc87 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-header-key-sort/post-header-key-sort.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;my-header1;x-amz-date, Signature=c5410059b04c1ee005303aed430f6e6645f61f4dc9e1461ec8f8916fdf18852c -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-header-key-sort/post-header-key-sort.creq: -------------------------------------------------------------------------------- 1 | POST 2 | / 3 | 4 | host:example.amazonaws.com 5 | my-header1:value1 6 | x-amz-date:20150830T123600Z 7 | 8 | host;my-header1;x-amz-date 9 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-header-key-sort/post-header-key-sort.req: -------------------------------------------------------------------------------- 1 | POST / HTTP/1.1 2 | Host:example.amazonaws.com 3 | My-Header1:value1 4 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-header-key-sort/post-header-key-sort.sreq: -------------------------------------------------------------------------------- 1 | POST / HTTP/1.1 2 | Host:example.amazonaws.com 3 | My-Header1:value1 4 | X-Amz-Date:20150830T123600Z 5 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;my-header1;x-amz-date, Signature=c5410059b04c1ee005303aed430f6e6645f61f4dc9e1461ec8f8916fdf18852c -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-header-key-sort/post-header-key-sort.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | 9368318c2967cf6de74404b30c65a91e8f6253e0a8659d6d5319f1a812f87d65 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-header-value-case/post-header-value-case.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;my-header1;x-amz-date, Signature=cdbc9802e29d2942e5e10b5bccfdd67c5f22c7c4e8ae67b53629efa58b974b7d -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-header-value-case/post-header-value-case.creq: -------------------------------------------------------------------------------- 1 | POST 2 | / 3 | 4 | host:example.amazonaws.com 5 | my-header1:VALUE1 6 | x-amz-date:20150830T123600Z 7 | 8 | host;my-header1;x-amz-date 9 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-header-value-case/post-header-value-case.req: -------------------------------------------------------------------------------- 1 | POST / HTTP/1.1 2 | Host:example.amazonaws.com 3 | My-Header1:VALUE1 4 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-header-value-case/post-header-value-case.sreq: -------------------------------------------------------------------------------- 1 | POST / HTTP/1.1 2 | Host:example.amazonaws.com 3 | My-Header1:VALUE1 4 | X-Amz-Date:20150830T123600Z 5 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;my-header1;x-amz-date, Signature=cdbc9802e29d2942e5e10b5bccfdd67c5f22c7c4e8ae67b53629efa58b974b7d -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-header-value-case/post-header-value-case.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | d51ced243e649e3de6ef63afbbdcbca03131a21a7103a1583706a64618606a93 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-sts-token/post-sts-header-after/post-sts-header-after.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=5da7c1a2acd57cee7505fc6676e4e544621c30862966e37dddb68e92efbe5d6b -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-sts-token/post-sts-header-after/post-sts-header-after.creq: -------------------------------------------------------------------------------- 1 | POST 2 | / 3 | 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-sts-token/post-sts-header-after/post-sts-header-after.req: -------------------------------------------------------------------------------- 1 | POST / HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-sts-token/post-sts-header-after/post-sts-header-after.sreq: -------------------------------------------------------------------------------- 1 | POST / HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z 4 | X-Amz-Security-Token:AQoDYXdzEPT//////////wEXAMPLEtc764bNrC9SAPBSM22wDOk4x4HIZ8j4FZTwdQWLWsKWHGBuFqwAeMicRXmxfpSPfIeoIYRqTflfKD8YUuwthAx7mSEI/qkPpKPi/kMcGdQrmGdeehM4IC1NtBmUpp2wUE8phUZampKsburEDy0KPkyQDYwT7WZ0wq5VSXDvp75YU9HFvlRd8Tx6q6fE8YQcHNVXAkiY9q6d+xo0rKwT38xVqr7ZD0u0iPPkUL64lIZbqBAz+scqKmlzm8FDrypNC9Yjc8fPOLn9FX9KSYvKTr4rvx3iSIlTJabIQwj2ICCR/oLxBA== 5 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=5da7c1a2acd57cee7505fc6676e4e544621c30862966e37dddb68e92efbe5d6b -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-sts-token/post-sts-header-after/post-sts-header-after.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | 553f88c9e4d10fc9e109e2aeb65f030801b70c2f6468faca261d401ae622fc87 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-sts-token/post-sts-header-before/post-sts-header-before.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date;x-amz-security-token, Signature=85d96828115b5dc0cfc3bd16ad9e210dd772bbebba041836c64533a82be05ead -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-sts-token/post-sts-header-before/post-sts-header-before.creq: -------------------------------------------------------------------------------- 1 | POST 2 | / 3 | 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | x-amz-security-token:AQoDYXdzEPT//////////wEXAMPLEtc764bNrC9SAPBSM22wDOk4x4HIZ8j4FZTwdQWLWsKWHGBuFqwAeMicRXmxfpSPfIeoIYRqTflfKD8YUuwthAx7mSEI/qkPpKPi/kMcGdQrmGdeehM4IC1NtBmUpp2wUE8phUZampKsburEDy0KPkyQDYwT7WZ0wq5VSXDvp75YU9HFvlRd8Tx6q6fE8YQcHNVXAkiY9q6d+xo0rKwT38xVqr7ZD0u0iPPkUL64lIZbqBAz+scqKmlzm8FDrypNC9Yjc8fPOLn9FX9KSYvKTr4rvx3iSIlTJabIQwj2ICCR/oLxBA== 7 | 8 | host;x-amz-date;x-amz-security-token 9 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-sts-token/post-sts-header-before/post-sts-header-before.req: -------------------------------------------------------------------------------- 1 | POST / HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z 4 | X-Amz-Security-Token:AQoDYXdzEPT//////////wEXAMPLEtc764bNrC9SAPBSM22wDOk4x4HIZ8j4FZTwdQWLWsKWHGBuFqwAeMicRXmxfpSPfIeoIYRqTflfKD8YUuwthAx7mSEI/qkPpKPi/kMcGdQrmGdeehM4IC1NtBmUpp2wUE8phUZampKsburEDy0KPkyQDYwT7WZ0wq5VSXDvp75YU9HFvlRd8Tx6q6fE8YQcHNVXAkiY9q6d+xo0rKwT38xVqr7ZD0u0iPPkUL64lIZbqBAz+scqKmlzm8FDrypNC9Yjc8fPOLn9FX9KSYvKTr4rvx3iSIlTJabIQwj2ICCR/oLxBA== -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-sts-token/post-sts-header-before/post-sts-header-before.sreq: -------------------------------------------------------------------------------- 1 | POST / HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z 4 | X-Amz-Security-Token:AQoDYXdzEPT//////////wEXAMPLEtc764bNrC9SAPBSM22wDOk4x4HIZ8j4FZTwdQWLWsKWHGBuFqwAeMicRXmxfpSPfIeoIYRqTflfKD8YUuwthAx7mSEI/qkPpKPi/kMcGdQrmGdeehM4IC1NtBmUpp2wUE8phUZampKsburEDy0KPkyQDYwT7WZ0wq5VSXDvp75YU9HFvlRd8Tx6q6fE8YQcHNVXAkiY9q6d+xo0rKwT38xVqr7ZD0u0iPPkUL64lIZbqBAz+scqKmlzm8FDrypNC9Yjc8fPOLn9FX9KSYvKTr4rvx3iSIlTJabIQwj2ICCR/oLxBA== 5 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date;x-amz-security-token, Signature=85d96828115b5dc0cfc3bd16ad9e210dd772bbebba041836c64533a82be05ead -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-sts-token/post-sts-header-before/post-sts-header-before.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | c237e1b440d4c63c32ca95b5b99481081cb7b13c7e40434868e71567c1a882f6 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-sts-token/readme.txt: -------------------------------------------------------------------------------- 1 | A note about using temporary security credentials: 2 | 3 | You can use temporary security credentials provided by the AWS Security Token Service (AWS STS) to sign a request. The process is the same as using long-term credentials but requires an additional HTTP header or query string parameter for the security token. The name of the header or query string parameter is X-Amz-Security-Token, and the value is the session token (the string that you received from AWS STS when you obtained temporary security credentials). 4 | 5 | When you add X-Amz-Security-Token, some services require that you include this parameter in the canonical (signed) request. For other services, you add this parameter at the end, after you calculate the signature. For details see the API reference documentation for that service. 6 | 7 | The test suite has 2 examples: 8 | 9 | post-sts-header-before - The X-Amz-Security-Token header is part of the canonical request. 10 | 11 | post-sts-header-after - The X-Amz-Security-Token header is added to the request after you calculate the signature. 12 | 13 | The test suite uses this example value for X-Amz-Security-Token: 14 | 15 | AQoDYXdzEPT//////////wEXAMPLEtc764bNrC9SAPBSM22wDOk4x4HIZ8j4FZTwdQWLWsKWHGBuFqwAeMicRXmxfpSPfIeoIYRqTflfKD8YUuwthAx7mSEI/qkPpKPi/kMcGdQrmGdeehM4IC1NtBmUpp2wUE8phUZampKsburEDy0KPkyQDYwT7WZ0wq5VSXDvp75YU9HFvlRd8Tx6q6fE8YQcHNVXAkiY9q6d+xo0rKwT38xVqr7ZD0u0iPPkUL64lIZbqBAz+scqKmlzm8FDrypNC9Yjc8fPOLn9FX9KSYvKTr4rvx3iSIlTJabIQwj2ICCR/oLxBA== -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-vanilla-empty-query-value/post-vanilla-empty-query-value.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=28038455d6de14eafc1f9222cf5aa6f1a96197d7deb8263271d420d138af7f11 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-vanilla-empty-query-value/post-vanilla-empty-query-value.creq: -------------------------------------------------------------------------------- 1 | POST 2 | / 3 | Param1=value1 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-vanilla-empty-query-value/post-vanilla-empty-query-value.req: -------------------------------------------------------------------------------- 1 | POST /?Param1=value1 HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-vanilla-empty-query-value/post-vanilla-empty-query-value.sreq: -------------------------------------------------------------------------------- 1 | POST /?Param1=value1 HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z 4 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=28038455d6de14eafc1f9222cf5aa6f1a96197d7deb8263271d420d138af7f11 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-vanilla-empty-query-value/post-vanilla-empty-query-value.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | 9d659678c1756bb3113e2ce898845a0a79dbbc57b740555917687f1b3340fbbd -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-vanilla-query/post-vanilla-query.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=28038455d6de14eafc1f9222cf5aa6f1a96197d7deb8263271d420d138af7f11 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-vanilla-query/post-vanilla-query.creq: -------------------------------------------------------------------------------- 1 | POST 2 | / 3 | Param1=value1 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-vanilla-query/post-vanilla-query.req: -------------------------------------------------------------------------------- 1 | POST /?Param1=value1 HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-vanilla-query/post-vanilla-query.sreq: -------------------------------------------------------------------------------- 1 | POST /?Param1=value1 HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z 4 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=28038455d6de14eafc1f9222cf5aa6f1a96197d7deb8263271d420d138af7f11 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-vanilla-query/post-vanilla-query.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | 9d659678c1756bb3113e2ce898845a0a79dbbc57b740555917687f1b3340fbbd -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-vanilla/post-vanilla.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=5da7c1a2acd57cee7505fc6676e4e544621c30862966e37dddb68e92efbe5d6b -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-vanilla/post-vanilla.creq: -------------------------------------------------------------------------------- 1 | POST 2 | / 3 | 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-vanilla/post-vanilla.req: -------------------------------------------------------------------------------- 1 | POST / HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-vanilla/post-vanilla.sreq: -------------------------------------------------------------------------------- 1 | POST / HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z 4 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=5da7c1a2acd57cee7505fc6676e4e544621c30862966e37dddb68e92efbe5d6b -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-vanilla/post-vanilla.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | 553f88c9e4d10fc9e109e2aeb65f030801b70c2f6468faca261d401ae622fc87 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-x-www-form-urlencoded-parameters/post-x-www-form-urlencoded-parameters.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=1a72ec8f64bd914b0e42e42607c7fbce7fb2c7465f63e3092b3b0d39fa77a6fe -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-x-www-form-urlencoded-parameters/post-x-www-form-urlencoded-parameters.creq: -------------------------------------------------------------------------------- 1 | POST 2 | / 3 | 4 | content-type:application/x-www-form-urlencoded; charset=utf8 5 | host:example.amazonaws.com 6 | x-amz-date:20150830T123600Z 7 | 8 | content-type;host;x-amz-date 9 | 9095672bbd1f56dfc5b65f3e153adc8731a4a654192329106275f4c7b24d0b6e -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-x-www-form-urlencoded-parameters/post-x-www-form-urlencoded-parameters.req: -------------------------------------------------------------------------------- 1 | POST / HTTP/1.1 2 | Content-Type:application/x-www-form-urlencoded; charset=utf8 3 | Host:example.amazonaws.com 4 | X-Amz-Date:20150830T123600Z 5 | 6 | Param1=value1 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-x-www-form-urlencoded-parameters/post-x-www-form-urlencoded-parameters.sreq: -------------------------------------------------------------------------------- 1 | POST / HTTP/1.1 2 | Content-Type:application/x-www-form-urlencoded; charset=utf8 3 | Host:example.amazonaws.com 4 | X-Amz-Date:20150830T123600Z 5 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=1a72ec8f64bd914b0e42e42607c7fbce7fb2c7465f63e3092b3b0d39fa77a6fe 6 | 7 | Param1=value1 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-x-www-form-urlencoded-parameters/post-x-www-form-urlencoded-parameters.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | 2e1cf7ed91881a30569e46552437e4156c823447bf1781b921b5d486c568dd1c -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-x-www-form-urlencoded/post-x-www-form-urlencoded.authz: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=ff11897932ad3f4e8b18135d722051e5ac45fc38421b1da7b9d196a0fe09473a -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-x-www-form-urlencoded/post-x-www-form-urlencoded.creq: -------------------------------------------------------------------------------- 1 | POST 2 | / 3 | 4 | content-type:application/x-www-form-urlencoded 5 | host:example.amazonaws.com 6 | x-amz-date:20150830T123600Z 7 | 8 | content-type;host;x-amz-date 9 | 9095672bbd1f56dfc5b65f3e153adc8731a4a654192329106275f4c7b24d0b6e -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-x-www-form-urlencoded/post-x-www-form-urlencoded.req: -------------------------------------------------------------------------------- 1 | POST / HTTP/1.1 2 | Content-Type:application/x-www-form-urlencoded 3 | Host:example.amazonaws.com 4 | X-Amz-Date:20150830T123600Z 5 | 6 | Param1=value1 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-x-www-form-urlencoded/post-x-www-form-urlencoded.sreq: -------------------------------------------------------------------------------- 1 | POST / HTTP/1.1 2 | Content-Type:application/x-www-form-urlencoded 3 | Host:example.amazonaws.com 4 | X-Amz-Date:20150830T123600Z 5 | Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=ff11897932ad3f4e8b18135d722051e5ac45fc38421b1da7b9d196a0fe09473a 6 | 7 | Param1=value1 -------------------------------------------------------------------------------- /test/resources/aws-sig-v4-test-suite/post-x-www-form-urlencoded/post-x-www-form-urlencoded.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | 42a5e5bb34198acb3e84da4f085bb7927f2bc277ca766e6d19c73c2154021281 -------------------------------------------------------------------------------- /test/resources/botocore/protocols/output/event-stream.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "REST XML Event Stream", 4 | "metadata": { 5 | "protocol": "rest-xml" 6 | }, 7 | "shapes": { 8 | "OutputShape": { 9 | "type": "structure", 10 | "members": { 11 | "Payload": {"shape": "EventStream"} 12 | }, 13 | "payload": "Payload" 14 | }, 15 | "EventStream": { 16 | "type": "structure", 17 | "eventstream": true, 18 | "members": { 19 | "TypeA": {"shape": "TypeAEvent"}, 20 | "TypeB": {"shape": "TypeBEvent"}, 21 | "TypeC": {"shape": "TypeCEvent"} 22 | } 23 | }, 24 | "TypeAEvent": { 25 | "type": "structure", 26 | "event": true, 27 | "members": { 28 | "Payload": { 29 | "shape": "BlobType", 30 | "eventpayload": true 31 | } 32 | } 33 | }, 34 | "TypeBEvent": { 35 | "type": "structure", 36 | "event": true, 37 | "members": { 38 | "Details": { 39 | "shape": "Details", 40 | "eventpayload": true 41 | } 42 | } 43 | }, 44 | "TypeCEvent": { 45 | "type": "structure", 46 | "event": true, 47 | "members": { 48 | "Details": { 49 | "shape": "Details", 50 | "eventpayload": true 51 | }, 52 | "Boolean": { 53 | "shape": "BooleanType", 54 | "eventheader": true 55 | }, 56 | "Integer": { 57 | "shape": "IntegerType", 58 | "eventheader": true 59 | }, 60 | "Blob": { 61 | "shape": "BlobType", 62 | "eventheader": true 63 | }, 64 | "String": { 65 | "shape": "StringType", 66 | "eventheader": true 67 | }, 68 | "Timestamp": { 69 | "shape": "TimestampType", 70 | "eventheader": true 71 | } 72 | } 73 | }, 74 | "Details": { 75 | "type": "structure", 76 | "members": { 77 | "StringField": {"shape": "StringType"}, 78 | "IntegerField": {"shape": "IntegerType"} 79 | } 80 | }, 81 | "StringType": { 82 | "type": "string" 83 | }, 84 | "IntegerType": { 85 | "type": "integer" 86 | }, 87 | "BooleanType": { 88 | "type": "boolean" 89 | }, 90 | "TimestampType": { 91 | "type": "timestamp" 92 | }, 93 | "BlobType": { 94 | "type": "blob" 95 | } 96 | }, 97 | "cases": [ 98 | { 99 | "given": { 100 | "output": { 101 | "shape": "OutputShape" 102 | }, 103 | "name": "OperationName" 104 | }, 105 | "result": { 106 | "Payload": [ 107 | { 108 | "TypeA": {"Payload": "somebytes"} 109 | }, 110 | { 111 | "TypeB": { 112 | "Details": { 113 | "StringField": "somestring", 114 | "IntegerField": 123 115 | } 116 | } 117 | } 118 | ] 119 | }, 120 | "response": { 121 | "status_code": 200, 122 | "headers": {}, 123 | "body": "AAAAbAAAAFPLgkVrDTptZXNzYWdlLXR5cGUHAAVldmVudAs6ZXZlbnQtdHlwZQcABVR5cGVBDTpjb250ZW50LXR5cGUHABhhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW1zb21lYnl0ZXMesj2HAAAAsAAAAEOaMMdXDTptZXNzYWdlLXR5cGUHAAVldmVudAs6ZXZlbnQtdHlwZQcABVR5cGVCDTpjb250ZW50LXR5cGUHAAh0ZXh0L3htbDxUeXBlQiB4bWxucz0iIj48U3RyaW5nRmllbGQ+c29tZXN0cmluZzwvU3RyaW5nRmllbGQ+PEludGVnZXJGaWVsZD4xMjM8L0ludGVnZXJGaWVsZD48L1R5cGVCPiwthPo=" 124 | } 125 | }, 126 | { 127 | "given": { 128 | "output": { 129 | "shape": "OutputShape" 130 | }, 131 | "name": "OperationName" 132 | }, 133 | "result": { 134 | "Payload": [ 135 | { 136 | "TypeC": { 137 | "Boolean": true, 138 | "Integer": 123, 139 | "Blob": "someblob", 140 | "String": "somestring", 141 | "Timestamp": 1422172800, 142 | "Details": { 143 | "StringField": "somestring", 144 | "IntegerField": 123 145 | } 146 | } 147 | } 148 | ] 149 | }, 150 | "response": { 151 | "status_code": 200, 152 | "headers": {}, 153 | "body": "AAABAQAAAJBjEbY4DTptZXNzYWdlLXR5cGUHAAVldmVudAs6ZXZlbnQtdHlwZQcABVR5cGVDDTpjb250ZW50LXR5cGUHAAh0ZXh0L3htbAdCb29sZWFuAAdJbnRlZ2VyBAAAAHsEQmxvYgYACHNvbWVibG9iBlN0cmluZwcACnNvbWVzdHJpbmcJVGltZXN0YW1wCAAAAUsgGsQAPERldGFpbHMgeG1sbnM9IiI+PFN0cmluZ0ZpZWxkPnNvbWVzdHJpbmc8L1N0cmluZ0ZpZWxkPjxJbnRlZ2VyRmllbGQ+MTIzPC9JbnRlZ2VyRmllbGQ+PC9EZXRhaWxzPhGUvKo=" 154 | } 155 | }, 156 | { 157 | "given": { 158 | "output": { 159 | "shape": "OutputShape" 160 | }, 161 | "name": "OperationName" 162 | }, 163 | "result": { 164 | "Payload": [] 165 | }, 166 | "response": { 167 | "status_code": 200, 168 | "headers": {}, 169 | "body": "" 170 | } 171 | } 172 | ] 173 | } 174 | ] 175 | -------------------------------------------------------------------------------- /test/resources/cognitect/protocols/input/query.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "URL Encoded values in body", 4 | "metadata": { 5 | "protocol": "query", 6 | "apiVersion": "2014-01-01" 7 | }, 8 | "shapes": { 9 | "InputShape": { 10 | "type": "structure", 11 | "members": { 12 | "Integer": { 13 | "shape": "IntegerType" 14 | }, 15 | "Long": { 16 | "shape": "LongType" 17 | }, 18 | "Double": { 19 | "shape" : "DoubleType" 20 | }, 21 | "Float": { 22 | "shape" : "FloatType" 23 | }, 24 | "String": { 25 | "shape": "StringType" 26 | }, 27 | "Boolean": { 28 | "shape": "BooleanType" 29 | }, 30 | "Timestamp": { 31 | "shape" : "TimestampType" 32 | }, 33 | "Blob": { 34 | "shape": "BlobType" 35 | } 36 | } 37 | }, 38 | "IntegerType": { 39 | "type": "integer" 40 | }, 41 | "LongType": { 42 | "type": "long" 43 | }, 44 | "DoubleType": { 45 | "type": "double" 46 | }, 47 | "FloatType": { 48 | "type": "float" 49 | }, 50 | "StringType": { 51 | "type": "string" 52 | }, 53 | "BooleanType": { 54 | "type": "boolean" 55 | }, 56 | "TimestampType": { 57 | "type": "timestamp" 58 | }, 59 | "BlobType": { 60 | "type": "blob" 61 | } 62 | }, 63 | "cases": [ 64 | { 65 | "given": { 66 | "input": { 67 | "shape": "InputShape" 68 | }, 69 | "name": "OperationName" 70 | }, 71 | "params": { 72 | "Integer": 22, 73 | "Long": 37, 74 | "Double": 1.2, 75 | "Float": 3.4, 76 | "String": "a+b", 77 | "Boolean": true, 78 | "Timestamp": 1422172800, 79 | "Blob": "foo" 80 | }, 81 | "serialized": { 82 | "uri": "/", 83 | "headers": { 84 | "Content-Type": "application/x-www-form-urlencoded; charset=utf-8" 85 | }, 86 | "body": "Action=OperationName&Version=2014-01-01&Integer=22&Long=37&Double=1.2&Float=3.4&String=a%2Bb&Boolean=true&Timestamp=2015-01-25T08%3A00%3A00Z&Blob=Zm9v" 87 | } 88 | } 89 | ] 90 | } 91 | ] 92 | -------------------------------------------------------------------------------- /test/resources/cognitect/protocols/input/rest-xml.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "Lists in headers", 4 | "metadata": { 5 | "protocol": "rest-xml", 6 | "apiVersion": "2014-01-01" 7 | }, 8 | "shapes": { 9 | "ObjectAttributes": { 10 | "type": "string", 11 | "enum": [ 12 | "ETag", 13 | "Checksum", 14 | "ObjectParts", 15 | "StorageClass", 16 | "ObjectSize" 17 | ] 18 | }, 19 | "ObjectAttributesList": { 20 | "type": "list", 21 | "member": { 22 | "shape": "ObjectAttributes" 23 | } 24 | }, 25 | "GetObjectAttributesRequest": { 26 | "type": "structure", 27 | "members": { 28 | "ObjectAttributes": { 29 | "shape": "ObjectAttributesList", 30 | "location": "header", 31 | "locationName": "x-amz-object-attributes" 32 | } 33 | } 34 | } 35 | }, 36 | "cases": [ 37 | { 38 | "given": { 39 | "http": { 40 | "method": "GET", 41 | "requestUri": "/2014-01-01/hostedzone" 42 | }, 43 | "input": { 44 | "shape": "GetObjectAttributesRequest" 45 | }, 46 | "name": "GetObjectAttributes" 47 | }, 48 | "params": { 49 | "ObjectAttributes": [ 50 | "Checksum", 51 | "ObjectParts" 52 | ] 53 | }, 54 | "serialized": { 55 | "method": "GET", 56 | "uri": "/2014-01-01/hostedzone", 57 | "headers": {"x-amz-object-attributes": "Checksum,ObjectParts"} 58 | } 59 | } 60 | ] 61 | } 62 | ] 63 | 64 | 65 | -------------------------------------------------------------------------------- /test/resources/cognitect/protocols/output/json.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "No output", 4 | "metadata": { 5 | "metadata": { 6 | "protocol": "json" 7 | }, 8 | "shapes": { 9 | "OutputShape": { 10 | "type": "structure", 11 | "members": { 12 | "StrType": { 13 | "shape": "StrType" 14 | } 15 | } 16 | }, 17 | "StrType": { 18 | "type": "string" 19 | } 20 | }, 21 | "cases": [ 22 | { 23 | "given": { 24 | "name": "OperationName" 25 | }, 26 | "result": {}, 27 | "response": { 28 | "status_code": 200, 29 | "headers": {} 30 | } 31 | } 32 | ] 33 | } 34 | }, 35 | { 36 | "description": "Timestamp members with doubles", 37 | "metadata": { 38 | "protocol": "json" 39 | }, 40 | "shapes": { 41 | "OutputShape": { 42 | "type": "structure", 43 | "members": { 44 | "TimeArg": { 45 | "shape": "TimestampType" 46 | } 47 | } 48 | }, 49 | "TimestampType": { 50 | "type": "timestamp" 51 | } 52 | }, 53 | "cases": [ 54 | { 55 | "given": { 56 | "output": { 57 | "shape": "OutputShape" 58 | }, 59 | "name": "OperationName" 60 | }, 61 | "result": { 62 | "TimeArg": 1398796238 63 | }, 64 | "response": { 65 | "status_code": 200, 66 | "headers": {}, 67 | "body": "{\"TimeArg\": 1.398796238E9}" 68 | } 69 | } 70 | ] 71 | } 72 | ] 73 | -------------------------------------------------------------------------------- /test/resources/cognitect/protocols/output/rest-json.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "No output", 4 | "metadata": { 5 | "metadata": { 6 | "protocol": "rest-json" 7 | }, 8 | "shapes": { 9 | "OutputShape": { 10 | "type": "structure", 11 | "members": { 12 | "StrType": { 13 | "shape": "StrType" 14 | } 15 | } 16 | }, 17 | "StrType": { 18 | "type": "string" 19 | } 20 | }, 21 | "cases": [ 22 | { 23 | "given": { 24 | "name": "OperationName" 25 | }, 26 | "result": {}, 27 | "response": { 28 | "status_code": 200, 29 | "headers": {} 30 | } 31 | } 32 | ] 33 | } 34 | }, 35 | { 36 | "description": "Named locations in JSON body", 37 | "metadata": { 38 | "protocol": "rest-json" 39 | }, 40 | "shapes": { 41 | "OutputShape": { 42 | "type": "structure", 43 | "payload": "Data", 44 | "members": { 45 | "Data": { 46 | "shape": "BodyStructure" 47 | } 48 | } 49 | }, 50 | "BodyStructure": { 51 | "type": "structure", 52 | "members": { 53 | "Foo": { 54 | "shape": "StringType", 55 | "locationName": "FOO" 56 | } 57 | } 58 | }, 59 | "StringType": { 60 | "type": "string" 61 | } 62 | }, 63 | "cases": [ 64 | { 65 | "given": { 66 | "output": { 67 | "shape": "OutputShape" 68 | }, 69 | "name": "OperationName" 70 | }, 71 | "result": { 72 | "Data": { 73 | "Foo": "abc" 74 | } 75 | }, 76 | "response": { 77 | "status_code": 200, 78 | "headers": {}, 79 | "body": "{\"FOO\": \"abc\"}" 80 | } 81 | } 82 | ] 83 | } 84 | ] 85 | -------------------------------------------------------------------------------- /test/resources/cognitect/protocols/output/rest-xml.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "Single text node", 4 | "metadata": {"protocol": "rest-xml"}, 5 | "shapes": { 6 | "OutputShape": { 7 | "type": "structure", 8 | "members": { 9 | "LocationConstraint": { 10 | "shape": "StringType" 11 | } 12 | } 13 | }, 14 | "StringType": { 15 | "type": "string" 16 | } 17 | }, 18 | "cases": [ 19 | { 20 | "given": { 21 | "output": { 22 | "shape": "OutputShape" 23 | }, 24 | "name": "OperationName" 25 | }, 26 | "result": { 27 | "LocationConstraint": "us-west-1" 28 | }, 29 | "response": { 30 | "status_code": 200, 31 | "body": "us-west-1" 32 | } 33 | } 34 | ] 35 | }, 36 | { 37 | "description": "Single string in payload", 38 | "metadata": {"protocol": "rest-xml"}, 39 | "shapes": { 40 | "OutputShape": { 41 | "type": "structure", 42 | "members": { 43 | "Data": { 44 | "shape": "DataShape" 45 | } 46 | }, 47 | "payload" : "Data" 48 | }, 49 | "DataShape": { 50 | "type": "string" 51 | } 52 | }, 53 | "cases": [ 54 | { 55 | "given": { 56 | "output": { 57 | "shape": "OutputShape" 58 | }, 59 | "name": "OperationName" 60 | }, 61 | "result": { 62 | "Data": "{\"a\":1}" 63 | }, 64 | "response": { 65 | "status_code": 200, 66 | "body": "{\"a\":1}" 67 | } 68 | } 69 | ] 70 | } 71 | ] 72 | -------------------------------------------------------------------------------- /test/src/cognitect/aws/api_test.clj: -------------------------------------------------------------------------------- 1 | (ns cognitect.aws.api-test 2 | (:require [clojure.datafy :as datafy] 3 | [clojure.test :as t :refer [deftest is testing]] 4 | [cognitect.aws.client.api :as aws] 5 | [cognitect.aws.client.protocol :as client.protocol] 6 | [cognitect.aws.client.shared :as shared] 7 | [cognitect.aws.http :as http])) 8 | 9 | (deftest test-underlying-http-client 10 | (testing "defaults to shared client" 11 | (let [clients (repeatedly 5 #(aws/client {:api :s3 :region "us-east-1"}))] 12 | (is (= #{(shared/http-client)} 13 | (into #{(shared/http-client)} 14 | (->> clients (map (fn [c] (-> c client.protocol/-get-info :http-client)))))))))) 15 | 16 | (deftest test-datafy 17 | (let [client (aws/client {:api :s3}) 18 | data (datafy/datafy client)] 19 | (is (= "s3" (:api data))) 20 | (is (map? (:service data))) 21 | (is (map? (:metadata (:service data)))) 22 | (is (map? (:endpoint data))) 23 | (is (string? (:region data))) 24 | (is (map? (:ops data))) 25 | (is (map? (:endpoint data))))) 26 | 27 | (deftest test-stop 28 | (let [call-count (atom 0) 29 | default (aws/client {:api :s3 :region "us-east-1"}) 30 | supplied-shared (aws/client {:api :s3 :region "us-east-1" 31 | :http-client (shared/http-client)}) 32 | supplied-unshared (aws/client {:api :s3 :region "us-east-1" 33 | :http-client (http/resolve-http-client nil)})] 34 | (with-redefs [http/stop (fn [_] (swap! call-count inc))] 35 | (testing "has no effect when aws-client uses the default shared http-client" 36 | (aws/stop default) 37 | (is (zero? @call-count))) 38 | (testing "has no effect when user supplies the shared http-client" 39 | (aws/stop supplied-shared) 40 | (is (zero? @call-count))) 41 | (testing "forwards to http/stop when user supplies a different http-client" 42 | (aws/stop supplied-unshared) 43 | (is (= 1 @call-count)))) 44 | ;; now actually stop the aws-client with the non-shared http-client 45 | (aws/stop supplied-unshared))) 46 | -------------------------------------------------------------------------------- /test/src/cognitect/aws/client/shared_test.clj: -------------------------------------------------------------------------------- 1 | (ns cognitect.aws.client.shared-test 2 | (:require [clojure.test :as t :refer [deftest is testing]] 3 | [cognitect.aws.client.api :as aws] 4 | [cognitect.aws.client.shared :as shared] 5 | [cognitect.aws.http :as http])) 6 | 7 | (deftest test-shared-delays-are-not-realized-unnecessarily 8 | ;; issue 262 9 | (testing "Creating a client with custom attributes does not deref the default delayed shared resources." 10 | ;; As a precondition of this test, the delays must be unrealized. 11 | (require 'cognitect.aws.client.shared :reload) 12 | (aws/client {:api :s3 13 | :http-client (reify http/HttpClient) 14 | :region-provider :test-provider 15 | :credentials-provider :test-provider}) 16 | (is (not (realized? @#'shared/shared-http-client))) 17 | (is (not (realized? @#'shared/shared-region-provider))) 18 | (is (not (realized? @#'shared/shared-credentials-provider))))) 19 | -------------------------------------------------------------------------------- /test/src/cognitect/aws/config_test.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns cognitect.aws.config-test 5 | (:require [clojure.test :refer [deftest is]] 6 | [clojure.java.io :as io] 7 | [cognitect.aws.config :as config])) 8 | 9 | (deftest read-config 10 | (let [config (config/parse (io/resource ".aws/config"))] 11 | (is (= {"region" "us-west-1"} 12 | (get config "tardigrade"))) 13 | (is (= {"s3" {"max_concurrent_requests" "10" 14 | "max_queue_size" "1000" 15 | "s3_key" "s3_val"} 16 | "region" "eu-west-1" 17 | "foo.bar" "baz"} 18 | (get config "nested"))) 19 | (is (re-matches 20 | #"^awsprocesscreds.*specialness$" 21 | (get-in config ["waterbear" "credential_process"]))) 22 | (is (= "FQoG/Ehj40mh/xf0TR+xLl+cp/xGWC+haIy+fJh6/fD+LFW=" 23 | (get-in config ["temp-credentials" "aws_session_token"]))))) -------------------------------------------------------------------------------- /test/src/cognitect/aws/ec2_metadata_utils_test.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns cognitect.aws.ec2-metadata-utils-test 5 | (:require [clojure.core.async :as a] 6 | [clojure.test :refer [deftest is testing]] 7 | [cognitect.aws.ec2-metadata-utils :as ec2-metadata-utils] 8 | [cognitect.aws.http :as http] 9 | [cognitect.aws.util :as u]) 10 | (:import [java.net URI])) 11 | 12 | 13 | (deftest returns-nil-after-retries 14 | ;; Using a mock http client that keeps track of the number of http requests and always returns a 15 | ;; busy response, assert that the expected number of requests were made and that ultimately a nil 16 | ;; response was returned. 17 | (let [expected-submit-count 4 ;; Expected to equal `max-retries` plus one. 18 | actual-submit-count (atom 0) 19 | response-chan (doto (a/promise-chan) 20 | (a/>!! {:cognitect.anomalies/category :cognitect.anomalies/busy})) 21 | mock-http-client (reify http/HttpClient 22 | (-submit [_ _request _channel] 23 | (swap! actual-submit-count inc) 24 | response-chan) 25 | (-stop [_]))] 26 | (is (nil? (ec2-metadata-utils/get-ec2-instance-region mock-http-client))) 27 | (is (= expected-submit-count @actual-submit-count)))) 28 | 29 | (deftest request-map 30 | (testing "server-port" 31 | (is (= 443 (:server-port (#'ec2-metadata-utils/request-map (URI/create "https://169.254.169.254"))))) 32 | (is (= 80 (:server-port (#'ec2-metadata-utils/request-map (URI/create "http://169.254.169.254"))))) 33 | (is (= 8081 (:server-port (#'ec2-metadata-utils/request-map (URI/create "http://169.254.169.254:8081")))))) 34 | (testing "auth token" 35 | (is (nil? (get-in (#'ec2-metadata-utils/request-map (URI/create "http://localhost")) [:headers "Authorization"]))) 36 | (with-redefs [u/getenv {"AWS_CONTAINER_AUTHORIZATION_TOKEN" "this-is-the-token"}] 37 | (is (#{"this-is-the-token"} (get-in (#'ec2-metadata-utils/request-map (URI/create "http://localhost")) [:headers "Authorization"])))))) 38 | -------------------------------------------------------------------------------- /test/src/cognitect/aws/endpoint_test.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns cognitect.aws.endpoint-test 5 | (:require [clojure.test :refer [deftest is testing]] 6 | [cognitect.aws.endpoint :as endpoint])) 7 | 8 | (def endpoints-excerpt 9 | {:partitions 10 | [{:defaults 11 | {:hostname "{service}.{region}.{dnsSuffix}" 12 | :protocols ["https"] 13 | :signatureVersions ["v4"]} 14 | :dnsSuffix "amazonaws.com" 15 | :partition "aws" 16 | :partitionName "AWS Standard" 17 | :regionRegex "^(us|eu|ap|sa|ca)\\-\\w+\\-\\d+$" 18 | :regions 19 | {:us-east-1 {:description "US East (N. Virginia)"}} 20 | :services 21 | {:ec2 22 | {:defaults {:protocols ["http" "https"]} 23 | :endpoints 24 | {:us-east-1 {}}} 25 | :marketplacecommerceanalytics {:endpoints {:us-east-1 {}}} 26 | :iam 27 | {:endpoints 28 | {:aws-global 29 | {:credentialScope {:region "us-east-1"} 30 | :hostname "iam.amazonaws.com"}} 31 | :isRegionalized false 32 | :partitionEndpoint "aws-global"}}}]}) 33 | 34 | (deftest test-resolve-endpoints 35 | (testing "resolves regionalized endpoints" 36 | (with-redefs [endpoint/resolver (constantly endpoints-excerpt)] 37 | (is (= "ec2.us-east-1.amazonaws.com" (:hostname (endpoint/resolve* :ec2 :us-east-1)))))) 38 | (testing "resolves global endpoints" 39 | (with-redefs [endpoint/resolver (constantly endpoints-excerpt)] 40 | (is (= "iam.amazonaws.com" 41 | (:hostname (endpoint/resolve* :iam :us-east-1)))))) 42 | (testing "uses defaults to resolve unspecified endpoints" 43 | (with-redefs [endpoint/resolver (constantly endpoints-excerpt)] 44 | (is (= "i-do-not-exist.us-east-1.amazonaws.com" 45 | (:hostname (endpoint/resolve* :i-do-not-exist :us-east-1))))))) 46 | -------------------------------------------------------------------------------- /test/src/cognitect/aws/generators.clj: -------------------------------------------------------------------------------- 1 | (ns cognitect.aws.generators 2 | (:require [clojure.string :as str] 3 | [clojure.test.check.generators :as gen] 4 | [cognitect.aws.util :as util])) 5 | 6 | ;; see cognitect.aws.protocols.rest/serialize-uri 7 | ;; we want to mimic inputs to cognitect.aws.signers/sign-http-request 8 | (defn ^:private serialize-path-part 9 | [part] 10 | (-> part 11 | (util/url-encode) 12 | (str/replace "%2F" "/") 13 | (str/replace "%7E" "~"))) 14 | 15 | (defn gen-service 16 | [sig-ver] 17 | (gen/let [service-name (gen/such-that seq gen/string-alphanumeric)] 18 | {:metadata {:signatureVersion sig-ver 19 | :signingName service-name}})) 20 | 21 | (def gen-request 22 | (gen/let [host (gen/fmap #(str % ".com") (gen/such-that seq gen/string-alphanumeric)) 23 | path-parts (gen/vector (gen/fmap serialize-path-part (gen/such-that (complement str/blank?) gen/string-ascii)) 1 10) 24 | path-separator (gen/elements ["/" "//"]) 25 | query-ks (gen/vector (gen/such-that seq gen/string-alphanumeric)) 26 | query-vs (gen/vector (gen/such-that seq gen/string-alphanumeric) (count query-ks)) 27 | method (gen/elements [:get :post]) 28 | ;; https://github.com/aws/aws-sdk-java-v2/blob/61d16e0/core/auth/src/main/java/software/amazon/awssdk/auth/signer/internal/SignerKey.java#L44 29 | ;; date will be >1 day past epoch and <= today 30 | ;; 1735838904634 == 2025-01-02 31 | epoch (gen/large-integer* {:min 86400000 :max 1735838904634}) 32 | body gen/string] 33 | {:request-method method 34 | :body (.getBytes ^String body "UTF-8") 35 | :headers {"x-amz-date" (util/format-date util/x-amz-date-format (java.util.Date. epoch)) 36 | "host" host} 37 | :uri (str path-separator 38 | (str/join path-separator path-parts) 39 | (when (seq query-ks) 40 | (str "?" (str/join "&" (map #(str %1 "=" %2) 41 | query-ks 42 | query-vs)))))})) 43 | -------------------------------------------------------------------------------- /test/src/cognitect/aws/http/default_test.clj: -------------------------------------------------------------------------------- 1 | (ns cognitect.aws.http.default-test 2 | (:require [clojure.string :as str] 3 | [clojure.test :refer [deftest is]] 4 | [cognitect.aws.http.default :as default-http-client] 5 | [cognitect.aws.test.utils :as utils])) 6 | 7 | (deftest http-client-defaults-parity-with-cognitect-client 8 | (let [client (default-http-client/create) 9 | client-class-name (.getName (class client)) 10 | java-version (utils/major-java-version) 11 | expected (if (< java-version 11) 12 | "cognitect.aws.http.cognitect$create" 13 | "cognitect.aws.http.java$create")] 14 | ; NOTE: this is matched via starts-with?, because the returned client 15 | ; is created via reify, and the class name is not fully predictable 16 | ; (e.g. cognitect.aws.http.java$create$reify__11484) 17 | (is (str/starts-with? client-class-name expected)))) 18 | -------------------------------------------------------------------------------- /test/src/cognitect/aws/http_test.clj: -------------------------------------------------------------------------------- 1 | (ns cognitect.aws.http-test 2 | (:require [clojure.java.io :as io] 3 | [clojure.test :refer :all] 4 | [cognitect.aws.http :as aws-http])) 5 | 6 | (deftest configured-client-test 7 | (testing "Returns the default http client" 8 | (is (= 'cognitect.aws.http.default/create 9 | (#'aws-http/configured-client)))) 10 | 11 | (testing "Returns new http client on cognitect_aws_http.edn file" 12 | (spit (io/file "test/resources/cognitect_aws_http.edn") 13 | "{:constructor-var cognitect.aws.http.java/create}") 14 | 15 | (is (= 'cognitect.aws.http.java/create 16 | (#'aws-http/configured-client))) 17 | 18 | (is (= true 19 | (io/delete-file "test/resources/cognitect_aws_http.edn" :failed)) 20 | "Accidentally failed to delete file"))) 21 | 22 | (deftest uri-authority-test 23 | (testing "http scheme, default port" 24 | (is (= "a-server.example.com" (aws-http/uri-authority :http "a-server.example.com" 80))) 25 | (is (= "a-server.example.com" (aws-http/uri-authority :http "A-sErvEr.example.com" nil))) 26 | (is (= "a-server.example.com" (aws-http/uri-authority "HTTP" "a-server.example.com" 80))) 27 | (is (= "a-server.example.com" (aws-http/uri-authority "http" "a-server.example.com" nil)))) 28 | 29 | (testing "https scheme, default port" 30 | (is (= "a-server.example.com" (aws-http/uri-authority :https "a-server.example.com" 443))) 31 | (is (= "a-server.example.com" (aws-http/uri-authority :https "A-sErvEr.example.com" nil))) 32 | (is (= "a-server.example.com" (aws-http/uri-authority "https" "a-server.example.com" 443))) 33 | (is (= "a-server.example.com" (aws-http/uri-authority "HTTPs" "a-server.example.com" nil)))) 34 | 35 | (testing "http scheme, custom port" 36 | (is (= "a-server.example.com:8080" (aws-http/uri-authority :http "a-server.example.com" 8080))) 37 | (is (= "a-server.example.com:4080" (aws-http/uri-authority :http "a-server.example.com" 4080))) 38 | (is (= "a-server.example.com:443" (aws-http/uri-authority :http "a-server.example.com" 443))) 39 | (is (= "a-server.example.com:1" (aws-http/uri-authority :http "a-server.example.com" 1)))) 40 | 41 | (testing "https scheme, custom port" 42 | (is (= "a-server.example.com:8080" (aws-http/uri-authority :https "a-server.example.com" 8080))) 43 | (is (= "a-server.example.com:4443" (aws-http/uri-authority :https "a-server.example.com" 4443))) 44 | (is (= "a-server.example.com:80" (aws-http/uri-authority :https "a-server.example.com" 80))) 45 | (is (= "a-server.example.com:1" (aws-http/uri-authority :https "a-server.example.com" 1))))) 46 | -------------------------------------------------------------------------------- /test/src/cognitect/aws/integration/error_codes_test.clj: -------------------------------------------------------------------------------- 1 | (ns cognitect.aws.integration.error-codes-test 2 | (:require [clojure.test :refer [deftest is testing use-fixtures]] 3 | [cognitect.aws.client.api :as aws] 4 | [cognitect.aws.integration.fixtures :as fixtures])) 5 | 6 | (use-fixtures :once fixtures/ensure-test-profile) 7 | 8 | (deftest ^:integration error-codes-for-protocols 9 | (testing "rest-xml" 10 | (is (= "NoSuchBucket" 11 | (:cognitect.aws.error/code 12 | (aws/invoke (aws/client {:api :s3}) 13 | {:op :GetObject 14 | :request {:Bucket "i-do-not-exist" 15 | :Key "neither-do-i.txt"}}))))) 16 | 17 | (testing "rest-json" 18 | (is (= "ValidationException" 19 | (:cognitect.aws.error/code 20 | (aws/invoke (aws/client {:api :lambda}) 21 | {:op :CreateFunction}))))) 22 | 23 | (testing "ec2" 24 | (is (= "MissingParameter" 25 | (:cognitect.aws.error/code 26 | (aws/invoke (aws/client {:api :ec2}) 27 | {:op :CreateVolume}))))) 28 | 29 | (testing "query" 30 | (is (= "ValidationError" 31 | (:cognitect.aws.error/code 32 | (aws/invoke (aws/client {:api :autoscaling}) 33 | {:op :DescribeTrafficSources}))))) 34 | 35 | (testing "json" 36 | (is (= "ValidationException" 37 | (:cognitect.aws.error/code 38 | (aws/invoke (aws/client {:api :ssm}) 39 | {:op :DescribePatchGroupState})))))) 40 | -------------------------------------------------------------------------------- /test/src/cognitect/aws/integration/fixtures.clj: -------------------------------------------------------------------------------- 1 | (ns cognitect.aws.integration.fixtures) 2 | 3 | (defn ensure-test-profile 4 | "Ensure AWS_PROFILE env var is aws-api-test 5 | 6 | To use it, add this at beginning of your test namespace: 7 | 8 | (use-fixtures :once aux.integration/ensure-test-profile)" 9 | [f] 10 | (if (= "aws-api-test" (System/getenv "AWS_PROFILE")) 11 | (f) 12 | (println "AWS_PROFILE is not configured, so not running integration tests."))) 13 | -------------------------------------------------------------------------------- /test/src/cognitect/aws/interceptors_test.clj: -------------------------------------------------------------------------------- 1 | (ns cognitect.aws.interceptors-test 2 | (:require [clojure.test :refer [deftest is]] 3 | [cognitect.aws.interceptors :as interceptors])) 4 | 5 | (deftest test-apigatewaymanagementapi 6 | (is (= "prefixsuffix" 7 | (:uri 8 | (interceptors/modify-http-request {:metadata {:uid "apigatewaymanagementapi"}} 9 | {:op :PostToConnection 10 | :request {:ConnectionId "suffix"}} 11 | {:uri "prefix"}))))) -------------------------------------------------------------------------------- /test/src/cognitect/aws/jdk.clj: -------------------------------------------------------------------------------- 1 | (ns cognitect.aws.jdk 2 | (:require [clojure.java.io :as io] 3 | [clojure.string :as str] 4 | [cognitect.aws.util :as util]) 5 | (:import [java.net URI] 6 | [com.amazonaws DefaultRequest] 7 | [com.amazonaws.auth AWS4Signer] 8 | [com.amazonaws.auth BasicAWSCredentials] 9 | [com.amazonaws.http HttpMethodName] 10 | [com.amazonaws.services.s3.internal AWSS3V4Signer] 11 | [com.amazonaws.services.s3.request S3HandlerContextKeys])) 12 | 13 | (defn ^:private ->http-method 14 | [request] 15 | (HttpMethodName/fromValue (name (:request-method request)))) 16 | 17 | (defn ^:private ->x-amz-date 18 | [request] 19 | (->> (get-in request [:headers "x-amz-date"]) 20 | (util/parse-date util/x-amz-date-format))) 21 | 22 | (defn ^:private ->basic-credentials 23 | [credentials] 24 | (BasicAWSCredentials. (:aws/access-key-id credentials) 25 | (:aws/secret-access-key credentials))) 26 | 27 | (defn ^:private ->default-request 28 | [service request] 29 | (let [[path query] (str/split (:uri request) #"\?" 2) 30 | req (doto (DefaultRequest. (get-in service [:metadata :signingName])) 31 | (.setHttpMethod (->http-method request)) 32 | (.setContent (io/input-stream (:body request))) 33 | (.setEndpoint (URI. (str "https://" (get-in request [:headers "host"])))) 34 | (.setResourcePath (str/replace path #"^//+" "/")))] 35 | (when (seq query) 36 | (doseq [[k v] (map #(str/split % #"=") (str/split query #"&"))] 37 | (.addParameter req k v))) 38 | req)) 39 | 40 | (defn v4-jdk-signed-request 41 | [service credentials request] 42 | (let [basic-credentials (->basic-credentials credentials) 43 | req (->default-request service request) 44 | signer (doto (AWS4Signer.) 45 | (.setServiceName (get-in service [:metadata :signingName])) 46 | (.setOverrideDate (->x-amz-date request)))] 47 | (.sign signer req basic-credentials) 48 | req)) 49 | 50 | (defn s3v4-jdk-signed-request 51 | [service credentials request] 52 | (let [basic-credentials (->basic-credentials credentials) 53 | req (doto (->default-request service request) 54 | (.addHandlerContext S3HandlerContextKeys/IS_PAYLOAD_SIGNING_ENABLED true) 55 | (.addHandlerContext S3HandlerContextKeys/IS_CHUNKED_ENCODING_DISABLED true)) 56 | signer (doto (AWSS3V4Signer.) 57 | (.setServiceName (get-in service [:metadata :signingName])) 58 | (.setOverrideDate (->x-amz-date request)))] 59 | (.sign signer req basic-credentials) 60 | req)) 61 | -------------------------------------------------------------------------------- /test/src/cognitect/aws/protocols/rest_test.clj: -------------------------------------------------------------------------------- 1 | (ns cognitect.aws.protocols.rest-test 2 | (:require [clojure.test :refer [deftest is testing]] 3 | [cognitect.aws.protocols.rest :as protocols.rest])) 4 | 5 | (deftest test-serialize-url 6 | (testing "ensures no double-slash" 7 | (is (= "/a/b/c/d/e/f" 8 | (protocols.rest/serialize-uri "/{Foo+}/{Bar+}" {} {:Foo "a/b/c" :Bar "d/e/f"}) 9 | (protocols.rest/serialize-uri "/{Foo+}/{Bar+}" {} {:Foo "a/b/c" :Bar "/d/e/f"}) 10 | (protocols.rest/serialize-uri "/{Foo+}/{Bar+}" {} {:Foo "/a/b/c" :Bar "/d/e/f"}) 11 | (protocols.rest/serialize-uri "/{Foo+}/{Bar+}" {} {:Foo "/a/b/c" :Bar "d/e/f"})))) 12 | 13 | (testing "throws when required key is missing" 14 | (is (thrown-with-msg? Exception 15 | #"missing" 16 | (protocols.rest/serialize-uri "/{Bucket}" {:required ["Bucket"]} {}))) 17 | (is (thrown-with-msg? Exception 18 | #"missing" 19 | (protocols.rest/serialize-uri "/{Bucket}" {:required ["Bucket"]} {:BucketName "wrong key"}))) 20 | (is (thrown-with-msg? Exception 21 | #"missing" 22 | (protocols.rest/serialize-uri "/{Bucket}/{Key+}" {:required ["Bucket" "Key"]} {:Bucket "foo"})))) 23 | 24 | (testing "serializes longs" 25 | (is (= "/a/1/b" 26 | (protocols.rest/serialize-uri "/a/{count}/b" {:type "structure" 27 | :members {:Count {:shape "__long", :location "uri", :locationName "count"}} 28 | :required ["Count"]} 29 | {:count 1}))))) 30 | -------------------------------------------------------------------------------- /test/src/cognitect/aws/region_test.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns cognitect.aws.region-test 5 | (:require [clojure.test :refer [deftest is testing]] 6 | [clojure.java.io :as io] 7 | [clojure.core.async :as a] 8 | [cognitect.aws.client.shared :as shared] 9 | [cognitect.aws.region :as region] 10 | [cognitect.aws.util :as u] 11 | [cognitect.aws.test.utils :as tu] 12 | [cognitect.aws.ec2-metadata-utils :as ec2-metadata-utils] 13 | [cognitect.aws.test.ec2-metadata-utils-server :as ec2-metadata-utils-test-server])) 14 | 15 | (deftest chain-region-provider-test 16 | (let [r "us-east-1" 17 | p1 (reify region/RegionProvider (region/fetch [_])) 18 | p2 (reify region/RegionProvider (region/fetch [_] r))] 19 | (testing "provider calls each provider until one returns a region" 20 | (is (= r (region/fetch (region/chain-region-provider [p1 p2]))))) 21 | (testing "provider throws if none of the providers returns a region." 22 | (is (thrown-with-msg? Exception #"No region found" (region/fetch (region/chain-region-provider [p1]))))))) 23 | 24 | (deftest profile-region-provider-test 25 | (let [config (io/file (io/resource ".aws/config"))] 26 | (testing "reads the default profile correctly." 27 | (is (= "us-east-1" 28 | (region/fetch (region/profile-region-provider "default" config))))) 29 | (testing "reads a custom profile correctly." 30 | (is (= "us-west-1" 31 | (region/fetch (region/profile-region-provider "tardigrade" config))))) 32 | 33 | (testing "uses env vars and sys props for credentials file location and profile" 34 | (with-redefs [u/getenv (tu/stub-getenv {"AWS_CONFIG_FILE" config})] 35 | (is (= "us-east-1" (region/fetch (region/profile-region-provider))))) 36 | (with-redefs [u/getenv (tu/stub-getenv {"AWS_CONFIG_FILE" config 37 | "AWS_PROFILE" "tardigrade"})] 38 | (is (= "us-west-1" (region/fetch (region/profile-region-provider))))) 39 | (with-redefs [u/getenv (tu/stub-getenv {"AWS_CONFIG_FILE" config}) 40 | u/getProperty (tu/stub-getProperty {"aws.profile" "tardigrade"})] 41 | (is (= "us-west-1" (region/fetch (region/profile-region-provider)))))))) 42 | 43 | (deftest instance-region-provider-test 44 | (testing "provider caches the fetched value" 45 | (ec2-metadata-utils-test-server/with-test-server 46 | (let [orig-get-region-fn ec2-metadata-utils/get-ec2-instance-region 47 | request-counter (atom 0) 48 | fetch-counter (atom 0)] 49 | (with-redefs [ec2-metadata-utils/get-ec2-instance-region 50 | (fn [http imdsv2-token] 51 | (swap! fetch-counter inc) 52 | (orig-get-region-fn http imdsv2-token))] 53 | (let [num-requests 10 54 | p (region/instance-region-provider (shared/http-client)) 55 | chans (repeatedly num-requests 56 | #(do 57 | (swap! request-counter inc) 58 | (region/fetch-async p)))] 59 | (is (apply = "us-east-1" (map #(a/!! c {:this :map}) 13 | response-ch (retry/with-retry 14 | (constantly c) 15 | (a/promise-chan) 16 | (constantly false) 17 | (constantly nil))] 18 | (a/!! c {:this :map}) 25 | response-ch (retry/with-retry 26 | (constantly c) 27 | (a/promise-chan) 28 | (constantly true) 29 | (constantly nil))] 30 | (a/!! c {:cognitect.anomalies/category :cognitect.anomalies/busy 36 | :test/attempt-number 1}) 37 | (a/>!! c {:cognitect.anomalies/category :cognitect.anomalies/busy 38 | :test/attempt-number 2}) 39 | (a/>!! c {:cognitect.anomalies/category :cognitect.anomalies/busy 40 | :test/attempt-number 3}) 41 | (a/!! c {:cognitect.anomalies/category :cognitect.anomalies/unavailable 51 | :test/attempt-number 1}) 52 | (a/>!! c {:cognitect.anomalies/category :cognitect.anomalies/unavailable 53 | :test/attempt-number 2}) 54 | (a/>!! c {:cognitect.anomalies/category :cognitect.anomalies/unavailable 55 | :test/attempt-number 3}) 56 | (a/!! c {:cognitect.anomalies/category :cognitect.anomalies/busy 66 | :test/attempt-number 1}) 67 | (a/>!! c {:cognitect.anomalies/category :cognitect.anomalies/busy 68 | :test/attempt-number 2}) 69 | (a/>!! c {:test/attempt-number 3}) 70 | (a/ server-stop-fn meta :local-port)] 107 | (try 108 | (System/setProperty ec2-metadata-utils/ec2-metadata-service-override-system-property 109 | (str "http://localhost:" test-server-port)) 110 | (binding [*test-server-port* test-server-port] 111 | (f)) 112 | (finally 113 | (server-stop-fn) 114 | (System/clearProperty ec2-metadata-utils/ec2-metadata-service-override-system-property))))) 115 | 116 | (defmacro with-test-server 117 | [& body] 118 | `(with-test-server* {} (fn [] ~@body))) 119 | 120 | (defmacro with-IMDSv2-test-server 121 | [& body] 122 | `(with-test-server* {::IMDSv2-enabled? true} (fn [] ~@body))) 123 | 124 | 125 | (comment 126 | 127 | (def stop-fn (start 0 {})) 128 | 129 | (stop-fn)) 130 | -------------------------------------------------------------------------------- /test/src/cognitect/aws/test/utils.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Cognitect, Inc. 2 | ;; All rights reserved. 3 | 4 | (ns cognitect.aws.test.utils 5 | (:require [clojure.string :as str])) 6 | 7 | (defn stub-getenv [env] 8 | (fn 9 | ([] env) 10 | ([k] (get env k)))) 11 | 12 | (defn stub-getProperty [props] 13 | (fn [k] 14 | (get props k))) 15 | 16 | (defn major-java-version [] 17 | (-> (System/getProperty "java.version") (str/split #"\.") first read-string)) 18 | 19 | (defmacro when-java11 [& body] 20 | (when (<= 11 (major-java-version)) 21 | `(do ~@body))) 22 | -------------------------------------------------------------------------------- /test/src/cognitect/aws/util_test.clj: -------------------------------------------------------------------------------- 1 | (ns cognitect.aws.util-test 2 | (:require [clojure.test :as t :refer [deftest is testing]] 3 | [clojure.java.io :as io] 4 | [cognitect.aws.util :as util]) 5 | (:import [java.nio ByteBuffer] 6 | [java.util Random] 7 | [java.util Arrays])) 8 | 9 | (deftest test-input-stream->byte-array 10 | (is (= "hi" (slurp (util/input-stream->byte-array (io/input-stream (.getBytes "hi")))))) 11 | (testing "works with a 1mb array" 12 | (let [input (byte-array (int (Math/pow 2 20))) 13 | rng (Random.) 14 | _ (.nextBytes rng input) 15 | output (util/input-stream->byte-array (io/input-stream input))] 16 | (is (Arrays/equals ^bytes input ^bytes output))))) 17 | 18 | (deftest test-bbuff->byte-array 19 | (testing "return ByteBuffer starting at the current position" 20 | (let [bb (ByteBuffer/wrap (.getBytes "bye")) 21 | positioned-bb (-> (.getBytes "hi bye") 22 | ByteBuffer/wrap 23 | (.position 3)) 24 | direct-bb (-> (ByteBuffer/allocateDirect 10) 25 | (.put (ByteBuffer/wrap (.getBytes "bye"))) 26 | .flip)] 27 | (is (= (seq (util/bbuff->byte-array bb)) 28 | (seq (util/bbuff->byte-array positioned-bb)) 29 | (seq (util/bbuff->byte-array direct-bb))))))) 30 | 31 | (deftest test-sha-256 32 | (testing "returns sha for empty string if given nil" 33 | (is (= (seq (util/sha-256 nil)) 34 | (seq (util/sha-256 "")) 35 | (seq (util/sha-256 (.getBytes "")))))) 36 | (testing "accepts string, byte array, or ByteBuffer" 37 | (is (= (seq (util/sha-256 "hi")) 38 | (seq (util/sha-256 (.getBytes "hi"))) 39 | (seq (util/sha-256 (ByteBuffer/wrap (.getBytes "hi"))))))) 40 | (testing "does not consume a ByteBuffer" 41 | (let [bb (ByteBuffer/wrap (.getBytes "hi"))] 42 | (util/sha-256 bb) 43 | (is (= "hi" (util/bbuf->str bb))))) 44 | (testing "return ByteBuffer content starting at current the position" 45 | (let [bb (ByteBuffer/wrap (.getBytes "bye")) 46 | positioned-bb (-> (.getBytes "hi bye") 47 | ByteBuffer/wrap 48 | (.position 3)) 49 | direct-bb (-> (ByteBuffer/allocateDirect 10) 50 | (.put (ByteBuffer/wrap (.getBytes "bye"))) 51 | .flip)] 52 | (is (= (seq (util/sha-256 bb)) 53 | (seq (util/sha-256 positioned-bb)) 54 | (seq (util/sha-256 direct-bb))))))) 55 | 56 | (deftest test-md5 57 | (testing "Respects positioned ByteBuffer arrays and direct ByteBuffers" 58 | (let [bb (ByteBuffer/wrap (.getBytes "bye")) 59 | positioned-bb (-> (.getBytes "hi bye") 60 | ByteBuffer/wrap 61 | (.position 3)) 62 | direct-bb (-> (ByteBuffer/allocateDirect 10) 63 | (.put (ByteBuffer/wrap (.getBytes "bye"))) 64 | .flip)] 65 | (is (= (seq (util/md5 bb)) 66 | (seq (util/md5 positioned-bb)) 67 | (seq (util/md5 direct-bb))))))) 68 | 69 | (deftest test-xml-read 70 | (testing "removes whitespace-only nodes, preserving whitespace in single text nodes" 71 | (let [parsed (util/xml-read " 72 | outer-value 73 | 74 | inner-value 75 | 76 | ")] 77 | (is (= 2 (count (-> parsed :content)))) 78 | (is (re-matches #"\n\s+outer-value\s+" (-> parsed :content first))) 79 | (is (= 1 (count (-> parsed :content last :content)))) 80 | (is (re-matches #"\n\s+inner-value\s+" (-> parsed :content last :content first)))))) 81 | 82 | (deftest hex-encode 83 | (is (= (util/hex-encode (byte-array (range -128 128))) 84 | "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f"))) 85 | 86 | (comment 87 | (t/run-tests)) 88 | -------------------------------------------------------------------------------- /test/src/cognitect/client/test_double_test.clj: -------------------------------------------------------------------------------- 1 | (ns cognitect.client.test-double-test 2 | "Tests for the test double client implementation." 3 | (:require [clojure.test :refer [deftest is testing]] 4 | [cognitect.client.impl-test :as client-test] 5 | [cognitect.aws.client.api :as aws] 6 | [cognitect.aws.client.test-double :as client.test])) 7 | 8 | (deftest keyword-access 9 | (let [c (client.test/client {:api :s3})] 10 | (is (= "s3" (:api c))) 11 | (is (map? (:service c))))) 12 | 13 | (deftest register-handlers-on-creation 14 | (testing "supports handler functions (sync and async)" 15 | (let [user-provided-response {:Location "abc"} 16 | test-s3 (client.test/client {:api :s3 :ops {:CreateBucket 17 | (constantly user-provided-response)}})] 18 | (doseq [invocation-response (client-test/invocations test-s3 19 | {:op :CreateBucket 20 | :request {:Bucket "bucket"}})] 21 | (is (= user-provided-response invocation-response)))))) 22 | 23 | (deftest register-handlers-with-instrument 24 | (let [user-provided-response {:Location "abc"} 25 | test-s3 (client.test/client {:api :s3})] 26 | (testing "register handler" 27 | (client.test/instrument test-s3 {:CreateBucket (constantly user-provided-response)}) 28 | (doseq [invocation-response (client-test/invocations test-s3 29 | {:op :CreateBucket 30 | :request {:Bucket "bucket"}})] 31 | (is (= user-provided-response invocation-response)))))) 32 | 33 | (deftest raw-response-values 34 | (let [test-s3 (client.test/client {:api :s3})] 35 | (let [response {:Buckets []}] 36 | (client.test/instrument test-s3 {:ListBuckets response}) 37 | (is (= response (aws/invoke test-s3 {:op :ListBuckets :request {}})))) 38 | (let [response {:Location "abc"}] 39 | (client.test/instrument test-s3 {:CreateBucket response}) 40 | (is (= response (aws/invoke test-s3 {:op :CreateBucket :request {:Bucket "bucket"}})))) 41 | (let [response {:cognitect.anomalies/category :cognitect.anomalies/busy}] 42 | (client.test/instrument test-s3 {:CreateBucket response}) 43 | (is (= response (aws/invoke test-s3 {:op :CreateBucket :request {:Bucket "bucket"}})))))) 44 | 45 | (deftest custom-testing-strategies 46 | (let [calls (atom []) 47 | test-s3 (client.test/client {:api :s3 48 | :ops {:CreateBucket 49 | (fn [op-map] 50 | (swap! calls conj op-map) 51 | {:Location "over the rainbow"})}})] 52 | (dotimes [n 5] 53 | (aws/invoke test-s3 {:op :CreateBucket 54 | :request {:Bucket (str "bucket-" n)}}) 55 | (is (= (take (inc n) [{:op :CreateBucket, :request {:Bucket "bucket-0"}} 56 | {:op :CreateBucket, :request {:Bucket "bucket-1"}} 57 | {:op :CreateBucket, :request {:Bucket "bucket-2"}} 58 | {:op :CreateBucket, :request {:Bucket "bucket-3"}} 59 | {:op :CreateBucket, :request {:Bucket "bucket-4"}}]) 60 | @calls))))) 61 | 62 | (deftest test-anomalies-and-exceptions 63 | (testing "returns an anomaly with spec report when invoked with invalid request" 64 | (let [res (aws/invoke 65 | (client.test/client {:api :s3}) 66 | {:op :CreateBucket 67 | :request {:BucketName "key should be :Bucket"}})] 68 | (is (= :cognitect.anomalies/incorrect (:cognitect.anomalies/category res))) 69 | (is (:clojure.spec.alpha/problems res)))) 70 | 71 | (testing "returns an anomaly when invoking op unsupported by service" 72 | (let [res (aws/invoke 73 | (client.test/client {:api :s3 :ops {}}) 74 | {:op :DoesNotExistInS3})] 75 | (is (= :cognitect.anomalies/unsupported (:cognitect.anomalies/category res))) 76 | (is (= "Operation not supported" (:cognitect.anomalies/message res))))) 77 | 78 | (testing "returns an anomaly when invoking undeclared operation" 79 | (let [res (aws/invoke 80 | (client.test/client {:api :s3 :ops {}}) 81 | {:op :CreateBucket 82 | :request {:Bucket "bucket"}})] 83 | (is (= :cognitect.anomalies/incorrect (:cognitect.anomalies/category res))) 84 | (is (= "No handler or response provided for op" (:cognitect.anomalies/message res))))) 85 | 86 | (testing "throws when instrumenting op unsupported by service" 87 | (is (thrown-with-msg? RuntimeException 88 | #"Operation not supported" 89 | (client.test/client {:api :s3 :ops {:DoesNotExistInS3 {}}}))) 90 | (let [client (client.test/client {:api :s3})] 91 | (is (thrown-with-msg? RuntimeException 92 | #"Operation not supported" 93 | (client.test/instrument client {:DoesNotExistInS3 {}})))))) 94 | --------------------------------------------------------------------------------