0

I'm trying to access an S3 bucket with nodejs using aws-sdk.

When I call the s3.getSignedUrl method and use the url it provides, I get a "NoSuchKey" error in the url.

<Code>NoSuchKey</Code>
<Message>The specified key does not exist.</Message>
<Key>{MY_BUCKET_NAME}/{REQUESTED_FILENAME}</Key>

My theory is that the request path I'm passing is wrong. Comparing my request:

{BUCKET_NAME}.s3.{BUCKET_REGION}.amazonaws.com/{BUCKET_NAME}/{KEY}

With the url created from the AWS console:

{BUCKET_NAME}.s3.{BUCKET_REGION}.amazonaws.com/{KEY}

Why is aws-sdk adding the "{BUCKET_NAME}" at the end?

NodeJS code:

// s3 instance setup
const s3 = new AWS.S3({
  region: BUCKET_REGION,
  endpoint: BUCKET_ENDPOINT, // {MY_BUCKET_NAME}.s3.{REGION}.amazonaws.com
  s3ForcePathStyle: true,
  signatureVersion: "v4",
});

const getSignedUrlFromS3 = async (filename) => {
    const s3Params = {
      Bucket: BUCKET_NAME,
      Key: filename,
      Expires: 60,
    };

    const signedUrl = await s3.getSignedUrl("getObject", s3Params);

    return { name: filename, url: signedUrl };
  };
1
  • I have my endpoint as {MY_BUCKET_NAME}.s3.{REGION}.amazonaws.com Commented Aug 22, 2020 at 22:38

1 Answer 1

1

The SDK adds the bucket name in the path because you specifically ask it to:

s3ForcePathStyle: true,

However, according to your comment, you use the bucket name in the endpoint already ("I have my endpoint as {MY_BUCKET_NAME}.s3.{REGION}.amazonaws.com") so your endpoint isn't meant to use path style...

Path style means using s3.amazonaws.com/bucket/key instead of bucket.s3.amazonaws.com/key. Forcing path style with an endpoint that actually already contains the bucket name ends up with bucket.s3.amazonaws.com/bucket/key which is interpreted as key bucket/key instead of key.

The fix should be to disable s3ForcePathStyle and instead to set s3BucketEndpoint: true because you specified an endpoint for an individual bucket.

However, in my opinion it's unnecessary to specify an endpoint in the first place - just let the SDK handle these things for you! I'd remove both s3ForcePathStyle and endpoint (then s3BucketEndpoint isn't needed either).

Sign up to request clarification or add additional context in comments.

4 Comments

That worked!!! Thank you :D I had to make 2 changes: (1) Removed the s3ForcePathStyle flag (copied that from somewhere, learned to be very selective of what arguments I choose to paste now) (2) Changed my ENDPOINT to just `s3.{REGION}.amazonaws.com (removed the leading {BUCKET_NAME})
If I didn't do #2 (with forcePathStyle disabled), it ended up requesting {BUCKET_NAME}/{BUCKET_NAME}.s3.{REGION}.amazonaws.com.
Ohh I see what you mean. I also could've done ENDPOINT = s3.{REGION}.amazonaws.com with forcePathStyle enabled. So i basicaly mixed those up, which ended up in an awkward url.
I amended my answer. It'll be best not to use any endpoint at all.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.