question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Handling DeleteObjectsRequest broken after JS SDK update

See original GitHub issue

I’m running some integration tests against a localstack S3 container using AWS SDK v3 for JavaScript. With the recently published version v3.197.0 of the SDK, i’m getting errors when running a DeleteObjects request.

I compared the requests that are sent by the SDK, and can see the following difference (from the localstack logs): Before:

POST localhost/3ee3499c-208f-43f3-aadd-b667f3b2ea6f?delete=&x-id=DeleteObjects

Afterwards:

POST localhost/89e28fce-e5f2-427a-ab59-5229b83a15ee/?delete=&x-id=DeleteObjects

Stacktrace of the error:

  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: 2022-10-27T09:35:28.605  INFO --- [   asgi_gw_0] localstack.request.aws     : AWS s3.DeleteObjects => 500 (InternalError); DeleteObjectsRequest({'Bucket': '89e28fce-e5f2-427a-ab59-5229b83a15ee', 'Delete': {'Objects': [{'Key': 'sameDirectory/316b663c-663f-4881-bdd8-73ec94d62260'}, {'Key': 'sameDirectory/77680bae-2e2c-4230-af2c-165680c8057d'}]}, 'MFA': None, 'RequestPayer': None, 'BypassGovernanceRetention': None, 'ExpectedBucketOwner': None, 'ChecksumAlgorithm': None}, headers={'content-type': 'application/xml', 'content-length': '259', 'Expect': '100-continue', 'content-md5': 'SeDvWL0dJ6G0h+yQ476qfg==', 'host': 'localhost', 'x-amz-user-agent': 'aws-sdk-js/3.197.0', 'user-agent': 'aws-sdk-js/3.197.0 os/darwin/22.1.0 lang/js md/nodejs/16.18.0 api/s3/3.197.0', 'amz-sdk-invocation-id': 'bbd8ffc8-d792-4298-b7bd-68deca0c3d07', 'amz-sdk-request': 'attempt=1; max=3', 'x-amz-date': '20221027T093528Z', 'x-amz-content-sha256': 'f52fc7ca91861bfc5dac677a383afa8e05c00d54b61593ddd96502aff8711057', 'authorization': 'AWS4-HMAC-SHA256 Credential=accessKeyId/20221027/eu-central-1/s3/aws4_request, SignedHeaders=amz-sdk-invocation-id;amz-sdk-request;content-length;content-md5;content-type;host;x-amz-content-sha256;x-amz-date;x-amz-user-agent, Signature=62c6fb145a2d09eca53b1083ec3b0b75490ffd7cd2a22d572087784bd0599536', 'Connection': 'keep-alive', 'x-localstack-tgt-api': 's3', 'x-moto-account-id': '000000000000', 'x-localstack-edge': 'http://localhost', 'X-Forwarded-For': '127.0.0.1, localhost'}); InternalError(exception while calling s3.DeleteObjects: Traceback (most recent call last): +4ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/localstack/aws/chain.py", line 90, in handle +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: handler(self, self.context, response) +1ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/localstack/aws/handlers/service.py", line 122, in __call__ +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: handler(chain, context, response) +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/localstack/aws/handlers/legacy.py", line 81, in __call__ +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: result = self.forward_request( +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/localstack/aws/handlers/legacy.py", line 141, in forward_request +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: return do_forward_request( +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/localstack/services/edge.py", line 225, in do_forward_request +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: result = do_forward_request_inmem(api, method, path, data, headers, port=port) +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/localstack/services/edge.py", line 249, in do_forward_request_inmem +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: response = modify_and_forward( +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/localstack/services/generic_proxy.py", line 601, in wrapper +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: value = func(*args, **kwargs) +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/localstack/services/generic_proxy.py", line 774, in modify_and_forward +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: updated_response = listener.return_response( +1ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/localstack/services/s3/s3_listener.py", line 1644, in return_response +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: object_path = parts[1] if parts[1][0] == "/" else "/+0ms" % parts[1]
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: IndexError: string index out of range +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: , headers={'Content-Type': 'application/xml', 'Content-Length': '1525', 'x-amz-request-id': 'FF7XCYIT7RZKAU1DEAH2YKXFG4F37LYNDJ07Z942D2LEXHLG1AOJ', 'x-amz-id-2': 'MzRISOwyjmnupFF7XCYIT7RZKAU1DEAH2YKXFG4F37LYNDJ07Z942D2LEXHLG1AOJ7/JypPGXLh0OVFGcJaaO3KW/hRAqKOpIEEp'}) +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: 2022-10-27T09:35:28.619 ERROR --- [uest_thread)] werkzeug                   : Error on request: +14ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: Traceback (most recent call last): +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/.venv/lib/python3.10/site-packages/werkzeug/serving.py", line 335, in run_wsgi +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: execute(self.server.app) +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/.venv/lib/python3.10/site-packages/werkzeug/serving.py", line 322, in execute +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: application_iter = app(environ, start_response) +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/.venv/lib/python3.10/site-packages/moto/moto_server/werkzeug_app.py", line 249, in __call__ +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: return backend_app(environ, start_response) +2ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/.venv/lib/python3.10/site-packages/flask/app.py", line 2091, in __call__ +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: return self.wsgi_app(environ, start_response) +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/.venv/lib/python3.10/site-packages/flask/app.py", line 2076, in wsgi_app +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: response = self.handle_exception(e) +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/.venv/lib/python3.10/site-packages/flask_cors/extension.py", line 165, in wrapped_function +1ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: return cors_after_request(app.make_response(f(*args, **kwargs))) +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/.venv/lib/python3.10/site-packages/flask/app.py", line 2073, in wsgi_app +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: response = self.full_dispatch_request() +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/.venv/lib/python3.10/site-packages/flask/app.py", line 1519, in full_dispatch_request +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: rv = self.handle_user_exception(e) +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/.venv/lib/python3.10/site-packages/flask_cors/extension.py", line 165, in wrapped_function +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: return cors_after_request(app.make_response(f(*args, **kwargs))) +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/.venv/lib/python3.10/site-packages/flask/app.py", line 1517, in full_dispatch_request +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: rv = self.dispatch_request() +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/.venv/lib/python3.10/site-packages/flask/app.py", line 1503, in dispatch_request +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args) +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/localstack/utils/patch.py", line 38, in proxy +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: return new(target, *args, **kwargs) +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/localstack/utils/aws/request_context.py", line 174, in convert_to_flask_response_call +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: return fn(*args, **kwargs) +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/.venv/lib/python3.10/site-packages/moto/core/utils.py", line 110, in __call__ +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: result = self.callback(request, request.url, dict(request.headers)) +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/.venv/lib/python3.10/site-packages/moto/s3/responses.py", line 254, in ambiguous_response +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: return self.bucket_response(request, full_url, headers) +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/.venv/lib/python3.10/site-packages/moto/utilities/aws_headers.py", line 60, in _wrapper +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: response = f(*args, **kwargs) +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/.venv/lib/python3.10/site-packages/moto/s3/responses.py", line 260, in bucket_response +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: response = self._bucket_response(request, full_url) +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/.venv/lib/python3.10/site-packages/moto/s3/responses.py", line 305, in _bucket_response +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: return self._bucket_response_post(request, bucket_name) +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/.venv/lib/python3.10/site-packages/moto/s3/responses.py", line 983, in _bucket_response_post +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: key = form["key"] +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: File "/opt/code/localstack/.venv/lib/python3.10/site-packages/werkzeug/datastructures.py", line 375, in __getitem__ +1ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: raise exceptions.BadRequestKeyError(key) +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand. +0ms
  testcontainers:containers TRACE a06d147a600e3a0d915f0ed0923d716f17491e2406353bc3a7829fd26c34b1a2: KeyError: 'key' +0ms

What I understand is that the POST request for deletion is not determined as a delete request by the self.is_delete_keys method here, and thus interpreted as a PutObject request afterwards.

From what I can see, the method for determining the delete request currently does not account for this changed URL, where we now have /?delete= instead of ?delete=.

Could it already be the fix to include /?delete= in the check?

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:6

github_iconTop GitHub Comments

1reaction
j-beyercommented, Oct 31, 2022

Hi @bblommers, thanks so much for the quick follow-up & fix! Much appreciated 😃

We’re currently using the localstack docker image in our tests, and I think they’re not pulling the latest moto version yet. I tried running our tests with the moto docker image instead, but couldn’t get it to work so far. So I can’t really verify, sorry 😕 But I believe your PR should do the trick, so I think you can consider this closed, and I will report back once I’m able to check.

Again, thanks for your quick help!

1reaction
bblommerscommented, Oct 27, 2022

No worries @j-beyer - I’ll raise a PR shortly to improve the overall logic here a bit.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Handling DeleteObjectsRequest broken after JS SDK update
I'm running some integration tests against a localstack S3 container using AWS SDK v3 for JavaScript. With the recently published version ...
Read more >
DeleteObjectsRequest (AWS SDK for Java - 1.12.367)
Provides options for deleting multiple objects in a specified bucket. Once deleted, the object(s) can only be restored if versioning was enabled when...
Read more >
How do I delete an object on AWS S3 using Javascript?
You can use the JS method from S3: var AWS = require('aws-sdk'); AWS.config.loadFromPath('./credentials-ehl.json'); var s3 = new AWS.
Read more >
Migrating to AWS SDK v3 for Javascript - Serverless.Pub
AWS SDK for JavaScript is going through a major update, with version 3 becoming ready for production usage. The API is not backwards...
Read more >
How to fix the profile support in the AWS JS SDK v3
Migrating to v3. Two months ago, AWS released the v3 of the Javascript SDK. It brings quite a few updates and unfortunately it...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found