Reputation: 305
I'm trying to use an S3 to store my application images and files. The thing is that even though I am using try...catch
, if I try to fetch a file that doesn't exist, it crashes because access was denied.
This is the function I use to get the files:
export const getImage = (req: Request, res: Response, next: NextFunction) => {
try{
const key = req.query.key;
if(!key) throw new HttpException(403, 'Hubo un error al cargar la imagen');
const readStream = getFileStream(key);
if(readStream) {
readStream.pipe(res);
} else {
throw new HttpException(403, 'Hubo un error al cargar la imagen');
}
}catch(err){
next(err);
}
}
And the getFileStream function is:
export const getFileStream = (fileKey: string) => {
const downloadParams = {
Key: fileKey,
Bucket: bucketName
}
return s3.getObject(downloadParams).createReadStream();
}
The error is:
\node_modules\aws-sdk\lib\services\s3.js:718
resp.error = AWS.util.error(new Error(), {
^
AccessDenied: Access Denied
What gets node to say:
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] start: `ts-node src/app.ts`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
I tried adding try...catch
in the getFileStream
function but that didn't work either.
Nir Alfasi suggestion:
turned get Image into an async function and tried doing this:
try{
const readStream = await getFileStream(key);
if(readStream) {
readStream.pipe(res);
}
} catch(err) { console.log(err)}
Also tried not adding a second try...catch
and just using the one that is already there but didn't work either. Same error, Access Denied and crashes.
D:\Personal\Yo\Paideia\ed\TypeScript\API\node_modules\aws-sdk\lib\services\s3.js:718
resp.error = AWS.util.error(new Error(), {
^
AccessDenied: Access Denied
at Request.extractError (D:\Personal\Yo\Paideia\ed\TypeScript\API\node_modules\aws-sdk\lib\services\s3.js:718:35)
at Request.callListeners (D:\Personal\Yo\Paideia\ed\TypeScript\API\node_modules\aws-sdk\lib\sequential_executor.js:106:20)
at Request.emit (D:\Personal\Yo\Paideia\ed\TypeScript\API\node_modules\aws-sdk\lib\sequential_executor.js:78:10)
at Request.emit (D:\Personal\Yo\Paideia\ed\TypeScript\API\node_modules\aws-sdk\lib\request.js:688:14)
at Request.transition (D:\Personal\Yo\Paideia\ed\TypeScript\API\node_modules\aws-sdk\lib\request.js:22:10)
at AcceptorStateMachine.runTo (D:\Personal\Yo\Paideia\ed\TypeScript\API\node_modules\aws-sdk\lib\state_machine.js:14:12)
at D:\Personal\Yo\Paideia\ed\TypeScript\API\node_modules\aws-sdk\lib\state_machine.js:26:10
at Request.<anonymous> (D:\Personal\Yo\Paideia\ed\TypeScript\API\node_modules\aws-sdk\lib\request.js:38:9)
at Request.<anonymous> (D:\Personal\Yo\Paideia\ed\TypeScript\API\node_modules\aws-sdk\lib\request.js:690:12)
at Request.callListeners (D:\Personal\Yo\Paideia\ed\TypeScript\API\node_modules\aws-sdk\lib\sequential_executor.js:116:18)
npm ERR! errno 1
npm ERR! [email protected] start: `ts-node src/app.ts`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
Upvotes: 2
Views: 2203
Reputation: 305
Nir Alfasi helped me and I found a working answer. The 403 error gets thrown because I didn't have permissions to access a list of existing bucket items, so, if I granted my self that permission I would get a 404. Now, to handle the error I had to add an event listener:
const readStream = getFileStream(key);
if(readStream) {
readStream.createReadStream().on('error', e => {
console.log(e);
}).pipe(res);
}
And changed getFileStream
to only get the object:
export const getFileStream = (fileKey: string) => {
const downloadParams = {
Key: fileKey,
Bucket: bucketName
}
return s3.getObject(downloadParams);
}
Upvotes: 1
Reputation: 53565
createReadStream()
returns a promise, which means that we can await on it and also surround it with try/catch to handle errors.
Try changing:
const readStream = getFileStream(key);
to:
try {
const readStream = await getFileStream(key);
} catch (e) {
if (e.statusCode === 404) {
// handle item doesn't exist
// ...
}
}
Upvotes: 2