lpares12
lpares12
CDCloudflare Developers
Created by lpares12 on 10/3/2024 in #general-help
PUT object with presigned URL sets the incorrect Type in R2 object
Hey! I'm trying to put an object to a bucket using presigned URL. But for some reason in the R2 I can always see the file type: application/x-www-form-urlencoded even when the file is a jpg, png,... This is the code I'm using in nodejs:
const config = {
header: {
'Content-Type': 'image/jpeg'
}
};

axios.put(url, photo.value, config)
.catch(error => {
console.log("Error");
});
const config = {
header: {
'Content-Type': 'image/jpeg'
}
};

axios.put(url, photo.value, config)
.catch(error => {
console.log("Error");
});
The image is correctly uploaded, but the type in the R2 bucket is wrong as explained before. If I download the image, I can open it correctly and windows shows it as a .jpg as expected. To generate the presigned URL I use python's boto3 package:
url = s3.generate_presigned_url('put_object',
Params={'Bucket': bucket_name, 'Key': object_name},
ExpiresIn=expiration,
HttpMethod='PUT')
url = s3.generate_presigned_url('put_object',
Params={'Bucket': bucket_name, 'Key': object_name},
ExpiresIn=expiration,
HttpMethod='PUT')
I saw this post of a user having a similar problem on your forums, but with no response: https://community.cloudflare.com/t/jpg-on-r2-served-with-wrong-content-type/484955/1
3 replies
CDCloudflare Developers
Created by lpares12 on 7/9/2024 in #general-help
R2: Create a presigned URL with Temporary access credentials
Hi! I'd like to know what's the proper way to create a presigned URL for an object with temporary access credentials. Is that even possible? This is my try with typescript:
export function generatePresignedURL(object: string, bucket: string, region: string, accessKeyId: string, secretAccessKey: string, sessionToken: string = ''): string {
const amzDate = new Date().toISOString().replace(/[:-]/g, '').replace(/\.\d{3}/, '');
const dateStamp = amzDate.slice(0, 8);
const algorithm: string = "AWS4-HMAC-SHA256";
const credentialScope: string = `${dateStamp}/${region}/s3/aws4_request`; // %2F is /
const expires = 3600; // 1 hour
const url: URL = new URL(`https://${import.meta.env.VITE_APP_R2_ACCOUNT_ID}.eu.r2.cloudflarestorage.com/${bucket}/${object}?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=${accessKeyId}%2F${encodeURIComponent(credentialScope)}&X-Amz-Date=${amzDate}&X-Amz-Expires=${expires}&X-Amz-SignedHeaders=host`);
if(sessionToken != '') {
url.searchParams.append('X-Amz-Security-Token', encodeURIComponent(sessionToken));
}
const host = url.hostname;
const canonicalUri = new URL(url).pathname;
const canonicalQueryString = new URL(url).searchParams.toString();
var signedHeaders = 'host';
var canonicalHeaders = `host:${host}\n`;
if(sessionToken != '') {
signedHeaders += ';x-amz-security-token';
canonicalHeaders += `x-amz-security-token:${encodeURIComponent(sessionToken)}\n`;
}
const canonicalRequest = `GET\n${canonicalUri}\n${canonicalQueryString}\n${canonicalHeaders}\n${signedHeaders}\nUNSIGNED-PAYLOAD`
const stringToSign = `AWS4-HMAC-SHA256\n${amzDate}\n${credentialScope}\n${CryptoJS.SHA256(canonicalRequest).toString()}`;
const signingKey = getSignatureKey(secretAccessKey, dateStamp, region, 's3');
const signature = CryptoJS.HmacSHA256(stringToSign, signingKey).toString();
const presignedUrl = url.toString() + `&X-Amz-Signature=${signature}`;

return presignedUrl;
}
export function generatePresignedURL(object: string, bucket: string, region: string, accessKeyId: string, secretAccessKey: string, sessionToken: string = ''): string {
const amzDate = new Date().toISOString().replace(/[:-]/g, '').replace(/\.\d{3}/, '');
const dateStamp = amzDate.slice(0, 8);
const algorithm: string = "AWS4-HMAC-SHA256";
const credentialScope: string = `${dateStamp}/${region}/s3/aws4_request`; // %2F is /
const expires = 3600; // 1 hour
const url: URL = new URL(`https://${import.meta.env.VITE_APP_R2_ACCOUNT_ID}.eu.r2.cloudflarestorage.com/${bucket}/${object}?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=${accessKeyId}%2F${encodeURIComponent(credentialScope)}&X-Amz-Date=${amzDate}&X-Amz-Expires=${expires}&X-Amz-SignedHeaders=host`);
if(sessionToken != '') {
url.searchParams.append('X-Amz-Security-Token', encodeURIComponent(sessionToken));
}
const host = url.hostname;
const canonicalUri = new URL(url).pathname;
const canonicalQueryString = new URL(url).searchParams.toString();
var signedHeaders = 'host';
var canonicalHeaders = `host:${host}\n`;
if(sessionToken != '') {
signedHeaders += ';x-amz-security-token';
canonicalHeaders += `x-amz-security-token:${encodeURIComponent(sessionToken)}\n`;
}
const canonicalRequest = `GET\n${canonicalUri}\n${canonicalQueryString}\n${canonicalHeaders}\n${signedHeaders}\nUNSIGNED-PAYLOAD`
const stringToSign = `AWS4-HMAC-SHA256\n${amzDate}\n${credentialScope}\n${CryptoJS.SHA256(canonicalRequest).toString()}`;
const signingKey = getSignatureKey(secretAccessKey, dateStamp, region, 's3');
const signature = CryptoJS.HmacSHA256(stringToSign, signingKey).toString();
const presignedUrl = url.toString() + `&X-Amz-Signature=${signature}`;

return presignedUrl;
}
22 replies