Writing Lambda functions for S3 Object Lambda Access Points
This section details how to write AWS Lambda functions for use with Amazon S3 Object Lambda Access Points.
To learn about complete end-to-end procedures for some S3 Object Lambda tasks, see the following:
Topics
Working with GetObject
requests in Lambda
This section assumes that your Object Lambda Access Point is configured to call the Lambda function for
GetObject
. S3 Object Lambda includes the Amazon S3 API operation,
WriteGetObjectResponse
, which enables the Lambda function to provide
customized data and response headers to the GetObject
caller.
WriteGetObjectResponse
gives you extensive control over the status code,
response headers, and response body, based on your processing needs. You can use
WriteGetObjectResponse
to respond with the whole transformed object,
portions of the transformed object, or other responses based on the context of your
application. The following section shows unique examples of using the
WriteGetObjectResponse
API operation.
-
Example 1: Respond with HTTP status code 403 (Forbidden)
-
Example 2: Respond with a transformed image
-
Example 3: Stream compressed content
Example 1: Respond with HTTP status code 403 (Forbidden)
You can use WriteGetObjectResponse
to respond with the HTTP status
code 403 (Forbidden) based on the content of the object.
Example 2: Respond with a transformed image
When performing an image transformation, you might find that you need all the
bytes of the source object before you can start processing them. In this case, your
WriteGetObjectResponse
request returns the whole object to the
requesting application in one call.
Example 3: Stream compressed content
When you're compressing objects, compressed data is produced incrementally.
Consequently, you can use your WriteGetObjectResponse
request to return
the compressed data as soon as it's ready. As shown in this example, you don't need
to know the length of the completed transformation.
Note
Although S3 Object Lambda allows up to 60 seconds to send a complete response to the
caller through the WriteGetObjectResponse
request, the actual amount of
time available might be less. For example, your Lambda function timeout might be less
than 60 seconds. In other cases, the caller might have more stringent timeouts.
For the original caller to receive a response other than HTTP status code 500
(Internal Server Error), the WriteGetObjectResponse
call must be completed.
If the Lambda function returns, with an exception or otherwise, before the
WriteGetObjectResponse
API operation is called, the original caller
receives a 500 (Internal Server Error) response. Exceptions thrown during the time it
takes to complete the response result in truncated responses to the caller. If the Lambda
function receives an HTTP status code 200 (OK) response from the
WriteGetObjectResponse
API call, then the original caller has sent the
complete request. The Lambda function's response, whether an exception is thrown or not,
is ignored by S3 Object Lambda.
When calling the WriteGetObjectResponse
API operation, Amazon S3 requires
the route and request token from the event context. For more information, see Event context format and usage.
The route and request token parameters are required to connect the
WriteGetObjectResult
response with the original caller. Even though it
is always appropriate to retry 500 (Internal Server Error) responses, because the
request token is a single-use token, subsequent attempts to use it might result in HTTP
status code 400 (Bad Request) responses. Although the call to
WriteGetObjectResponse
with the route and request tokens doesn't need
to be made from the invoked Lambda function, it must be made by an identity in the same
account. The call also must be completed before the Lambda function finishes
execution.
Working with HeadObject
requests in
Lambda
This section assumes that your Object Lambda Access Point is configured to call the Lambda function for
HeadObject
. Lambda will receive a JSON payload that contains a key
called headObjectContext
. Inside the context, there is a single property
called inputS3Url
, which is a presigned URL for the supporting access point for
HeadObject
.
The presigned URL will include the following properties if they're specified:
-
versionId
(in the query parameters) -
requestPayer
(in thex-amz-request-payer
header) -
expectedBucketOwner
(in thex-amz-expected-bucket-owner
header)
Other properties won't be presigned, and thus won't be included. Non-signed options
sent as headers can be added manually to the request when calling the presigned URL
that's found in the userRequest
headers. Server-side encryption options are
not supported for HeadObject
.
For the request syntax URI parameters, see HeadObject
in
the Amazon Simple Storage Service API Reference.
The following example shows a Lambda JSON input payload for
HeadObject
.
{ "xAmzRequestId": "
requestId
", "**headObjectContext**": { "**inputS3Url**": "https://my-s3-ap-111122223333
.s3-accesspoint.us-east-1
.amazonaws.com/example?X-Amz-Security-Token=<snip>" }, "configuration": { "accessPointArn": "arn:aws:s3-object-lambda:us-east-1
:111122223333
:accesspoint/example-object-lambda-ap
", "supportingAccessPointArn": "arn:aws:s3:us-east-1
:111122223333
:accesspoint/example-ap
", "payload": "{}" }, "userRequest": { "url": "https://object-lambda-111122223333
.s3-object-lambda.us-east-1
.amazonaws.com/example
", "headers": { "Host": "object-lambda-111122223333
.s3-object-lambda.us-east-1
.amazonaws.com", "Accept-Encoding": "identity", "X-Amz-Content-SHA256": "e3b0c44298fc1example
" } }, "userIdentity": { "type": "AssumedRole", "principalId": "principalId
", "arn": "arn:aws:sts::111122223333
:assumed-role/Admin/example
", "accountId": "111122223333
", "accessKeyId": "accessKeyId
", "sessionContext": { "attributes": { "mfaAuthenticated": "false", "creationDate": "Wed Mar 10 23:41:52 UTC 2021" }, "sessionIssuer": { "type": "Role", "principalId": "principalId
", "arn": "arn:aws:iam::111122223333
:role/Admin", "accountId": "111122223333
", "userName": "Admin" } } }, "protocolVersion": "1.00" }
Your Lambda function should return a JSON object that contains the headers and
values that will be returned for the HeadObject
call.
The following example shows the structure of the Lambda response JSON for
HeadObject
.
{ "statusCode": <number>; // Required "errorCode": <string>; "errorMessage": <string>; "headers": { "Accept-Ranges": <string>, "x-amz-archive-status": <string>, "x-amz-server-side-encryption-bucket-key-enabled": <boolean>, "Cache-Control": <string>, "Content-Disposition": <string>, "Content-Encoding": <string>, "Content-Language": <string>, "Content-Length": <number>, // Required "Content-Type": <string>, "x-amz-delete-marker": <boolean>, "ETag": <string>, "Expires": <string>, "x-amz-expiration": <string>, "Last-Modified": <string>, "x-amz-missing-meta": <number>, "x-amz-object-lock-mode": <string>, "x-amz-object-lock-legal-hold": <string>, "x-amz-object-lock-retain-until-date": <string>, "x-amz-mp-parts-count": <number>, "x-amz-replication-status": <string>, "x-amz-request-charged": <string>, "x-amz-restore": <string>, "x-amz-server-side-encryption": <string>, "x-amz-server-side-encryption-customer-algorithm": <string>, "x-amz-server-side-encryption-aws-kms-key-id": <string>, "x-amz-server-side-encryption-customer-key-MD5": <string>, "x-amz-storage-class": <string>, "x-amz-tagging-count": <number>, "x-amz-version-id": <string>, <x-amz-meta-headers>: <string>, // user-defined metadata "x-amz-meta-meta1": <string>, // example of the user-defined metadata header, it will need the x-amz-meta prefix "x-amz-meta-meta2": <string> ... }; }
The following example shows how to use the presigned URL to populate your response by modifying the header values as needed before returning the JSON.
Working with ListObjects
requests in
Lambda
This section assumes that your Object Lambda Access Point is configured to call the Lambda function for
ListObjects
. Lambda will receive the JSON payload with a new object
named listObjectsContext
. listObjectsContext
contains a single
property, inputS3Url
, which is a presigned URL for the supporting access point for
ListObjects
.
Unlike GetObject
and HeadObject
, the presigned URL will
include the following properties if they're specified:
-
All the query parameters
-
requestPayer
(in thex-amz-request-payer
header) -
expectedBucketOwner
(in thex-amz-expected-bucket-owner
header)
For the request syntax URI parameters, see ListObjects
in
the Amazon Simple Storage Service API Reference.
Important
We recommend that you use the newer version, ListObjectsV2, when
developing applications. For backward compatibility, Amazon S3 continues to support
ListObjects
.
The following example shows the Lambda JSON input payload for
ListObjects
.
{ "xAmzRequestId": "
requestId
", "**listObjectsContext**": { "**inputS3Url**": "https://my-s3-ap-111122223333
.s3-accesspoint.us-east-1
.amazonaws.com/?X-Amz-Security-Token=<snip>", }, "configuration": { "accessPointArn": "arn:aws:s3-object-lambda:us-east-1
:111122223333
:accesspoint/example-object-lambda-ap
", "supportingAccessPointArn": "arn:aws:s3:us-east-1
:111122223333
:accesspoint/example-ap
", "payload": "{}" }, "userRequest": { "url": "https://object-lambda-111122223333
.s3-object-lambda.us-east-1
.amazonaws.com/example
", "headers": { "Host": "object-lambda-111122223333
.s3-object-lambda.us-east-1
.amazonaws.com", "Accept-Encoding": "identity", "X-Amz-Content-SHA256": "e3b0c44298fc1example
" } }, "userIdentity": { "type": "AssumedRole", "principalId": "principalId
", "arn": "arn:aws:sts::111122223333
:assumed-role/Admin/example
", "accountId": "111122223333
", "accessKeyId": "accessKeyId
", "sessionContext": { "attributes": { "mfaAuthenticated": "false", "creationDate": "Wed Mar 10 23:41:52 UTC 2021" }, "sessionIssuer": { "type": "Role", "principalId": "principalId
", "arn": "arn:aws:iam::111122223333
:role/Admin", "accountId": "111122223333
", "userName": "Admin" } } }, "protocolVersion": "1.00" }
Your Lambda function should return a JSON object that contains the status code, list XML result, or error information that will be returned from S3 Object Lambda.
S3 Object Lambda does not process or validate listResultXml
, but instead forwards it
to ListObjects
caller. For listBucketResult
, S3 Object Lambda expects certain properties
to be of a specific type and will throw exceptions if it cannot parse them. listResultXml
and
listBucketResult
can not be provided at the same time.
The following example demonstrates how to use the presigned URL to call Amazon S3 and use the result to populate a response, including error checking.
The following example shows the structure of the Lambda response JSON for
ListObjects
.
{ "statusCode": <number>; // Required "errorCode": <string>; "errorMessage": <string>; "listResultXml": <string>; // This can also be Error XML string in case S3 returned error response when calling the pre-signed URL "listBucketResult": { // listBucketResult can be provided instead of listResultXml, however they can not both be provided in the JSON response "name": <string>, // Required for 'listBucketResult' "prefix": <string>, "marker": <string>, "nextMarker": <string>, "maxKeys": <int>, // Required for 'listBucketResult' "delimiter": <string>, "encodingType": <string> "isTruncated": <boolean>, // Required for 'listBucketResult' "contents": [ { "key": <string>, // Required for 'content' "lastModified": <string>, "eTag": <string>, "checksumAlgorithm": <string>, // CRC32, CRC32C, SHA1, SHA256 "size": <int>, // Required for 'content' "owner": { "displayName": <string>, // Required for 'owner' "id": <string>, // Required for 'owner' }, "storageClass": <string> }, ... ], "commonPrefixes": [ { "prefix": <string> // Required for 'commonPrefix' }, ... ], } }
Working with ListObjectsV2
requests in Lambda
This section assumes that your Object Lambda Access Point is configured to call the Lambda function for
ListObjectsV2
. Lambda will receive the JSON payload with a new object
named listObjectsV2Context
. listObjectsV2Context
contains a
single property, inputS3Url
, which is a presigned URL for the supporting
access point for ListObjectsV2
.
Unlike GetObject
and HeadObject
, the presigned URL will
include the following properties, if they're specified:
-
All the query parameters
-
requestPayer
(in thex-amz-request-payer
header) -
expectedBucketOwner
(in thex-amz-expected-bucket-owner
header)
For the request syntax URI parameters, see ListObjectsV2
in the Amazon Simple Storage Service API Reference.
The following example shows the Lambda JSON input payload for
ListObjectsV2
.
{ "xAmzRequestId": "
requestId
", "**listObjectsV2Context**": { "**inputS3Url**": "https://my-s3-ap-111122223333
.s3-accesspoint.us-east-1
.amazonaws.com/?list-type=2&X-Amz-Security-Token=<snip>", }, "configuration": { "accessPointArn": "arn:aws:s3-object-lambda:us-east-1
:111122223333
:accesspoint/example-object-lambda-ap
", "supportingAccessPointArn": "arn:aws:s3:us-east-1
:111122223333
:accesspoint/example-ap
", "payload": "{}" }, "userRequest": { "url": "https://object-lambda-111122223333
.s3-object-lambda.us-east-1
.amazonaws.com/example
", "headers": { "Host": "object-lambda-111122223333
.s3-object-lambda.us-east-1
.amazonaws.com", "Accept-Encoding": "identity", "X-Amz-Content-SHA256": "e3b0c44298fc1example
" } }, "userIdentity": { "type": "AssumedRole", "principalId": "principalId
", "arn": "arn:aws:sts::111122223333
:assumed-role/Admin/example
", "accountId": "111122223333
", "accessKeyId": "accessKeyId
", "sessionContext": { "attributes": { "mfaAuthenticated": "false", "creationDate": "Wed Mar 10 23:41:52 UTC 2021" }, "sessionIssuer": { "type": "Role", "principalId": "principalId
", "arn": "arn:aws:iam::111122223333
:role/Admin", "accountId": "111122223333
", "userName": "Admin" } } }, "protocolVersion": "1.00" }
Your Lambda function should return a JSON object that contains the status code, list XML result, or error information that will be returned from S3 Object Lambda.
S3 Object Lambda does not process or validate listResultXml
, but instead forwards it
to ListObjectsV2
caller. For listBucketResult
, S3 Object Lambda expects certain properties
to be of a specific type and will throw exceptions if it cannot parse them. listResultXml
and
listBucketResult
can not be provided at the same time.
The following example demonstrates how to use the presigned URL to call Amazon S3 and use the result to populate a response, including error checking.
The following example shows the structure of the Lambda response JSON for
ListObjectsV2
.
{ "statusCode": <number>; // Required "errorCode": <string>; "errorMessage": <string>; "listResultXml": <string>; // This can also be Error XML string in case S3 returned error response when calling the pre-signed URL "listBucketResult": { // listBucketResult can be provided instead of listResultXml, however they can not both be provided in the JSON response "name": <string>, // Required for 'listBucketResult' "prefix": <string>, "startAfter": <string>, "continuationToken": <string>, "nextContinuationToken": <string>, "keyCount": <int>, // Required for 'listBucketResult' "maxKeys": <int>, // Required for 'listBucketResult' "delimiter": <string>, "encodingType": <string> "isTruncated": <boolean>, // Required for 'listBucketResult' "contents": [ { "key": <string>, // Required for 'content' "lastModified": <string>, "eTag": <string>, "checksumAlgorithm": <string>, // CRC32, CRC32C, SHA1, SHA256 "size": <int>, // Required for 'content' "owner": { "displayName": <string>, // Required for 'owner' "id": <string>, // Required for 'owner' }, "storageClass": <string> }, ... ], "commonPrefixes": [ { "prefix": <string> // Required for 'commonPrefix' }, ... ], } }