anacronw / multer-s3

multer storage engine for amazon s3
MIT License
662 stars 193 forks source link

Crash in v3.0.0 if metadata handler is not specified #170

Closed volnyansky closed 2 years ago

volnyansky commented 2 years ago

I get crash if I don't specify metadata handler.

TypeError: Cannot convert undefined or null to object
        at Function.keys (<anonymous>)
        at serializeAws_restXmlPutObjectCommand (/usr/local/media-manager/stas/node_modules/@aws-sdk/client-s3/dist-cjs/protocols/Aws_restXml.js:3586:20)
        at processTicksAndRejections (node:internal/process/task_queues:96:5)
        at async /usr/local/media-manager/stas/node_modules/@aws-sdk/middleware-serde/dist-cjs/serializerMiddleware.js:5:21
        at async /usr/local/media-manager/stas/node_modules/@aws-sdk/middleware-logger/dist-cjs/loggerMiddleware.js:6:22
        at async Promise.all (index 0)
        at async Upload.__uploadUsingPut (/usr/local/media-manager/stas/node_modules/@aws-sdk/lib-storage/dist-cjs/Upload.js:46:39)
        at async Upload.__doConcurrentUpload (/usr/local/media-manager/stas/node_modules/@aws-sdk/lib-storage/dist-cjs/Upload.js:91:28)
        at async Promise.all (index 0)
        at async Upload.__doMultipartUpload (/usr/local/media-manager/stas/node_modules/@aws-sdk/lib-storage/dist-cjs/Upload.js:141:9)

My config :

const upload = multer({
    storage: multerS3({
        s3: new S3(config.awsConfig),
        bucket: config.awsConfig.bucketName,
        contentType: multerS3.AUTO_CONTENT_TYPE,
     //   metadata: function (req, file, cb) {
     //       cb(null, {});
     //   },
        key(req, file, cb) {
            const key = `${Date.now()}-${
                file.originalname
            }`;
            cb(null, key);
        },
        acl: "public-read",
    }),

});
Reckonyd commented 2 years ago

I think the problem is that AWS ONLY checks that the metadata object is not undefined. (node_modules/@aws-sdk/client-s3/dist-cjs/protocols/Aws_restXml.js line:3585)

...(input.Metadata !== undefined &&
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Object.keys(input.Metadata).reduce((acc, suffix) => ({
      ...acc,
      [`x-amz-meta-${suffix.toLowerCase()}`]: input.Metadata[suffix],
  }), {})),

Your library passes to the metadata object the default value of NULL. So null !== undefined is true in Javascript and thus the error. A possible solution is to change the default value to undefined so your library aligns with the AWS API behaviour. (node_modules/multer-s3/index.js line: 18)

var defaultMetadata = staticValue(null)

to

var defaultMetadata = staticValue(undefined)
LinusU commented 2 years ago

That sounds like a good workaround, would you be willing to submit a pull request?

Reckonyd commented 2 years ago

Of course!

LinusU commented 2 years ago

Fixed in 🚢 3.0.1 / 2022-05-31