Quantcast
Channel: Recent Questions - Stack Overflow
Viewing all articles
Browse latest Browse all 12111

Unable to upload PDF to S3 bucket via presigned URL created from my Node backend

$
0
0

Scenario:

  1. Client (Nextjs client component) queries backend (NextJS rest endpoint) for pre-signed URL
  2. Backend gets presigned URL for S3 via getSignedUrl
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";import { getSignedUrl } from "@aws-sdk/s3-request-presigner";import { env } from "@/env";const AWS_REGION = "ap-southeast-2";const s3Client = new S3Client({  region: AWS_REGION,  credentials: {    accessKeyId: env.AWS_S3_ACCESS_ID,    secretAccessKey: env.AWS_S3_ACCESS_KEY,  },});const command = new PutObjectCommand({     Bucket: s3Object.bucket,     Key: s3Object.key,     // I also tried passing the contenttype here to see if it changed anything. But no it didn't.     // ContentType: s3Object.contentType,     // Might need more fields here to refine...});// Calculate dynamic expiration time based on file size, user's internet connection speed, etc.const expiresIn = calculateExpirationTime(s3Object);const presignedUrl = await getSignedUrl(s3Client, command, { expiresIn });return presignedUrl;
  1. Client receives presigned URL from backend
  2. Client sends file chunk to presigned URL
// Uploads a chunk to the presigned URLconst uploadPart = (opts: {  url: string;  chunk: Blob;  contentType: string;  chunkSize: number;  fileName: string;  maxRetries: number;}) =>  fetch(opts.url, {    method: "PUT",    body: opts.chunk,    //headers: {    //  "Content-Type": opts.contentType,    //},  })
  1. Frontend throws a CORs error:
Access to fetch at 'https://mybucket.s3.ap-southeast-2.amazonaws.com/mydoc.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AMZ_VALUE%2Fap-southeast-2%2Fs3%2Faws4_request&X-Amz-Date=20240516T010037Z&X-Amz-Expires=14400&X-Amz-Signature=SIGNATURE&X-Amz-SignedHeaders=host&x-id=PutObject' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

OPTIONS request is sent and comes back as 403 Forbidden

Request Method:OPTIONSStatus Code:403 ForbiddenRemote Address:<IP>:443Referrer Policy:strict-origin-when-cross-origin

RESPONSE HEADERS:

Content-Type:application/xmlDate:Thu, 16 May 2024 01:03:33 GMTServer:AmazonS3Transfer-Encoding:chunkedX-Amz-Id-2:<ID>X-Amz-Request-Id:<ID>

REQUEST HEADERS:

Accept:*/*Accept-Encoding:gzip, deflate, br, zstdAccept-Language:en-US,en;q=0.9Access-Control-Request-Method:PUTCache-Control:no-cacheConnection:keep-aliveHost:mybucket.s3.ap-southeast-2.amazonaws.comOrigin:http://localhost:3000Pragma:no-cacheReferer:http://localhost:3000/Sec-Fetch-Dest:emptySec-Fetch-Mode:corsSec-Fetch-Site:cross-siteUser-Agent:<AGENT>

S3 Bucket Permissions

I have configured this correctly. I have tried many different variations including explicitly defining localhost:3000 in the AllowedOrigins.

CORS settings:

[    {"AllowedHeaders": ["*"        ],"AllowedMethods": ["GET","PUT","POST","DELETE","HEAD"        ],"AllowedOrigins": ["*"        ]    }]

Policy attached to the user

The user who is generating the presigned URL has the following policy attached:

  {"Version": "2012-10-17","Statement": [      {"Action": ["s3:GetObject","s3:GetObjectVersion","s3:PutObject"        ],"Resource": ["arn:aws:s3:::mybucket","arn:aws:s3:::bmybucket/*"        ],"Effect": "Allow"      }    ]  }

I have been struggling with this one for quite some time and tried so many of the suggestions from around SO and Google. None have worked. I have a feeling I have missed some small detail and it's causing me all this grief.

Update 1

When I test the PUT command in Postman, I get the following error which is different to the CORs error:

<?xml version="1.0" encoding="UTF-8"?><Error><Code>PermanentRedirect</Code><Message>The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint.</Message><Endpoint>s3.amazonaws.com</Endpoint><Bucket>mybucket</Bucket><RequestId>__ID__</RequestId><HostId>__ID__</HostId></Error>

Viewing all articles
Browse latest Browse all 12111

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>