I have a pre-signed S3 URL and I can't upload a video when I call this link via Axios but I can when I do it via Postman.
Presigned URL creation:
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
import { S3Client } from '@aws-sdk/client-s3';
const myClient = new S3Client(myConfig);
const commandParams: PutObjectCommandInput = {
Bucket: 'placeholder_name',
Key: 'some_key',
ContentType: `video/${contentType}`,
};
const url = await getSignedUrl(myClient, new PutObjectCommand(commandParams);, {
expiresIn: 3600,
});
/** URL goes back to the front-end, nextjs app */
return url
The URL starts with our domain name, region, etc., then the video name and all the parameters Amazon creates, the link works as you will see later on.
Then, on the front end when I call that URL like this, it fails:
uploadVideoViaPresignedUrl(urlFromServer: string, keyFromServer: string, files: File[]) {
const formData = new FormData();
for (const file of files) {
formData.append(keyFromServer, file);
}
return axios({
method: 'PUT',
url: urlFromServer
data: formData,
headers: { 'Content-Type': 'multipart/form-data' },
});
}
I tried with and without the headers, and all I get from axios is network_error
and in the browser's network tab, this PUT
request fails with NS_ERROR_DOM_BAD_URI
But then when I call the same URL in Postman, with 0 extra configurations it succeeds (notice the 200 status code) and it even uploads a new file every time to my S3 bucket (I have checked):
So, I think the issue is from my axios code, it's just a PUT request, does it need anything extra or something? any ideas? Thanks.
Edit:
You need to configure CORS on your S3 bucket and whitelist your web application's domain.
Your CORS policy could look something like this:
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"PUT"
],
"AllowedOrigins": [
"https://my-application.example.com"
]
}
]
Before issuing a PUT
request, your browser would send a separate OPTIONS
request, called "preflight", basically asking the server this:
You're not the server I loaded my JS code from, but the JS code coming from
my-application.example.com
is asking me to upload some data to you. Could you please double-check I'm not being a confused deputy?
This way, S3 knows that code loaded from my-application.example.com
has a valid use case to upload data to this bucket, and confirms the browser's preflight request.