To implement serving the images using signed URLs, we'll need to implement a couple of things. Starting from AppSync, the interesting point is the resolver for the Image.url
field. This is going to use a Lambda function and as such it needs some setup to work properly.
The first thing is a role for AppSync with permission to call the function:
Then the role has a policy with a statement:
{
"Action": "lambda:InvokeFunction",
"Effect": "Allow",
"Resource": [
"arn:aws:lambda:...:function:signer"
]
}
Next, the Lambda function needs an execution role with s3:GetObject
permission:
Finally, the Lambda function needs to know the name of the S3 bucket in an environment variable:
The resolver function for the Image.url
calls this Lambda function with the image's key. In the database, images are stored in a table that contains the userid
and the key
field:
The User.images
resolver returns the rows from this table. That means that in the Image.url
resolver, the key is accessible in the ctx.source
. The only thing that resolver needs to do is to invoke the Lambda function, passing the image key as an argument:
export function request(ctx) {
return {
version: "2018-05-29",
operation: "BatchInvoke",
payload: {
type: "download",
imageKey: ctx.source.key,
}
};
}
Note the type: "download"
argument. In the example project the same Lambda function is used for both upload and download URL signing. The type
differentiates between the two cases.
Also notice the BatchInvoke
operation. This is a performance best practice that aggregates multiple calls to the Lambda function as we've discussed in the Batching chapter.
After all this plumbing, let's move on to the more interesting part of the URL signing, to the implementation of the Lambda code!