diff --git a/gems/aws-sdk-apigateway/spec/client_spec.rb b/gems/aws-sdk-apigateway/spec/client_spec.rb
index d1d204d1149..8606fcfb654 100644
--- a/gems/aws-sdk-apigateway/spec/client_spec.rb
+++ b/gems/aws-sdk-apigateway/spec/client_spec.rb
@@ -6,7 +6,7 @@ module Aws
module APIGateway
describe Client do
- let(:client) { Client.new(stub_responses:true) }
+ let(:client) { Client.new(stub_responses: true) }
it 'supports maps for querystrings' do
resp = client.get_sdk({
@@ -21,9 +21,7 @@ module APIGateway
})
expect(resp.context.http_request.endpoint.to_s).to match(/\?abc=xyz&key=value&string=string$/)
-
end
-
end
end
end
diff --git a/gems/aws-sdk-apigateway/spec/protocols_spec.rb b/gems/aws-sdk-apigateway/spec/protocols_spec.rb
new file mode 100644
index 00000000000..796cdb155fd
--- /dev/null
+++ b/gems/aws-sdk-apigateway/spec/protocols_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require_relative 'spec_helper'
+
+module Aws
+ module APIGateway
+ describe Client do
+
+ let(:client) { Client.new(stub_responses: true) }
+
+ # {
+ # id: "ApiGatewayAccept",
+ # documentation: "API Gateway requires that this Accept header is set on all requests.",
+ # protocol: restJson1,
+ # method: "GET",
+ # uri: "/restapis",
+ # headers: {
+ # "Accept": "application/json",
+ # },
+ # body: "",
+ # params: {},
+ # }
+ it 'ApiGatewayAccept' do
+ resp = client.get_rest_apis
+ request = resp.context.http_request
+ expect(request.headers['accept']).to eq('application/json')
+ end
+ end
+ end
+end
diff --git a/gems/aws-sdk-core/CHANGELOG.md b/gems/aws-sdk-core/CHANGELOG.md
index 29e8e70a644..3a77880e044 100644
--- a/gems/aws-sdk-core/CHANGELOG.md
+++ b/gems/aws-sdk-core/CHANGELOG.md
@@ -1,6 +1,8 @@
Unreleased Changes
------------------
+* Issue - Fix trailing slash in endpoint URLs for rest-json and rest-xml services.
+
3.197.1 (2024-06-19)
------------------
diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/rest/request/endpoint.rb b/gems/aws-sdk-core/lib/aws-sdk-core/rest/request/endpoint.rb
index 935ac72076f..b69ad71b090 100644
--- a/gems/aws-sdk-core/lib/aws-sdk-core/rest/request/endpoint.rb
+++ b/gems/aws-sdk-core/lib/aws-sdk-core/rest/request/endpoint.rb
@@ -30,7 +30,9 @@ def uri(base_uri, params)
private
def apply_path_params(uri, params)
- path = uri.path.sub(%r{/$}, '') + @path_pattern.split('?')[0]
+ path = uri.path.sub(%r{/$}, '')
+ # handle trailing slash
+ path += @path_pattern.split('?')[0] if path.empty? || @path_pattern != '/'
uri.path = path.gsub(/{.+?}/) do |placeholder|
param_value_for_placeholder(placeholder, params)
end
diff --git a/gems/aws-sdk-glacier/CHANGELOG.md b/gems/aws-sdk-glacier/CHANGELOG.md
index aa54b2cfd9e..14b57734502 100644
--- a/gems/aws-sdk-glacier/CHANGELOG.md
+++ b/gems/aws-sdk-glacier/CHANGELOG.md
@@ -1,6 +1,8 @@
Unreleased Changes
------------------
+* Issue - Require `account_id` to be non-empty and set it to the default.
+
1.62.0 (2024-06-05)
------------------
diff --git a/gems/aws-sdk-glacier/lib/aws-sdk-glacier/plugins/account_id.rb b/gems/aws-sdk-glacier/lib/aws-sdk-glacier/plugins/account_id.rb
index 5c4ed74ed19..d9654a86a8f 100644
--- a/gems/aws-sdk-glacier/lib/aws-sdk-glacier/plugins/account_id.rb
+++ b/gems/aws-sdk-glacier/lib/aws-sdk-glacier/plugins/account_id.rb
@@ -14,10 +14,18 @@ class AccountId < Seahorse::Client::Plugin
your `:credentials` belong to.
DOCS
- handle_request(step: :initialize) do |context|
- context.params[:account_id] ||= context.config.account_id
+ class Handler < Seahorse::Client::Handler
+ def call(context)
+ context.params[:account_id] ||= context.config.account_id
+ if context.params[:account_id].empty?
+ context.params[:account_id] = '-'
+ end
+ @handler.call(context)
+ end
end
+ handler(Handler, step: :initialize)
+
end
end
end
diff --git a/gems/aws-sdk-glacier/lib/aws-sdk-glacier/plugins/api_version.rb b/gems/aws-sdk-glacier/lib/aws-sdk-glacier/plugins/api_version.rb
index 19c19c4ad28..25f80b582fd 100644
--- a/gems/aws-sdk-glacier/lib/aws-sdk-glacier/plugins/api_version.rb
+++ b/gems/aws-sdk-glacier/lib/aws-sdk-glacier/plugins/api_version.rb
@@ -7,13 +7,11 @@ module Plugins
class ApiVersion < Seahorse::Client::Plugin
class Handler < Seahorse::Client::Handler
-
def call(context)
version = context.config.api.version
context.http_request.headers['x-amz-glacier-version'] = version
@handler.call(context)
end
-
end
handler(Handler)
diff --git a/gems/aws-sdk-glacier/spec/client_spec.rb b/gems/aws-sdk-glacier/spec/client_spec.rb
index 98acd25d437..0373a1b24e9 100644
--- a/gems/aws-sdk-glacier/spec/client_spec.rb
+++ b/gems/aws-sdk-glacier/spec/client_spec.rb
@@ -39,17 +39,8 @@ module Glacier
)
end
- describe 'api verison' do
-
- it 'sends the API version as a header' do
- resp = client.list_vaults
- expect(resp.context.http_request.headers['x-amz-glacier-version']).to eq('2012-06-01')
- end
-
- end
describe 'errors' do
-
it 'extracts the error code form the header' do
client.handle(step: :send) do |context|
context.http_response.signal_headers(409, {})
@@ -67,11 +58,9 @@ module Glacier
client.list_vaults(account_id: '12345')
}.to raise_error(Errors::AccessDeniedException)
end
-
end
describe ':account_id' do
-
it 'defaults to -' do
resp = client.list_vaults
expect(resp.context.http_request.endpoint.path).to eq('/-/vaults')
@@ -88,7 +77,6 @@ module Glacier
resp = client.list_vaults(account_id: 'xyz')
expect(resp.context.http_request.endpoint.path).to eq('/xyz/vaults')
end
-
end
end
end
diff --git a/gems/aws-sdk-glacier/spec/protocols_spec.rb b/gems/aws-sdk-glacier/spec/protocols_spec.rb
new file mode 100644
index 00000000000..c29241b8577
--- /dev/null
+++ b/gems/aws-sdk-glacier/spec/protocols_spec.rb
@@ -0,0 +1,137 @@
+# frozen_string_literal: true
+
+require_relative 'spec_helper'
+
+module Aws
+ module Glacier
+ describe Client do
+
+ let(:client) { Client.new(stub_responses: true) }
+
+ describe '#upload_archive' do
+ # {
+ # id: "GlacierVersionHeader",
+ # documentation: "Glacier requires that a version header be set on all requests.",
+ # protocol: restJson1,
+ # method: "POST",
+ # uri: "/foo/vaults/bar/archives",
+ # headers: {
+ # "X-Amz-Glacier-Version": "2012-06-01",
+ # },
+ # body: "",
+ # params: {
+ # accountId: "foo",
+ # vaultName: "bar",
+ # },
+ # },
+ it 'GlacierVersionHeader' do
+ resp = client.upload_archive(
+ account_id: 'foo',
+ vault_name: 'bar'
+ )
+ request = resp.context.http_request
+ expect(request.headers['x-amz-glacier-version']).to eq('2012-06-01')
+ end
+
+ # {
+ # id: "GlacierChecksums",
+ # documentation: "Glacier requires checksum headers that are cumbersome to provide.",
+ # protocol: restJson1,
+ # method: "POST",
+ # uri: "/foo/vaults/bar/archives",
+ # headers: {
+ # "X-Amz-Glacier-Version": "2012-06-01",
+ # "X-Amz-Content-Sha256": "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9",
+ # "X-Amz-Sha256-Tree-Hash": "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9",
+ # },
+ # body: "hello world",
+ # params: {
+ # accountId: "foo",
+ # vaultName: "bar",
+ # body: "hello world"
+ # },
+ # appliesTo: "client",
+ # },
+ it 'GlacierChecksums' do
+ resp = client.upload_archive(
+ account_id: 'foo',
+ vault_name: 'bar',
+ body: 'hello world'
+ )
+ request = resp.context.http_request
+ expect(request.headers['x-amz-glacier-version']).to eq('2012-06-01')
+ expect(request.headers['x-amz-content-sha256'])
+ .to eq('b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9')
+ expect(request.headers['x-amz-sha256-tree-hash'])
+ .to eq('b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9')
+ end
+
+ # {
+ # id: "GlacierAccountId",
+ # documentation: """
+ # Glacier requires that the account id be set, but you can just use a
+ # hyphen (-) to indicate the current account. This should be default
+ # behavior if the customer provides a null or empty string.""",
+ # protocol: restJson1,
+ # method: "POST",
+ # uri: "/-/vaults/bar/archives",
+ # headers: {
+ # "X-Amz-Glacier-Version": "2012-06-01",
+ # },
+ # body: "",
+ # params: {
+ # accountId: "",
+ # vaultName: "bar",
+ # },
+ # appliesTo: "client",
+ # }
+ it 'GlacierAccountId' do
+ resp = client.upload_archive(
+ account_id: '',
+ vault_name: 'bar'
+ )
+ request = resp.context.http_request
+ expect(request.headers['x-amz-glacier-version']).to eq('2012-06-01')
+ expect(request.endpoint.path).to eq('/-/vaults/bar/archives')
+ end
+ end
+
+ describe '#upload_multipart_part' do
+ # {
+ # id: "GlacierMultipartChecksums",
+ # documentation: "Glacier requires checksum headers that are cumbersome to provide.",
+ # protocol: restJson1,
+ # method: "PUT",
+ # uri: "/foo/vaults/bar/multipart-uploads/baz",
+ # headers: {
+ # "X-Amz-Glacier-Version": "2012-06-01",
+ # "X-Amz-Content-Sha256": "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9",
+ # "X-Amz-Sha256-Tree-Hash": "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9",
+ # },
+ # body: "hello world",
+ # params: {
+ # accountId: "foo",
+ # vaultName: "bar",
+ # uploadId: "baz",
+ # body: "hello world"
+ # },
+ # appliesTo: "client",
+ # }
+ it 'GlacierMultipartChecksums' do
+ resp = client.upload_multipart_part(
+ account_id: 'foo',
+ vault_name: 'bar',
+ upload_id: 'baz',
+ body: 'hello world'
+ )
+ request = resp.context.http_request
+ expect(request.headers['x-amz-glacier-version']).to eq('2012-06-01')
+ expect(request.headers['x-amz-content-sha256'])
+ .to eq('b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9')
+ expect(request.headers['x-amz-sha256-tree-hash'])
+ .to eq('b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9')
+ end
+ end
+ end
+ end
+end
diff --git a/gems/aws-sdk-machinelearning/spec/client_spec.rb b/gems/aws-sdk-machinelearning/spec/client_spec.rb
deleted file mode 100644
index c952cd81e6d..00000000000
--- a/gems/aws-sdk-machinelearning/spec/client_spec.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-require_relative 'spec_helper'
-
-module Aws
- module MachineLearning
- describe Client do
-
- let(:client) { Client.new(stub_responses:true) }
-
- describe '#predict' do
-
- it 'uses the :predict_endpoint parameter as the http endpoint' do
-
- endpoint = nil
- client.handle(step: :send) do |context|
- endpoint = context.http_request.endpoint
- Seahorse::Client::Response.new(context: context)
- end
- client.predict(
- predict_endpoint: 'https://foo.com',
- ml_model_id: 'id',
- record: {}
- )
- expect(endpoint.to_s).to eq('https://foo.com')
- end
-
- end
- end
- end
-end
diff --git a/gems/aws-sdk-machinelearning/spec/protocols_spec.rb b/gems/aws-sdk-machinelearning/spec/protocols_spec.rb
new file mode 100644
index 00000000000..8299d18d125
--- /dev/null
+++ b/gems/aws-sdk-machinelearning/spec/protocols_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require_relative 'spec_helper'
+
+module Aws
+ module MachineLearning
+ describe Client do
+
+ let(:client) { Client.new(stub_responses: true) }
+
+ describe '#predict' do
+ # {
+ # id: "MachinelearningPredictEndpoint",
+ # documentation: """
+ # MachineLearning's api makes use of generated endpoints that the
+ # customer is then expected to use for the Predict operation. Having
+ # to alter the endpoint for a specific operation would be cumbersome,
+ # so an AWS client should be able to do it for them.""",
+ # protocol: awsJson1_1,
+ # method: "POST",
+ # uri: "/",
+ # host: "example.com",
+ # resolvedHost: "custom.example.com",
+ # body: "{\"MLModelId\": \"foo\", \"Record\": {}, \"PredictEndpoint\": \"https://custom.example.com/\"}",
+ # bodyMediaType: "application/json",
+ # headers: {"Content-Type": "application/x-amz-json-1.1"},
+ # params: {
+ # MLModelId: "foo",
+ # Record: {},
+ # PredictEndpoint: "https://custom.example.com/",
+ # }
+ # }
+ it 'MachinelearningPredictEndpoint' do
+ endpoint = 'https://custom.example.com/'
+ body = '{"MLModelId":"foo","Record":{},"PredictEndpoint":"https://custom.example.com/"}'
+ headers = { 'Content-Type' => 'application/x-amz-json-1.1' }
+ resp = client.predict(
+ ml_model_id: 'foo',
+ record: {},
+ predict_endpoint: endpoint
+ )
+ request = resp.context.http_request
+ expect(request.endpoint.to_s).to eq(endpoint)
+ expect(request.body_contents).to eq(body)
+ expect(request.headers['content-type']).to eq(headers['Content-Type'])
+ end
+ end
+ end
+ end
+end
diff --git a/gems/aws-sdk-s3/spec/client_spec.rb b/gems/aws-sdk-s3/spec/client_spec.rb
index ca3534d8e21..bbd262193d0 100644
--- a/gems/aws-sdk-s3/spec/client_spec.rb
+++ b/gems/aws-sdk-s3/spec/client_spec.rb
@@ -492,7 +492,7 @@ module S3
it 'uses path style addressing for DNS incompatible bucket names' do
client = Client.new(stub_responses: true)
resp = client.head_bucket(bucket: 'Bucket123')
- expect(resp.context.http_request.endpoint.path).to eq('/Bucket123/')
+ expect(resp.context.http_request.endpoint.path).to eq('/Bucket123')
end
end
diff --git a/gems/aws-sdk-s3/spec/protocols_spec.rb b/gems/aws-sdk-s3/spec/protocols_spec.rb
new file mode 100644
index 00000000000..f08f3575cb3
--- /dev/null
+++ b/gems/aws-sdk-s3/spec/protocols_spec.rb
@@ -0,0 +1,488 @@
+# frozen_string_literal: true
+
+require_relative 'spec_helper'
+
+module Aws
+ module S3
+ describe Client do
+
+ let(:client) { Client.new(stub_responses: true) }
+
+ describe '#list_objects_v2' do
+ # {
+ # id: "S3DefaultAddressing",
+ # documentation: "S3 clients should map the default addressing style to virtual host.",
+ # protocol: restXml,
+ # method: "GET",
+ # uri: "/",
+ # host: "s3.us-west-2.amazonaws.com",
+ # resolvedHost: "mybucket.s3.us-west-2.amazonaws.com",
+ # body: "",
+ # queryParams: [
+ # "list-type=2",
+ # ],
+ # params: {
+ # Bucket: "mybucket",
+ # },
+ # vendorParamsShape: aws.protocoltests.config#AwsConfig,
+ # vendorParams: {
+ # scopedConfig: {
+ # client: {
+ # region: "us-west-2",
+ # },
+ # },
+ # },
+ # },
+ it 'S3DefaultAddressing' do
+ client.config.region = 'us-west-2'
+ resp = client.list_objects_v2(bucket: 'mybucket')
+ request = resp.context.http_request
+ expect(request.endpoint.host).to eq('mybucket.s3.us-west-2.amazonaws.com')
+ expect(request.endpoint.query).to include('list-type=2')
+ expect(request.endpoint.path).to eq('/')
+ end
+
+ # {
+ # id: "S3VirtualHostAddressing",
+ # documentation: "S3 clients should support the explicit virtual host addressing style.",
+ # protocol: restXml,
+ # method: "GET",
+ # uri: "/",
+ # host: "s3.us-west-2.amazonaws.com",
+ # resolvedHost: "mybucket.s3.us-west-2.amazonaws.com",
+ # body: "",
+ # queryParams: [
+ # "list-type=2",
+ # ],
+ # params: {
+ # Bucket: "mybucket",
+ # },
+ # vendorParamsShape: aws.protocoltests.config#AwsConfig,
+ # vendorParams: {
+ # scopedConfig: {
+ # client: {
+ # region: "us-west-2",
+ # s3: {
+ # addressing_style: "virtual",
+ # },
+ # },
+ # },
+ # },
+ # },
+ it 'S3VirtualHostAddressing' do
+ client.config.region = 'us-west-2'
+ client.config.force_path_style = false
+ resp = client.list_objects_v2(bucket: 'mybucket')
+ request = resp.context.http_request
+ expect(request.endpoint.host).to eq('mybucket.s3.us-west-2.amazonaws.com')
+ expect(request.endpoint.query).to include('list-type=2')
+ expect(request.endpoint.path).to eq('/')
+ end
+
+ # {
+ # id: "S3PathAddressing",
+ # documentation: "S3 clients should support the explicit path addressing style.",
+ # protocol: restXml,
+ # method: "GET",
+ # uri: "/mybucket",
+ # host: "s3.us-west-2.amazonaws.com",
+ # resolvedHost: "s3.us-west-2.amazonaws.com",
+ # body: "",
+ # queryParams: [
+ # "list-type=2",
+ # ],
+ # params: {
+ # Bucket: "mybucket",
+ # },
+ # vendorParamsShape: aws.protocoltests.config#AwsConfig,
+ # vendorParams: {
+ # scopedConfig: {
+ # client: {
+ # region: "us-west-2",
+ # s3: {
+ # addressing_style: "path",
+ # },
+ # },
+ # },
+ # },
+ # },
+ it 'S3PathAddressing' do
+ client.config.region = 'us-west-2'
+ client.config.force_path_style = true
+ resp = client.list_objects_v2(bucket: 'mybucket')
+ request = resp.context.http_request
+ expect(request.endpoint.host).to eq('s3.us-west-2.amazonaws.com')
+ expect(request.endpoint.query).to include('list-type=2')
+ expect(request.endpoint.path).to eq('/mybucket')
+ end
+
+ # {
+ # id: "S3VirtualHostDualstackAddressing",
+ # documentation: """
+ # S3 clients should support the explicit virtual host
+ # addressing style with Dualstack.""",
+ # protocol: restXml,
+ # method: "GET",
+ # uri: "/",
+ # host: "s3.us-west-2.amazonaws.com",
+ # resolvedHost: "mybucket.s3.dualstack.us-west-2.amazonaws.com",
+ # body: "",
+ # queryParams: [
+ # "list-type=2",
+ # ],
+ # params: {
+ # Bucket: "mybucket",
+ # },
+ # vendorParamsShape: aws.protocoltests.config#AwsConfig,
+ # vendorParams: {
+ # scopedConfig: {
+ # client: {
+ # region: "us-west-2",
+ # s3: {
+ # addressing_style: "virtual",
+ # use_dualstack_endpoint: true,
+ # },
+ # },
+ # },
+ # },
+ # },
+ it 'S3VirtualHostDualstackAddressing' do
+ client.config.region = 'us-west-2'
+ client.config.use_dualstack_endpoint = true
+ resp = client.list_objects_v2(bucket: 'mybucket')
+ request = resp.context.http_request
+ expect(request.endpoint.host).to eq('mybucket.s3.dualstack.us-west-2.amazonaws.com')
+ expect(request.endpoint.query).to include('list-type=2')
+ expect(request.endpoint.path).to eq('/')
+ end
+
+ # {
+ # id: "S3VirtualHostAccelerateAddressing",
+ # documentation: """
+ # S3 clients should support the explicit virtual host
+ # addressing style with S3 Accelerate.""",
+ # protocol: restXml,
+ # method: "GET",
+ # uri: "/",
+ # host: "s3.us-west-2.amazonaws.com",
+ # resolvedHost: "mybucket.s3-accelerate.amazonaws.com",
+ # body: "",
+ # queryParams: [
+ # "list-type=2",
+ # ],
+ # params: {
+ # Bucket: "mybucket",
+ # },
+ # vendorParamsShape: aws.protocoltests.config#AwsConfig,
+ # vendorParams: {
+ # scopedConfig: {
+ # client: {
+ # region: "us-west-2",
+ # s3: {
+ # addressing_style: "virtual",
+ # use_accelerate_endpoint: true,
+ # },
+ # },
+ # },
+ # },
+ # },
+ it 'S3VirtualHostAccelerateAddressing' do
+ client.config.region = 'us-west-2'
+ client.config.use_accelerate_endpoint = true
+ resp = client.list_objects_v2(bucket: 'mybucket')
+ request = resp.context.http_request
+ expect(request.endpoint.host).to eq('mybucket.s3-accelerate.amazonaws.com')
+ expect(request.endpoint.query).to include('list-type=2')
+ expect(request.endpoint.path).to eq('/')
+ end
+
+ # {
+ # id: "S3VirtualHostDualstackAccelerateAddressing",
+ # documentation: """
+ # S3 clients should support the explicit virtual host
+ # addressing style with Dualstack and S3 Accelerate.""",
+ # protocol: restXml,
+ # method: "GET",
+ # uri: "/",
+ # host: "s3.us-west-2.amazonaws.com",
+ # resolvedHost: "mybucket.s3-accelerate.dualstack.amazonaws.com",
+ # body: "",
+ # queryParams: [
+ # "list-type=2",
+ # ],
+ # params: {
+ # Bucket: "mybucket",
+ # },
+ # vendorParamsShape: aws.protocoltests.config#AwsConfig,
+ # vendorParams: {
+ # scopedConfig: {
+ # client: {
+ # region: "us-west-2",
+ # s3: {
+ # addressing_style: "virtual",
+ # use_dualstack_endpoint: true,
+ # use_accelerate_endpoint: true,
+ # },
+ # },
+ # },
+ # },
+ # },
+ it 'S3VirtualHostDualstackAccelerateAddressing' do
+ client.config.region = 'us-west-2'
+ client.config.use_dualstack_endpoint = true
+ client.config.use_accelerate_endpoint = true
+ resp = client.list_objects_v2(bucket: 'mybucket')
+ request = resp.context.http_request
+ expect(request.endpoint.host).to eq('mybucket.s3-accelerate.dualstack.amazonaws.com')
+ expect(request.endpoint.query).to include('list-type=2')
+ expect(request.endpoint.path).to eq('/')
+ end
+
+ # {
+ # id: "S3OperationAddressingPreferred",
+ # documentation: """
+ # S3 clients should resolve to the addressing style of the
+ # operation if defined on both the client and operation.""",
+ # protocol: restXml,
+ # method: "GET",
+ # uri: "/",
+ # host: "s3.us-west-2.amazonaws.com",
+ # resolvedHost: "mybucket.s3.us-west-2.amazonaws.com",
+ # body: "",
+ # queryParams: [
+ # "list-type=2",
+ # ],
+ # params: {
+ # Bucket: "mybucket",
+ # },
+ # vendorParamsShape: aws.protocoltests.config#AwsConfig,
+ # vendorParams: {
+ # scopedConfig: {
+ # client: {
+ # region: "us-west-2",
+ # s3: {
+ # addressing_style: "path",
+ # },
+ # },
+ # operation: {
+ # s3: {
+ # addressing_style: "virtual",
+ # },
+ # },
+ # },
+ # },
+ # },
+ it 'S3OperationAddressingPreferred' do
+ skip 'Operation addressing style is not supported'
+ end
+ end
+
+ describe '#delete_object_tagging' do
+ # {
+ # id: "S3EscapeObjectKeyInUriLabel",
+ # documentation: """
+ # S3 clients should escape special characters in Object Keys
+ # when the Object Key is used as a URI label binding.
+ # """,
+ # protocol: restXml,
+ # method: "DELETE",
+ # uri: "/my%20key.txt",
+ # host: "s3.us-west-2.amazonaws.com",
+ # resolvedHost: "mybucket.s3.us-west-2.amazonaws.com",
+ # body: "",
+ # queryParams: [
+ # "tagging"
+ # ],
+ # params: {
+ # Bucket: "mybucket",
+ # Key: "my key.txt"
+ # },
+ # vendorParamsShape: aws.protocoltests.config#AwsConfig,
+ # vendorParams: {
+ # scopedConfig: {
+ # client: {
+ # region: "us-west-2",
+ # },
+ # },
+ # },
+ # },
+ it 'S3EscapeObjectKeyInUriLabel' do
+ client.config.region = 'us-west-2'
+ resp = client.delete_object_tagging(bucket: 'mybucket', key: 'my key.txt')
+ request = resp.context.http_request
+ expect(request.endpoint.host).to eq('mybucket.s3.us-west-2.amazonaws.com')
+ expect(request.endpoint.query).to include('tagging')
+ expect(request.endpoint.path).to eq('/my%20key.txt')
+ end
+
+ # {
+ # id: "S3EscapePathObjectKeyInUriLabel",
+ # documentation: """
+ # S3 clients should preserve an Object Key representing a path
+ # when the Object Key is used as a URI label binding, but still
+ # escape special characters.
+ # """,
+ # protocol: restXml,
+ # method: "DELETE",
+ # uri: "/foo/bar/my%20key.txt",
+ # host: "s3.us-west-2.amazonaws.com",
+ # resolvedHost: "mybucket.s3.us-west-2.amazonaws.com",
+ # body: "",
+ # queryParams: [
+ # "tagging"
+ # ],
+ # params: {
+ # Bucket: "mybucket",
+ # Key: "foo/bar/my key.txt"
+ # },
+ # vendorParamsShape: aws.protocoltests.config#AwsConfig,
+ # vendorParams: {
+ # scopedConfig: {
+ # client: {
+ # region: "us-west-2",
+ # },
+ # },
+ # },
+ # }
+ it 'S3EscapePathObjectKeyInUriLabel' do
+ client.config.region = 'us-west-2'
+ resp = client.delete_object_tagging(bucket: 'mybucket', key: 'foo/bar/my key.txt')
+ request = resp.context.http_request
+ expect(request.endpoint.host).to eq('mybucket.s3.us-west-2.amazonaws.com')
+ expect(request.endpoint.query).to include('tagging')
+ expect(request.endpoint.path).to eq('/foo/bar/my%20key.txt')
+ end
+ end
+
+ describe '#get_object' do
+ # {
+ # id: "S3PreservesLeadingDotSegmentInUriLabel",
+ # documentation: """
+ # S3 clients should not remove dot segments from request paths.
+ # """,
+ # protocol: restXml,
+ # method: "GET",
+ # uri: "/../key.txt",
+ # host: "s3.us-west-2.amazonaws.com",
+ # resolvedHost: "mybucket.s3.us-west-2.amazonaws.com",
+ # body: "",
+ # params: {
+ # Bucket: "mybucket",
+ # Key: "../key.txt"
+ # },
+ # vendorParamsShape: aws.protocoltests.config#AwsConfig,
+ # vendorParams: {
+ # scopedConfig: {
+ # client: {
+ # region: "us-west-2",
+ # s3: {
+ # addressing_style: "virtual",
+ # },
+ # },
+ # },
+ # },
+ # },
+ it 'S3PreservesLeadingDotSegmentInUriLabel' do
+ client.config.region = 'us-west-2'
+ resp = client.get_object(bucket: 'mybucket', key: '../key.txt')
+ request = resp.context.http_request
+ expect(request.endpoint.host).to eq('mybucket.s3.us-west-2.amazonaws.com')
+ expect(request.endpoint.path).to eq('/../key.txt')
+ end
+
+ # {
+ # id: "S3PreservesEmbeddedDotSegmentInUriLabel",
+ # documentation: """
+ # S3 clients should not remove dot segments from request paths.
+ # """,
+ # protocol: restXml,
+ # method: "GET",
+ # uri: "/foo/../key.txt",
+ # host: "s3.us-west-2.amazonaws.com",
+ # resolvedHost: "mybucket.s3.us-west-2.amazonaws.com",
+ # body: "",
+ # params: {
+ # Bucket: "mybucket",
+ # Key: "foo/../key.txt"
+ # },
+ # vendorParamsShape: aws.protocoltests.config#AwsConfig,
+ # vendorParams: {
+ # scopedConfig: {
+ # client: {
+ # region: "us-west-2",
+ # s3: {
+ # addressing_style: "virtual",
+ # },
+ # },
+ # },
+ # },
+ # }
+ it 'S3PreservesEmbeddedDotSegmentInUriLabel' do
+ client.config.region = 'us-west-2'
+ resp = client.get_object(bucket: 'mybucket', key: 'foo/../key.txt')
+ request = resp.context.http_request
+ expect(request.endpoint.host).to eq('mybucket.s3.us-west-2.amazonaws.com')
+ expect(request.endpoint.path).to eq('/foo/../key.txt')
+ end
+ end
+
+ describe '#get_bucket_location' do
+ # {
+ # id: "GetBucketLocationUnwrappedOutput",
+ # documentation: """
+ # S3 clients should use the @s3UnwrappedXmlOutput trait to determine
+ # that the response shape is not wrapped in a restxml operation-level XML node.
+ # """,
+ # code: 200,
+ # body: "\nus-west-2",
+ # params: {
+ # "LocationConstraint": "us-west-2"
+ # },
+ # protocol: restXml
+ # }
+ it 'GetBucketLocationUnwrappedOutput' do
+ client.handle(step: :send) do |context|
+ context.http_response.signal_done(
+ status_code: 200,
+ headers: {},
+ body: "\nus-west-2"
+ )
+ Seahorse::Client::Response.new(context: context)
+ end
+ resp = client.get_bucket_location(bucket: 'mybucket')
+ expect(resp.location_constraint).to eq('us-west-2')
+ end
+ end
+
+ describe 'NoSuchBucket' do
+ # {
+ # id: "S3OperationNoErrorWrappingResponse",
+ # documentation: """
+ # S3 operations return Error XML nodes unwrapped by
+ # the ErrorResponse XML node.
+ # """,
+ # protocol: restXml,
+ # code: 400,
+ # headers: {
+ # "Content-Type": "application/xml"
+ # },
+ # body: "\n\n\tSender\n\tNoSuchBucket
\n",
+ # bodyMediaType: "application/xml",
+ # }
+ it 'S3OperationNoErrorWrappingResponse' do
+ client.handle(step: :send) do |context|
+ context.http_response.signal_done(
+ status_code: 400,
+ headers: { 'Content-Type' => 'application/xml' },
+ body: "\n\n\tSender\n\tNoSuchBucket
\n"
+ )
+ Seahorse::Client::Response.new(context: context)
+ end
+ expect {
+ client.list_objects_v2(bucket: 'mybucket')
+ }.to raise_error(Errors::NoSuchBucket)
+ end
+ end
+ end
+ end
+end