Ross Coundon
01/30/2021, 12:25 PMOMWGetThumbPhoto: {
handler: '.build/main/handler/someHandler.handleGetThumb',
layers: [
sharpLayerArn
],
events: [
{
http: {
method: 'get',
path: 'resourceConfig/{resourceId}/thumb',
cors: true
}
}
]
},
In the code lambda function the image is retrieved like this:
public static async getFileByName(bucket: string, name: string): Promise<AWS.S3.GetObjectOutput> {
const s3 = S3Factory.getS3();
const getObjectParams: GetObjectRequest = {
Bucket: bucket,
Key: name,
};
return s3.getObject(getObjectParams).promise();
}
The data for the response is built like this (none of the exceptions throw and image is determined to be of type image/png):
public static async getPhotoByName(name: string, fullsize = true): Promise<PhotoAndMime> {
const photoName = fullsize ? name : `${this.SMALL_PHOTO_PREFIX}${name}`;
const photo = await FileStorage.getFileByName(this.getBucketId(), photoName);
if (!photo || !photo.Body) throw new Error(`Failed to retrieve image file for photo '${photoName}'`);
let photoStr = '';
const base64Photo = photo.Body.toString('base64');
const type = await FileType.fromBuffer(photo.Body as Buffer);
if (!type) throw new Error(`Invalid or missing image type for for photo '${photoName}'`);
<http://log.info|log.info>(`File Type determined to be: ${type.mime}`);
photoStr = `data:${type.mime};base64,${base64Photo}`;
return { photo: photoStr, mimeType: type.mime };
}
Then the response is returned like this
async function handleGetCommon(event: APIGatewayProxyEvent, fullSize: boolean): Promise<APIGatewayProxyResult> {
let response: APIGatewayProxyResult;
try {
const result = await ResourcePhotoService.getPhotoById(resourceId, datasetId, fullSize);
if (result) {
response = {
statusCode: 200,
headers: { 'Content-Type': result.mimeType },
body: result.photo,
isBase64Encoded: true,
};
} else {
response = { statusCode: 204, body: '' };
}
} catch (err) {
response = HandlerUtils.handleCaughtError(err, `Could not retrieve resource config photo`);
}
Utils.addCorsHeaders(response);
return response;
}
The web application that calls the API Gateway uses axios like this:
const { data } = await axios.get(url, {
headers: {
accept: 'image/jpg, image/png',
Authorization: `Bearer ${token}`,
},
responseType: 'arraybuffer',
params,
});
and tries to process the response the data uses this function to convert the response to an image data URL
export function convertBinaryToImage(rawPhoto) {
return new Promise((resolve) => {
if (rawPhoto?.byteLength > 0) {
FileType.fromBuffer(rawPhoto).then((type) => {
const blob = new Blob([rawPhoto], { type: type.mime });
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = () => {
return resolve(reader.result); // data url
};
});
}
});
}
However it cannot determine the file type, something seems to be getting corrupted along the way. Has anyone solved the problem of retrieving a private image from an S3 bucket and return that via API Gateway to be displayed on a web page? I feel like I’m missing some serverless configuration somewhere. I’ve tried setting response.contentHandling CONVERT_TO_TEXT and CONVERT_TO_BINARY but that didn’t seem to make any difference.Ross Coundon
01/30/2021, 1:00 PMString.fromCharCode.apply(null, new Uint8Array(rawThumb))
Although, I don’t yet understand why and how this relates to how API Gateway transforms responses!Frank
Frank
Ross Coundon
01/30/2021, 5:18 PMRoss Coundon
01/30/2021, 5:19 PMFrank
Frank
Frank
Frank
new iam.PolicyStatement({
actions: ["s3:*"],
effect: iam.Effect.ALLOW,
resources: [
bucketArn + "/private/${<http://cognito-identity.amazonaws.com:sub|cognito-identity.amazonaws.com:sub>}/*",
],
})
Ross Coundon
01/30/2021, 5:27 PMFrank
Frank
Ross Coundon
01/30/2021, 5:30 PMFrank
Ross Coundon
01/30/2021, 5:31 PMFrank
action: s3:*
effect: allow
resource: [
arn:s3:...bucket1/${<http://cognito-identity.amazonaws.com:sub|cognito-identity.amazonaws.com:sub>}/*,
arn:s3:...bucket2/${<http://cognito-identity.amazonaws.com:sub|cognito-identity.amazonaws.com:sub>}/*,
...
]
Frank
Frank
${<http://cognito-identity.amazonaws.com:sub|cognito-identity.amazonaws.com:sub>}
will be the authenticated user’s Cognito Identity Pool’s user idFrank
Ross Coundon
01/30/2021, 5:35 PMFrank
Frank
Ross Coundon
01/30/2021, 5:39 PMRoss Coundon
01/30/2021, 5:43 PMFrank
Ross Coundon
01/30/2021, 5:46 PMFrank
Ross Coundon
01/30/2021, 5:46 PMPaulo
01/30/2021, 6:22 PMRoss Coundon
01/30/2021, 6:25 PMPaulo
01/30/2021, 6:36 PMRoss Coundon
01/30/2021, 6:38 PMRoss Coundon
01/30/2021, 6:40 PMRoss Coundon
01/30/2021, 6:42 PMPaulo
01/30/2021, 6:43 PMRoss Coundon
01/30/2021, 6:45 PMPaulo
01/30/2021, 6:48 PMRoss Coundon
01/30/2021, 6:50 PMPaulo
01/30/2021, 6:51 PMRoss Coundon
01/30/2021, 6:59 PMRoss Coundon
01/30/2021, 6:59 PMPaulo
01/30/2021, 7:00 PMJay
Ross Coundon
01/31/2021, 10:14 AM