Next.js Discord

Discord Forum

Help with S3 pre-signed URL

Answered
Olive-sided Flycatcher posted this in #help-forum
Open in Discord
Olive-sided FlycatcherOP
Hi everyone,
I'm trying to upload a file using S3 pre-signed URL and I get this error

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://... (Reason: CORS header ‘Access-Control-Allow-Origin’ missing)

I'm not sure whether the error is in the code or there's something to set on S3, code snippet wil follow
Answered by joulev
yes i believe you have to configure cors on the s3 dashboard. for example i use cloudflare r2 and have this enabled:
View full answer

8 Replies

Olive-sided FlycatcherOP
This is the code that runs on the input file change:

function uploadWithPresignedUrl(file, unique_name) {

    return new Promise((resolve, reject) => {

        // Create signature
        clientRequest('/api/create-signature', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: {
                name: unique_name,
                type: file.type
            }
        })
        .then(({uploadUrl}) => {

            // Upload URL seems OK, this generates the error
            fetch(uploadUrl, {
                method: 'PUT',
                headers: {
                    'Content-Type': file.type
                },
                body: file
            })

        })
        .then(() => {
            // Some other logic to save the file info on my DB  

        })
        .catch(err => {
            reject(err)
        })

    })
This is the create-signature api

import { S3_ACCESS_KEY_ID, S3_BUCKET_NAME, S3_ENDPOINT, S3_REGION_NAME, S3_SECRET_ACCESS_KEY } from '@/lib/constants';
import { INTERNAL_SERVER_ERROR, OK } from '@/lib/statusCode';
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
import { NextResponse } from 'next/server';

export async function POST(req){

    const body = await req.json();
    const {name, type} = body
        
    const s3 = new S3Client({
        region: S3_REGION_NAME,
        credentials: {
            accessKeyId: S3_ACCESS_KEY_ID,
            secretAccessKey: S3_SECRET_ACCESS_KEY
        },
        endpoint: S3_ENDPOINT
    });

    const params = {
        Bucket: S3_BUCKET_NAME,
        Key: name,
        ContentType: type,
    };

    try {
        const command = new PutObjectCommand(params);
        const uploadUrl = await getSignedUrl(s3, command, { expiresIn: 3600 }); // URL valid for 1 hour
        
        return NextResponse.json({ uploadUrl, name }, {status: OK});

    } catch (error) {
        return NextResponse.json({message: error.message}, {status: INTERNAL_SERVER_ERROR})
    }
};
Answer
Olive-sided FlycatcherOP
@joulev It seems to work! However I have another question: in order to solve the issue, I had to remove the Authorization Header, is it safe?

{
  "CORSRules": [
    {
      "AllowedHeaders": [
        "Authorization"
      ],
      "AllowedMethods": [
        "GET",
        "PUT"
      ],
      "AllowedOrigins": [
        "*"
      ],
      "MaxAgeSeconds": 3000,
      "ExposeHeaders": []
    }
  ]
}
@joulev what do you mean by "remove the authorization header"?
Olive-sided FlycatcherOP
I had to remove "AllowedHeaders" from the configuration
@Olive-sided Flycatcher I had to remove "AllowedHeaders" from the configuration
the examples in https://docs.aws.amazon.com/AmazonS3/latest/userguide/ManageCorsUsing.html have AllowedHeaders as * so i assume it is safe. my configuration has * also