I'm making a GraphQL API server with apollo-server-express.
To allow users to upload their image to S3, I made a mutation called userContentFileUpload Mutation which schema looks like:
type Mutation {
userContentFileUpload(file: File!) {
uploadUrl
fileUrl
}
}
uploadUrl
is a pre-signed S3 URL for uploading image file and fileUrl
is a S3 URL including a key which the uploaded image file will have.
So a client could use this API as follows:
uploadUrl
using fetch
or axios
.fileUrl
as remote URL of the uploaded file.Now I'm trying to add an AWS lambda function that compresses uploaded images.
The lambda function will:
However, since the upload request to uploadUrl
will be completed before the step 1 of lambda function, there will be a gap between the time that client start using fileUrl
and the time that the compressed file actually get put to the S3 bucket.
How can I fill this gap??
As far as I can tell, you have two general options now:
Those are the two options you have in all asset delivery systems. Both approaches have their advantages and disadvantages.
Since you did not provide a lot of details (image size, usage patterns etc), it is hard to say which of the two is better for you.
Therefore, I will just give you hints how both could be implemented in AWS.
If you want to compress the image when you receive it and only want to allow access to fileUrl
when the image is compressed, you could switch to Step Functions. Since a few months API Gateway allows you to send incoming requests directly to express Step Functions for processing. So you could create a Step Function that downloads the image, creates the compressed version and then returns to the caller. Obviously, this has limits. The larger the image, the longer processing might take and you might run in timeouts etc. So uploading images with 2MB, no problem. Uploading images that are 1GB large, that might become an issue.
Your second option is to compress on delivery and cache the result. If you use AWS Cloudfront, you can use Lambda@Edge to do this. But you could also use S3 Object Lambdas.
There are probably a few more options how you could build something like this. But without a lot more detail, it is hard to find the best solution for you.