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