supabase / storage

S3 compatible object storage service that stores metadata in Postgres
https://supabase.com/docs/guides/storage
Apache License 2.0
764 stars 107 forks source link

Delete.Objects.map is not a function when trying to delete a single file via S3 DeleteObjects Command #504

Closed michaeljauk closed 3 months ago

michaeljauk commented 3 months ago

Bug report

Describe the bug

When trying to delete a single file via the S3 API (calling POST /s3/<bucket>/?delete=&x-id=DeleteObjects, DeleteObjects Command) a HTTP 500 error gets returned and no file gets deleted. In the corresponding logs of Supbase the following error gets displayed (abbreviated for brevity):

...
"error": [
  {
    "message": "Delete.Objects.map is not a function",
    "name": "TypeError",
    "raw": "{}",
    "stack": "TypeError: Delete.Objects.map is not a function\n    at S3ProtocolHandler.deleteObjects (/app/dist/storage/protocols/s3/s3-handler.js:595:43)\n    at Object.handler (/app/dist/http/routes/s3/commands/delete-object.js:59:27)\n    at Object.routeHandler (/app/dist/http/routes/s3/index.js:44:60)\n    at preHandlerCallback (/app/node_modules/fastify/lib/handleRequest.js:128:37)\n    at next (/app/node_modules/fastify/lib/hooks.js:176:7)\n    at handleResolve (/app/node_modules/fastify/lib/hooks.js:193:5)\n    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)"
  }
],
"event": null,
"job": null,
"jodId": null,
"level": "error",
"metadata": null,
"objectPath": null,
"operation": "storage.s3.object.delete_many",
"owner": null,
"payload": null,
...

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Upload one or more files to a bucket
  2. Try to delete the file via the S3 API's DeleteObjectsCommand

Expected behavior

The corresponding files should be deleted

fenos commented 3 months ago

Hi @michaeljauk this is interesting, I can't reproduce the issue. Can you provide more information on how you are sending the DeleteObjects Command?

fenos commented 3 months ago

In the PR above I've added more strict validation. But apparently, the command you are sending doesn't seem to be conforming with the Spec.

Once you have more information on this, I'll be happy to dig further

michaeljauk commented 3 months ago

@fenos I dug a bit deeper and verified that an HTTP 500 error only gets thrown when trying to delete a single file via the DeleteObjectsCommand. When trying to delete multiple files it works flawlessly. Sorry for not catching that earlier!

This is something that i verified works with native S3, as well as MinIO though. So i guess, this is still something you'd want to fix or rather change? 🤔

For further reference, I'm using Typescript/Node.js and the @aws-sdk/client-s3 lib.

See this example, which works with S3/MinIO but not Supabase:

const params: DeleteObjectsCommandInput = {
  Bucket: "testBucket",
  Delete: {
    Objects: [{ Key: "singleFile" }],
  },
};

const command = new DeleteObjectsCommand(params);

await this.client.send(command);
fenos commented 3 months ago

@michaeljauk thanks a lot for this! I could reproduce the issue, filing a fix shortly!

fenos commented 3 months ago

Ok, I have expanded the above PR and introduced the fix. TLDR, the XML parser when it receives only an item, parses it as an object as opposed to an array.

I could force the parsing to an array by implementing the isArray method on the fast-xml-parser

github-actions[bot] commented 3 months ago

:tada: This issue has been resolved in version 1.5.2 :tada:

The release is available on GitHub release

Your semantic-release bot :package::rocket:

michaeljauk commented 3 months ago

@fenos Thanks for resolving this so quickly! I guess another week or 2 weeks until it is GA? 👀

fenos commented 2 months ago

it is now being deployed GA