

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

# Écriture de fonctions Lambda pour les points d’accès S3 Object Lambda
<a name="olap-writing-lambda"></a>

**Note**  
Depuis le 7 novembre 2025, S3 Object Lambda n'est disponible que pour les clients existants qui utilisent actuellement le service, ainsi que pour certains AWS partenaires du réseau de partenaires (APN). Pour des fonctionnalités semblables à celles de S3 Object Lambda, cliquez ici : [Modification de la disponibilité d’Amazon S3 Object Lambda](https://docs.aws.amazon.com/AmazonS3/latest/userguide/amazons3-ol-change.html).

Cette section explique comment écrire des AWS Lambda fonctions à utiliser avec les points d'accès Amazon S3 Object Lambda.

Pour en savoir plus sur end-to-end les procédures complètes relatives à certaines tâches S3 Object Lambda, consultez les rubriques suivantes :
+ [Didacticiel : Transformation de données pour votre application avec S3 Object Lambda](tutorial-s3-object-lambda-uppercase.md)
+ [Didacticiel : Détecter et expurger des PII avec S3 Object Lambda et Amazon Comprehend](tutorial-s3-object-lambda-redact-pii.md)
+ [Tutoriel : Utilisation de S3 Object Lambda pour filigraner dynamiquement des images au fur et à mesure de leur récupération](https://aws.amazon.com/getting-started/hands-on/amazon-s3-object-lambda-to-dynamically-watermark-images/?ref=docs_gateway/amazons3/olap-writing-lambda.html)

**Topics**
+ [

## Utilisation de requêtes `GetObject` dans Lambda
](#olap-getobject-response)
+ [

## Utilisation de requêtes `HeadObject` dans Lambda
](#olap-headobject)
+ [

## Utilisation de requêtes `ListObjects` dans Lambda
](#olap-listobjects)
+ [

## Utilisation de requêtes `ListObjectsV2` dans Lambda
](#olap-listobjectsv2)
+ [

# Format et utilisation du contexte d’événement
](olap-event-context.md)
+ [

# Utilisation des en-têtes Range et partNumber
](range-get-olap.md)

## Utilisation de requêtes `GetObject` dans Lambda
<a name="olap-getobject-response"></a>

Cette section suppose que votre point d’accès Object Lambda est configuré pour appeler la fonction Lambda pour `GetObject`. S3 Object Lambda inclut l’opération d’API Amazon S3, `WriteGetObjectResponse`, qui permet à la fonction Lambda de fournir des données personnalisées et des en-têtes de réponse à l’appelant `GetObject`. 

`WriteGetObjectResponse` vous offre un contrôle étendu sur le code de statut, les en-têtes de réponse et le corps de réponse, en fonction de vos besoins de traitement. Vous pouvez utiliser `WriteGetObjectResponse` pour répondre avec l’ensemble de l’objet transformé, des parties de l’objet transformé ou d’autres réponses basées sur le contexte de votre application. La section suivante présente des exemples uniques d’utilisation de l’opération d’API `WriteGetObjectResponse`.
+ **Exemple 1 :** répondre avec un code de statut HTTP 403 (Interdit) 
+ **Exemple 2 :** répondre avec une image transformée
+ **Exemple 3 :** diffuser du contenu compressé

**Exemple 1 : répondre avec un code de statut HTTP 403 (Interdit) **

Vous pouvez utiliser `WriteGetObjectResponse` pour répondre avec le code d’état HTTP 403 (Interdit) en fonction du contenu de l’objet.

------
#### [ Java ]



```
package com.amazon.s3.objectlambda;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.events.S3ObjectLambdaEvent;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.WriteGetObjectResponseRequest;

import java.io.ByteArrayInputStream;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class Example1 {

    public void handleRequest(S3ObjectLambdaEvent event, Context context) throws Exception {
        S3Client s3Client = S3Client.builder().build();

        // Check to see if the request contains all of the necessary information.
        // If it does not, send a 4XX response and a custom error code and message.
        // Otherwise, retrieve the object from S3 and stream it
        // to the client unchanged.
        var tokenIsNotPresent = !event.getUserRequest().getHeaders().containsKey("requiredToken");
        if (tokenIsNotPresent) {
            s3Client.writeGetObjectResponse(WriteGetObjectResponseRequest.builder()
                    .requestRoute(event.outputRoute())
                    .requestToken(event.outputToken())
                    .statusCode(403)
                    .contentLength(0L)
                    .errorCode("MissingRequiredToken")
                    .errorMessage("The required token was not present in the request.")
                    .build(),
                    RequestBody.fromInputStream(new ByteArrayInputStream(new byte[0]), 0L));
            return;
        }

        // Prepare the presigned URL for use and make the request to S3.
        HttpClient httpClient = HttpClient.newBuilder().build();
        var presignedResponse = httpClient.send(
                HttpRequest.newBuilder(new URI(event.inputS3Url())).GET().build(),
                HttpResponse.BodyHandlers.ofInputStream());

        // Stream the original bytes back to the caller.
        s3Client.writeGetObjectResponse(WriteGetObjectResponseRequest.builder()
                .requestRoute(event.outputRoute())
                .requestToken(event.outputToken())
                .build(),
                RequestBody.fromInputStream(presignedResponse.body(),
                    presignedResponse.headers().firstValueAsLong("content-length").orElse(-1L)));
    }
}
```

------
#### [ Python ]



```
import boto3
import requests 

def handler(event, context):
    s3 = boto3.client('s3')

    """
    Retrieve the operation context object from the event. This object indicates where the WriteGetObjectResponse request
    should be delivered and contains a presigned URL in 'inputS3Url' where we can download the requested object from.
    The 'userRequest' object has information related to the user who made this 'GetObject' request to 
    S3 Object Lambda.
    """
    get_context = event["getObjectContext"]
    user_request_headers = event["userRequest"]["headers"]

    route = get_context["outputRoute"]
    token = get_context["outputToken"]
    s3_url = get_context["inputS3Url"]

    # Check for the presence of a 'CustomHeader' header and deny or allow based on that header.
    is_token_present = "SuperSecretToken" in user_request_headers

    if is_token_present:
        # If the user presented our custom 'SuperSecretToken' header, we send the requested object back to the user.
        response = requests.get(s3_url)
        s3.write_get_object_response(RequestRoute=route, RequestToken=token, Body=response.content)
    else:
        # If the token is not present, we send an error back to the user. 
        s3.write_get_object_response(RequestRoute=route, RequestToken=token, StatusCode=403,
        ErrorCode="NoSuperSecretTokenFound", ErrorMessage="The request was not secret enough.")

    # Gracefully exit the Lambda function.
    return { 'status_code': 200 }
```

------
#### [ Node.js ]



```
const { S3 } = require('aws-sdk');
const axios = require('axios').default;

exports.handler = async (event) => {
    const s3 = new S3();

    // Retrieve the operation context object from the event. This object indicates where the WriteGetObjectResponse request
    // should be delivered and contains a presigned URL in 'inputS3Url' where we can download the requested object from.
    // The 'userRequest' object has information related to the user who made this 'GetObject' request to S3 Object Lambda.
    const { userRequest, getObjectContext } = event;
    const { outputRoute, outputToken, inputS3Url } = getObjectContext;

    // Check for the presence of a 'CustomHeader' header and deny or allow based on that header.
    const isTokenPresent = Object
        .keys(userRequest.headers)
        .includes("SuperSecretToken");

    if (!isTokenPresent) {
        // If the token is not present, we send an error back to the user. The 'await' in front of the request
        // indicates that we want to wait for this request to finish sending before moving on. 
        await s3.writeGetObjectResponse({
            RequestRoute: outputRoute,
            RequestToken: outputToken,
            StatusCode: 403,
            ErrorCode: "NoSuperSecretTokenFound",
            ErrorMessage: "The request was not secret enough.",
        }).promise();
    } else {
        // If the user presented our custom 'SuperSecretToken' header, we send the requested object back to the user.
        // Again, note the presence of 'await'.
        const presignedResponse = await axios.get(inputS3Url);
        await s3.writeGetObjectResponse({
            RequestRoute: outputRoute,
            RequestToken: outputToken,
            Body: presignedResponse.data,
        }).promise();
    }

    // Gracefully exit the Lambda function.
    return { statusCode: 200 };
}
```

------

**Exemple 2 :** répondre avec une image transformée

Lorsque vous effectuez une transformation d’image, vous pouvez constater que vous avez besoin de tous les octets de l’objet source avant de pouvoir commencer à les traiter. Dans ce cas, votre demande `WriteGetObjectResponse` renvoie l’objet entier à l’application requérante en un seul appel.

------
#### [ Java ]



```
package com.amazon.s3.objectlambda;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.events.S3ObjectLambdaEvent;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.WriteGetObjectResponseRequest;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.Image;
import java.io.ByteArrayOutputStream;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class Example2V2 {

    private static final int HEIGHT = 250;
    private static final int WIDTH = 250;

    public void handleRequest(S3ObjectLambdaEvent event, Context context) throws Exception {
        S3Client s3Client = S3Client.builder().build();
        HttpClient httpClient = HttpClient.newBuilder().build();

        // Prepare the presigned URL for use and make the request to S3.
        var presignedResponse = httpClient.send(
                HttpRequest.newBuilder(new URI(event.inputS3Url())).GET().build(),
                HttpResponse.BodyHandlers.ofInputStream());

        // The entire image is loaded into memory here so that we can resize it.
        // Once the resizing is completed, we write the bytes into the body
        // of the WriteGetObjectResponse request.
        var originalImage = ImageIO.read(presignedResponse.body());
        var resizingImage = originalImage.getScaledInstance(WIDTH, HEIGHT, Image.SCALE_DEFAULT);
        var resizedImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
        resizedImage.createGraphics().drawImage(resizingImage, 0, 0, WIDTH, HEIGHT, null);

        var baos = new ByteArrayOutputStream();
        ImageIO.write(resizedImage, "png", baos);

        // Stream the bytes back to the caller.
        s3Client.writeGetObjectResponse(WriteGetObjectResponseRequest.builder()
                .requestRoute(event.outputRoute())
                .requestToken(event.outputToken())
                .build(), RequestBody.fromBytes(baos.toByteArray()));
    }
}
```

------
#### [ Python ]



```
import boto3
import requests 
import io
from PIL import Image

def handler(event, context):
    """
    Retrieve the operation context object from the event. This object indicates where the WriteGetObjectResponse request
    should be delivered and has a presigned URL in 'inputS3Url' where we can download the requested object from.
    The 'userRequest' object has information related to the user who made this 'GetObject' request to 
    S3 Object Lambda.
    """
    get_context = event["getObjectContext"]
    route = get_context["outputRoute"]
    token = get_context["outputToken"]
    s3_url = get_context["inputS3Url"]

    """
    In this case, we're resizing .png images that are stored in S3 and are accessible through the presigned URL
    'inputS3Url'.
    """
    image_request = requests.get(s3_url)
    image = Image.open(io.BytesIO(image_request.content))
    image.thumbnail((256,256), Image.ANTIALIAS)

    transformed = io.BytesIO()
    image.save(transformed, "png")

    # Send the resized image back to the client.
    s3 = boto3.client('s3')
    s3.write_get_object_response(Body=transformed.getvalue(), RequestRoute=route, RequestToken=token)

    # Gracefully exit the Lambda function.
    return { 'status_code': 200 }
```

------
#### [ Node.js ]



```
const { S3 } = require('aws-sdk');
const axios = require('axios').default;
const sharp = require('sharp');

exports.handler = async (event) => {
    const s3 = new S3();

    // Retrieve the operation context object from the event. This object indicates where the WriteGetObjectResponse request
    // should be delivered and has a presigned URL in 'inputS3Url' where we can download the requested object from.
    const { getObjectContext } = event;
    const { outputRoute, outputToken, inputS3Url } = getObjectContext;

    // In this case, we're resizing .png images that are stored in S3 and are accessible through the presigned URL
    // 'inputS3Url'.
    const { data } = await axios.get(inputS3Url, { responseType: 'arraybuffer' });

    // Resize the image.
    const resized = await sharp(data)
        .resize({ width: 256, height: 256 })
        .toBuffer();

    // Send the resized image back to the client.
    await s3.writeGetObjectResponse({
        RequestRoute: outputRoute,
        RequestToken: outputToken,
        Body: resized,
    }).promise();

    // Gracefully exit the Lambda function.
    return { statusCode: 200 };
}
```

------

**Exemple 3 :** diffuser du contenu compressé

Lorsque vous compressez des objets, les données compressées sont produites de manière incrémentielle. Par conséquent, vous pouvez utiliser votre demande `WriteGetObjectResponse` pour renvoyer les données compressées dès qu’elles sont prêtes. Comme le montre cet exemple, vous n’avez pas besoin de connaître la longueur de la transformation terminée.

------
#### [ Java ]



```
package com.amazon.s3.objectlambda;

import com.amazonaws.services.lambda.runtime.events.S3ObjectLambdaEvent;
import com.amazonaws.services.lambda.runtime.Context;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.WriteGetObjectResponseRequest;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class Example3 {

    public void handleRequest(S3ObjectLambdaEvent event, Context context) throws Exception {
        S3Client s3Client = S3Client.builder().build();
        HttpClient httpClient = HttpClient.newBuilder().build();

        // Request the original object from S3.
        var presignedResponse = httpClient.send(
                HttpRequest.newBuilder(new URI(event.inputS3Url())).GET().build(),
                HttpResponse.BodyHandlers.ofInputStream());

        // Consume the incoming response body from the presigned request,
        // apply our transformation on that data, and emit the transformed bytes
        // into the body of the WriteGetObjectResponse request as soon as they're ready.
        // This example compresses the data from S3, but any processing pertinent
        // to your application can be performed here.
        var bodyStream = new GZIPCompressingInputStream(presignedResponse.body());

        // Stream the bytes back to the caller.
        s3Client.writeGetObjectResponse(WriteGetObjectResponseRequest.builder()
                .requestRoute(event.outputRoute())
                .requestToken(event.outputToken())
                .build(),
                RequestBody.fromInputStream(bodyStream,
                    presignedResponse.headers().firstValueAsLong("content-length").orElse(-1L)));
    }
}
```

------
#### [ Python ]



```
import boto3
import requests
import zlib
from botocore.config import Config


"""
A helper class to work with content iterators. Takes an interator and compresses the bytes that come from it. It
implements 'read' and '__iter__' so that the SDK can stream the response. 
"""
class Compress:
    def __init__(self, content_iter):
        self.content = content_iter
        self.compressed_obj = zlib.compressobj()

    def read(self, _size):
        for data in self.__iter__()
            return data

    def __iter__(self):
        while True:
            data = next(self.content)
            chunk = self.compressed_obj.compress(data)
            if not chunk:
                break

            yield chunk

        yield self.compressed_obj.flush()


def handler(event, context):
    """
    Setting the 'payload_signing_enabled' property to False allows us to send a streamed response back to the client.
    in this scenario, a streamed response means that the bytes are not buffered into memory as we're compressing them,
    but instead are sent straight to the user.
    """
    my_config = Config(
        region_name='eu-west-1',
        signature_version='s3v4',
        s3={
            "payload_signing_enabled": False
        }
    )
    s3 = boto3.client('s3', config=my_config)

    """
    Retrieve the operation context object from the event. This object indicates where the WriteGetObjectResponse request
    should be delivered and has a presigned URL in 'inputS3Url' where we can download the requested object from.
    The 'userRequest' object has information related to the user who made this 'GetObject' request to S3 Object Lambda.
    """
    get_context = event["getObjectContext"]
    route = get_context["outputRoute"]
    token = get_context["outputToken"]
    s3_url = get_context["inputS3Url"]

    # Compress the 'get' request stream.
    with requests.get(s3_url, stream=True) as r:
        compressed = Compress(r.iter_content())

        # Send the stream back to the client.
        s3.write_get_object_response(Body=compressed, RequestRoute=route, RequestToken=token, ContentType="text/plain",
                                     ContentEncoding="gzip")

    # Gracefully exit the Lambda function.
    return {'status_code': 200}
```

------
#### [ Node.js ]



```
const { S3 } = require('aws-sdk');
const axios = require('axios').default;
const zlib = require('zlib');

exports.handler = async (event) => {
    const s3 = new S3();

    // Retrieve the operation context object from the event. This object indicates where the WriteGetObjectResponse request
    // should be delivered and has a presigned URL in 'inputS3Url' where we can download the requested object from.
    const { getObjectContext } = event;
    const { outputRoute, outputToken, inputS3Url } = getObjectContext;

    // Download the object from S3 and process it as a stream, because it might be a huge object and we don't want to
    // buffer it in memory. Note the use of 'await' because we want to wait for 'writeGetObjectResponse' to finish 
    // before we can exit the Lambda function. 
    await axios({
        method: 'GET',
        url: inputS3Url,
        responseType: 'stream',
    }).then(
        // Gzip the stream.
        response => response.data.pipe(zlib.createGzip())
    ).then(
        // Finally send the gzip-ed stream back to the client.
        stream => s3.writeGetObjectResponse({
            RequestRoute: outputRoute,
            RequestToken: outputToken,
            Body: stream,
            ContentType: "text/plain",
            ContentEncoding: "gzip",
        }).promise()
    );

    // Gracefully exit the Lambda function.
    return { statusCode: 200 };
}
```

------

**Note**  
Bien que S3 Object Lambda laisse jusqu’à 60 secondes pour envoyer une réponse complète à l’appelant via la demande `WriteGetObjectResponse`, le temps réel disponible peut être inférieur. Par exemple, le délai d’expiration de votre fonction Lambda peut être inférieur à 60 secondes. Dans d’autres cas, l’appelant peut avoir des délais d’attente plus stricts. 

Pour que l’appelant d’origine reçoive une réponse autre que le code de statut HTTP 500 (Erreur de serveur interne), l’appel `WriteGetObjectResponse` doit être terminé. Si la fonction Lambda renvoie une réponse, avec une exception ou autrement, avant que l’opération d’API `WriteGetObjectResponse` soit appelée, l’appelant d’origine reçoit une réponse 500 (Erreur de serveur interne). Les exceptions lancées pendant le temps nécessaire pour compléter la réponse entraînent des réponses tronquées à l’appelant. Si la fonction Lambda reçoit une réponse avec code de statut HTTP 200 (OK) de l’appel d’API `WriteGetObjectResponse`, l’appelant d’origine a envoyé la demande complète. La réponse de la fonction Lambda, qu’une exception soit déclenchée ou non, est ignorée par S3 Object Lambda.

Au moment d’appeler l’opération d’API `WriteGetObjectResponse`, Amazon S3 exige la route et le jeton de demande du contexte d’événement. Pour plus d’informations, consultez [Format et utilisation du contexte d’événement](olap-event-context.md).

Les paramètres de route et de jeton de demande sont nécessaires pour connecter la réponse `WriteGetObjectResult` à l’appelant d’origine. Bien qu’il soit toujours approprié de réessayer les réponses 500 (Erreur de serveur interne), car le jeton de demande est un jeton à usage unique, les tentatives ultérieures de l’utiliser peuvent entraîner des réponses avec code de statut HTTP 400 (Demande incorrecte). Bien que l’appel à `WriteGetObjectResponse` avec la route et les jetons de demande n’ait pas besoin d’être réalisé à partir de la fonction Lambda invoquée, il doit être réalisé par une identité figurant dans le même compte. L’appel doit également être terminé avant que la fonction Lambda ne termine l’exécution.

## Utilisation de requêtes `HeadObject` dans Lambda
<a name="olap-headobject"></a>

Cette section suppose que votre point d'accès Object Lambda est configuré pour appeler la fonction Lambda pour `HeadObject`. Lambda recevra une charge utile JSON contenant une clé appelée `headObjectContext`. Dans le contexte, il existe une propriété unique appelée `inputS3Url`, qui est une URL présignée pour le point d’accès de prise en charge pour `HeadObject`.

L’URL présignée inclura les propriétés suivantes si elles sont spécifiées : 
+ `versionId` (dans les paramètres de la requête)
+ `requestPayer` (dans l’en-tête `x-amz-request-payer`)
+ `expectedBucketOwner` (dans l'en-tête `x-amz-expected-bucket-owner`)

Les autres propriétés ne seront pas présignées et ne seront donc pas incluses. Les options non signées envoyées sous forme d’en-têtes peuvent être ajoutées manuellement à la demande lors de l’appel de l’URL présignée qui se trouve dans les en-têtes `userRequest`. Les options de chiffrement côté serveur ne sont pas prises en charge pour `HeadObject`.

Pour les paramètres d’URI de la syntaxe de la demande, consultez [https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html) dans la *Référence des API Amazon Simple Storage Service*.

L’exemple suivant illustre une charge utile d’entrée JSON de Lambda pour `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"
}
```

Votre fonction Lambda doit renvoyer un objet JSON contenant les en-têtes et les valeurs qui seront renvoyés pour l’appel `HeadObject`.

L’exemple suivant illustre la structure du code JSON de réponse de Lambda pour `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>
        ...
    };
}
```

L’exemple suivant montre comment utiliser l’URL pré-signée pour renseigner votre réponse en modifiant les valeurs d’en-tête selon les besoins avant de renvoyer le code JSON.

------
#### [ Python ]



```
import requests

def lambda_handler(event, context):
    print(event)
    
    # Extract the presigned URL from the input.
    s3_url = event["headObjectContext"]["inputS3Url"]

    # Get the head of the object from S3.     
    response = requests.head(s3_url)
    
    # Return the error to S3 Object Lambda (if applicable).           
    if (response.status_code >= 400):
        return {
            "statusCode": response.status_code,
            "errorCode": "RequestFailure",                         
            "errorMessage": "Request to S3 failed"    
    }
    
    # Store the headers in a dictionary.
    response_headers = dict(response.headers)

    # This obscures Content-Type in a transformation, it is optional to add
    response_headers["Content-Type"] = "" 

    # Return the headers to S3 Object Lambda.     
    return {
        "statusCode": response.status_code,
        "headers": response_headers     
        }
```

------

## Utilisation de requêtes `ListObjects` dans Lambda
<a name="olap-listobjects"></a>

Cette section suppose que votre point d'accès Object Lambda est configuré pour appeler la fonction Lambda pour `ListObjects`. Lambda recevra la charge utile JSON avec un nouvel objet nommé `listObjectsContext`. `listObjectsContext` contient une propriété unique, `inputS3Url`, qui est une URL pré-signée pour le point d’accès de prise en charge pour `ListObjects`.

Contrairement à `GetObject` et `HeadObject`, l’URL pré-signée inclura les propriétés suivantes si elles sont spécifiées :
+ Tous les paramètres de la requête
+ `requestPayer` (dans l'en-tête `x-amz-request-payer`) 
+ `expectedBucketOwner` (dans l'en-tête `x-amz-expected-bucket-owner`)

Pour les paramètres d'URI de la syntaxe de la demande, consultez [https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html) dans la *Référence des API Amazon Simple Storage Service*.

**Important**  
Nous vous recommandons d'utiliser la version la plus récente, [ListObjectsV2](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html), lorsque vous développez des applications. Pour assurer la compatibilité descendante, Amazon S3 continue de prendre en charge `ListObjects`.

L’exemple suivant illustre la charge utile d’entrée JSON de Lambda pour `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"
}
```

Votre fonction Lambda devrait renvoyer un objet JSON contenant le code de statut, le résultat XML de liste ou les informations d’erreur qui seront renvoyées de S3 Object Lambda.

S3 Object Lambda ne traite ni ne valide `listResultXml`, mais les transmet à l’appelant `ListObjects`. Pour `listBucketResult`, S3 Object Lambda s’attend à ce que certaines propriétés soient d’un type spécifique et lèvera des exceptions s’il ne peut pas les analyser. `listResultXml` et `listBucketResult` ne peuvent pas être fournies en même temps.

L’exemple suivant montre comment utiliser l’URL pré-signée pour appeler Amazon S3 et comment utiliser le résultat pour renseigner une réponse ainsi que vérifier les erreurs.

------
#### [ Python ]

```
import requests 
import xmltodict

def lambda_handler(event, context):
    # Extract the presigned URL from the input.
    s3_url = event["listObjectsContext"]["inputS3Url"]


    # Get the head of the object from Amazon S3.
    response = requests.get(s3_url)

    # Return the error to S3 Object Lambda (if applicable).
    if (response.status_code >= 400):
        error = xmltodict.parse(response.content)
        return {
            "statusCode": response.status_code,
            "errorCode": error["Error"]["Code"],
            "errorMessage": error["Error"]["Message"]
        }

    # Store the XML result in a dict.
    response_dict = xmltodict.parse(response.content)

    # This obscures StorageClass in a transformation, it is optional to add
    for item in response_dict['ListBucketResult']['Contents']:
        item['StorageClass'] = ""

    # Convert back to XML.
    listResultXml = xmltodict.unparse(response_dict)
    
    # Create response with listResultXml.
    response_with_list_result_xml = {
        'statusCode': 200,
        'listResultXml': listResultXml
    }

    # Create response with listBucketResult.
    response_dict['ListBucketResult'] = sanitize_response_dict(response_dict['ListBucketResult'])
    response_with_list_bucket_result = {
        'statusCode': 200,
        'listBucketResult': response_dict['ListBucketResult']
    }

    # Return the list to S3 Object Lambda.
    # Can return response_with_list_result_xml or response_with_list_bucket_result
    return response_with_list_result_xml

# Converting the response_dict's key to correct casing
def sanitize_response_dict(response_dict: dict):
    new_response_dict = dict()
    for key, value in response_dict.items():
        new_key = key[0].lower() + key[1:] if key != "ID" else 'id'
        if type(value) == list:
            newlist = []
            for element in value:
                if type(element) == type(dict()):
                    element = sanitize_response_dict(element)
                newlist.append(element)
            value = newlist
        elif type(value) == dict:
            value = sanitize_response_dict(value)
        new_response_dict[new_key] = value
    return new_response_dict
```

------

L'exemple suivant illustre la structure du code JSON de réponse de Lambda pour `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'
        },  
        ...  
        ],  
    }
}
```

## Utilisation de requêtes `ListObjectsV2` dans Lambda
<a name="olap-listobjectsv2"></a>

Cette section suppose que votre point d'accès Object Lambda est configuré pour appeler la fonction Lambda pour `ListObjectsV2`. Lambda recevra la charge utile JSON avec un nouvel objet nommé `listObjectsV2Context`. `listObjectsV2Context` contient une propriété unique, `inputS3Url`, qui est une URL pré-signée pour le point d’accès de prise en charge pour `ListObjectsV2`.

Contrairement à `GetObject` et `HeadObject`, l’URL pré-signée inclura les propriétés suivantes, si elles sont spécifiées : 
+ Tous les paramètres de la requête
+ `requestPayer` (dans l'en-tête `x-amz-request-payer`) 
+ `expectedBucketOwner` (dans l'en-tête `x-amz-expected-bucket-owner`)

Pour les paramètres d'URI de la syntaxe de la demande, consultez [https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html) dans la *Référence des API Amazon Simple Storage Service*.

L'exemple suivant illustre la charge utile d'entrée JSON de Lambda pour `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" 
}
```

Votre fonction Lambda devrait renvoyer un objet JSON contenant le code de statut, le résultat XML de liste ou les informations d’erreur qui seront renvoyées de S3 Object Lambda.

S3 Object Lambda ne traite ni ne valide `listResultXml`, mais les transmet à l’appelant `ListObjectsV2`. Pour `listBucketResult`, S3 Object Lambda s’attend à ce que certaines propriétés soient d’un type spécifique et lèvera des exceptions s’il ne peut pas les analyser. `listResultXml` et `listBucketResult` ne peuvent pas être fournies en même temps.

L’exemple suivant montre comment utiliser l’URL pré-signée pour appeler Amazon S3 et comment utiliser le résultat pour renseigner une réponse ainsi que vérifier les erreurs.

------
#### [ Python ]

```
import requests 
import xmltodict

def lambda_handler(event, context):
    # Extract the presigned URL from the input.
    s3_url = event["listObjectsV2Context"]["inputS3Url"]


    # Get the head of the object from Amazon S3.
    response = requests.get(s3_url)

    # Return the error to S3 Object Lambda (if applicable).
    if (response.status_code >= 400):
        error = xmltodict.parse(response.content)
        return {
            "statusCode": response.status_code,
            "errorCode": error["Error"]["Code"],
            "errorMessage": error["Error"]["Message"]
        }

    # Store the XML result in a dict.
    response_dict = xmltodict.parse(response.content)

    # This obscures StorageClass in a transformation, it is optional to add
    for item in response_dict['ListBucketResult']['Contents']:
        item['StorageClass'] = ""

    # Convert back to XML.
    listResultXml = xmltodict.unparse(response_dict)
    
    # Create response with listResultXml.
    response_with_list_result_xml = {
        'statusCode': 200,
        'listResultXml': listResultXml
    }

    # Create response with listBucketResult.
    response_dict['ListBucketResult'] = sanitize_response_dict(response_dict['ListBucketResult'])
    response_with_list_bucket_result = {
        'statusCode': 200,
        'listBucketResult': response_dict['ListBucketResult']
    }

    # Return the list to S3 Object Lambda.
    # Can return response_with_list_result_xml or response_with_list_bucket_result
    return response_with_list_result_xml

# Converting the response_dict's key to correct casing
def sanitize_response_dict(response_dict: dict):
    new_response_dict = dict()
    for key, value in response_dict.items():
        new_key = key[0].lower() + key[1:] if key != "ID" else 'id'
        if type(value) == list:
            newlist = []
            for element in value:
                if type(element) == type(dict()):
                    element = sanitize_response_dict(element)
                newlist.append(element)
            value = newlist
        elif type(value) == dict:
            value = sanitize_response_dict(value)
        new_response_dict[new_key] = value
    return new_response_dict
```

------

L'exemple suivant illustre la structure du code JSON de réponse de Lambda pour `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'  
            },  
        ...  
        ],  
    }  
}
```

# Format et utilisation du contexte d’événement
<a name="olap-event-context"></a>

**Note**  
Depuis le 7 novembre 2025, S3 Object Lambda n'est disponible que pour les clients existants qui utilisent actuellement le service, ainsi que pour certains AWS partenaires du réseau de partenaires (APN). Pour des fonctionnalités semblables à celles de S3 Object Lambda, cliquez ici : [Modification de la disponibilité d’Amazon S3 Object Lambda](https://docs.aws.amazon.com/AmazonS3/latest/userguide/amazons3-ol-change.html).

Amazon S3 Object Lambda fournit le contexte de la demande effectuée lors de l'événement transmis à votre AWS Lambda fonction. Voici un exemple de demande. Les descriptions des champs sont incluses après l’exemple.

```
{
    "xAmzRequestId": "requestId",
    "getObjectContext": {
        "inputS3Url": "https://my-s3-ap-111122223333.s3-accesspoint.us-east-1.amazonaws.com/example?X-Amz-Security-Token=<snip>",
        "outputRoute": "io-use1-001",
        "outputToken": "OutputToken"
    },
    "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"
}
```

Les champs suivants sont inclus dans la demande :
+ `xAmzRequestId` – ID de demande Amazon S3 pour cette demande. Nous vous recommandons de consigner cette valeur pour faciliter le débogage.
+ `getObjectContext` – Détails d’entrée et de sortie pour les connexions à Amazon S3 et S3 Object Lambda.
  + `inputS3Url` – URL présignée qui peut être utilisée pour récupérer l’objet d’origine depuis Amazon S3. L’URL est signée avec l’identité de l’appelant d’origine et les autorisations de cet utilisateur s’appliquent quand l’URL est utilisée. S’il y a des en-têtes signés dans cette URL, la fonction Lambda doit les inclure dans l’appel à Amazon S3, à l’exception de l’en-tête `Host`.
  + `outputRoute` – Un jeton de routage qui est ajouté à l’URL S3 Object Lambda lorsque la fonction Lambda appelle `WriteGetObjectResponse`.
  + `outputToken` – Jeton opaque utilisé par S3 Object Lambda pour mettre en correspondance l’appel `WriteGetObjectResponse` avec l’appelant d’origine.
+ `configuration` : informations de configuration sur le point d’accès Object Lambda.
  + `accessPointArn` : Amazon Resource Name (ARN) du point d’accès Object Lambda qui a reçu cette demande.
  + `supportingAccessPointArn` : ARN du point d’accès de prise en charge spécifié dans la configuration du point d’accès Object Lambda.
  + `payload` : données personnalisées qui sont appliquées à la configuration du point d’accès Object Lambda. S3 Object Lambda considère ces données comme une chaîne opaque. Dès lors, elles devront peut-être être décodées avant utilisation.
+ `userRequest` – Informations sur l’appel d’origine à S3 Object Lambda.
  + `url` – URL décodée de la demande telle qu’elle a été reçue par S3 Object Lambda, à l’exclusion des paramètres de requête liés à l’autorisation.
  + `headers` – Carte de chaîne aux chaînes contenant les en-têtes HTTP et leurs valeurs de l’appel d’origine, à l’exclusion de tous les en-têtes liés à l’autorisation. Si le même en-tête apparaît plusieurs fois, les valeurs de chaque instance du même en-tête sont combinées dans une liste délimitée par des virgules. Le cas des en-têtes d’origine est conservé dans cette carte.
+ `userIdentity` – Détails sur l’identité qui a adressé l’appel à S3 Object Lambda. Pour plus d’informations, consultez [Consignation d’événements de données pour les journaux d’activité](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/logging-data-events-with-cloudtrail.html) dans le *Guide de l’utilisateur AWS CloudTrail *.
  + `type` – Type d’identité.
  + `accountId`— Compte AWS À laquelle appartient l'identité.
  + `userName` – Nom descriptif de l’identité qui a réalisé l’appel.
  + `principalId` – Identifiant unique de l’entité qui a effectué l’appel.
  + `arn` – ARN du principal qui a effectué l’appel. La dernière partie de l’ARN contient l’utilisateur ou le rôle qui a réalisé l’appel.
  + `sessionContext` – Si la demande a été effectuée avec les autorisations de sécurité temporaires, cet élément fournit des informations sur la session qui a été créée pour ces autorisations.
  + `invokedBy`— Le nom de la personne à Service AWS l'origine de la demande, par exemple Amazon EC2 Auto Scaling AWS Elastic Beanstalk ou.
  + `sessionIssuer` – Si la demande a été effectuée avec des informations d’identification de sécurité temporaires, cet élément fournit des informations sur la façon dont les autorisations ont été obtenues.
+ `protocolVersion` – ID de version du contexte fourni. Le format de ce champ est `{Major Version}.{Minor Version}`. Les numéros de version mineure sont toujours des nombres à deux chiffres. Toute suppression ou modification de la sémantique d’un champ nécessite un changement de version majeur et une participation active. Simple Storage Service (Amazon S3) peut ajouter de nouveaux champs à tout moment, auquel cas vous risquez de rencontrer un changement de version mineure. En raison de la nature des déploiements logiciels, il est possible que plusieurs versions mineures soient utilisées simultanément.

# Utilisation des en-têtes Range et partNumber
<a name="range-get-olap"></a>

**Note**  
Depuis le 7 novembre 2025, S3 Object Lambda n'est disponible que pour les clients existants qui utilisent actuellement le service, ainsi que pour certains AWS partenaires du réseau de partenaires (APN). Pour des fonctionnalités semblables à celles de S3 Object Lambda, cliquez ici : [Modification de la disponibilité d’Amazon S3 Object Lambda](https://docs.aws.amazon.com/AmazonS3/latest/userguide/amazons3-ol-change.html).

Lorsque vous travaillez avec des objets volumineux dans Amazon S3 Object Lambda, vous pouvez utiliser l’en-tête HTTP `Range` pour télécharger une plage d’octets spécifiée à partir d’un objet. Pour extraire différentes plages d’octets à partir d’un même objet, utilisez des connexions simultanées à Amazon S3. Spécifiez également le paramètre `partNumber` (entier compris entre 1 et 10 000) pour exécuter une demande « par plage » pour la partie spécifiée de l’objet.

Étant donné qu’il existe plusieurs façons de gérer une demande qui inclut le paramètre `Range` ou `partNumber`, S3 Object Lambda n’applique pas ces paramètres à l’objet transformé. Votre AWS Lambda fonction doit plutôt implémenter cette fonctionnalité selon les besoins de votre application.

Pour utiliser les paramètres `Range` et `partNumber` avec S3 Object Lambda, procédez comme suit : 
+ Activez ces paramètres dans la configuration de vos points d’accès Object Lambda.
+ Écrivez une fonction Lambda capable de gérer les demandes qui incluent ces paramètres.

Les étapes suivantes expliquent comment procéder.

## Étape 1 : configurer votre point d’accès Object Lambda
<a name="range-get-olap-step-1"></a>

Par défaut, les points d’accès Object Lambda répondent avec une erreur de code de statut HTTP 501 (Non implémenté) à toute requête `GetObject` ou `HeadObject` contenant un paramètre `Range` ou `partNumber`, que ce soit dans les en-têtes ou les paramètres de requête. 

Pour permettre à un point d’accès Object Lambda d’accepter ces demandes, vous devez inclure `GetObject-Range`, `GetObject-PartNumber`, `HeadObject-Range` ou `HeadObject-PartNumber` dans la section `AllowedFeatures` de la configuration de votre point d’accès Object Lambda. Pour plus d’informations sur la mise à jour de votre configuration de point d’accès Object Lambda, consultez [Création de points d’accès Object Lambda](olap-create.md). 

## Étape 2 : implémenter la gestion de `Range` ou `partNumber` dans votre fonction Lambda
<a name="range-get-olap-step-2"></a>

Lorsque votre point d’accès Object Lambda invoque votre fonction Lambda avec une demande `GetObject` ou `HeadObject` par plage, le paramètre `Range` ou `partNumber` est inclus dans le contexte de l’événement. L’emplacement du paramètre dans le contexte d’événement dépend du paramètre utilisé et de la façon dont il a été inclus dans la demande d’origine au point d’accès Object Lambda, comme expliqué dans le tableau suivant. 


| Paramètre | Emplacement du contexte d’événement | 
| --- | --- | 
|  `Range` (en-tête)   |  `userRequest.headers.Range`  | 
|  `Range` (paramètre de la demande)  |  `userRequest.url` (paramètre `Range` de la demande)  | 
|  `partNumber`  |  `userRequest.url` (paramètre `partNumber` de la demande)  | 

**Important**  
L’URL pré-signée fournie pour votre point d’accès Object Lambda ne contient pas le paramètre `Range` ou `partNumber` de la demande d’origine. Consultez les options suivantes pour savoir comment gérer ces paramètres dans votre AWS Lambda fonction.

Après avoir extrait la valeur `Range` ou `partNumber`, vous pouvez adopter l’une des approches suivantes en fonction des besoins de votre application :

1. **Mapper le paramètre `Range` ou `partNumber` demandé à l’objet transformé (recommandé)** 

   La méthode la plus fiable pour traiter les requêtes `Range` et `partNumber` consiste à effectuer les opérations suivantes : 
   + Récupérez l’objet complet à partir d’Amazon S3.
   + Transformez l’objet.
   + Appliquez le paramètre `Range` ou `partNumber` demandé à l’objet transformé.

   Pour ce faire, utilisez l’URL pré-signée fournie afin de récupérer l’objet entier d’Amazon S3, puis traitez l’objet au besoin. Pour un exemple de fonction Lambda qui traite un `Range` paramètre de cette manière, consultez [cet exemple](https://github.com/aws-samples/amazon-s3-object-lambda-default-configuration/blob/main/function/nodejs_20_x/src/response/range_mapper.ts) dans le référentiel AWS Samples GitHub .

1. **Mappez l’élément `Range` demandé sur l’URL pré-signée.**

   Dans certains cas, votre fonction Lambda peut mapper l’élément `Range` demandé directement sur l’URL pré-signée pour récupérer uniquement une partie de l’objet à partir d’Amazon S3. Cette approche n’est appropriée que si votre transformation répond aux deux critères suivants :

   1. Votre fonction de transformation peut être appliquée à des plages d’objets partielles.

   1. L’application du paramètre `Range` avant ou après la fonction de transformation aboutit au même objet transformé.

   Par exemple, une fonction de transformation qui convertit tous les caractères d’un objet codé en ASCII en majuscules répond aux deux critères précédents. La transformation peut être appliquée à une partie d’un objet, et l’application du paramètre `Range` avant la transformation donne le même résultat que son application après la transformation.

   En revanche, une fonction qui rétablit les caractères d’un objet codé en ASCII ne répond pas à ces critères. Cette fonction répond au critère 1, car elle peut être appliquée à des plages d’objets partielles. Cependant, elle ne répond pas au critère 2, car le paramètre `Range` appliqué avant la transformation ne donne pas le même résultat que lorsqu’il est appliqué après la transformation. 

   Prenons une demande d’application de la fonction aux trois premiers caractères d’un objet avec le contenu `abcdefg`. Si le paramètre `Range` est appliqué avant la transformation, il récupère uniquement `abc`, puis rétablit les données et renvoie `cba`. Mais si le paramètre est appliqué après la transformation, la fonction récupère l’objet entier, le rétablit, puis applique le paramètre `Range` et renvoie `gfe`. Étant donné que ces résultats sont différents, cette fonction ne doit pas appliquer le paramètre `Range` lors de la récupération de l’objet à partir d’Amazon S3. À la place, elle doit récupérer l’objet entier, effectuer la transformation, et seulement alors appliquer le paramètre `Range`. 
**Avertissement**  
Dans de nombreux cas, l’application du paramètre `Range` à l’URL pré-signée entraîne un comportement inattendu de la fonction Lambda ou du client demandeur. À moins que vous ne soyez sûr que votre application fonctionne correctement lorsque vous récupérez uniquement un objet partiel d’Amazon S3, nous vous recommandons de récupérer et de transformer des objets complets comme décrit précédemment dans l’approche A. 

   Si votre application répond aux critères décrits précédemment dans l'approche B, vous pouvez simplifier votre AWS Lambda fonction en récupérant uniquement la plage d'objets demandée, puis en exécutant votre transformation sur cette plage. 

   L’exemple de code Java suivant montre comment effectuer les opérations suivantes : 
   + Récupérer l’en-tête `Range` de la requête `GetObject`.
   + Ajouter l’en-tête `Range` à l’URL pré-signée que Lambda peut utiliser pour récupérer la plage demandée à partir d’Amazon S3.

   ```
   private HttpRequest.Builder applyRangeHeader(ObjectLambdaEvent event, HttpRequest.Builder presignedRequest) {
       var header = event.getUserRequest().getHeaders().entrySet().stream()
               .filter(e -> e.getKey().toLowerCase(Locale.ROOT).equals("range"))
               .findFirst();
   
       // Add check in the query string itself.
       header.ifPresent(entry -> presignedRequest.header(entry.getKey(), entry.getValue()));
       return presignedRequest;
   }
   ```