

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

# Scrittura di funzioni Lambda per i punti di accesso Lambda per oggetti S3
<a name="olap-writing-lambda"></a>

**Nota**  
A partire dal 7 novembre 2025, S3 Object Lambda è disponibile solo per i clienti esistenti che attualmente utilizzano il servizio e per alcuni AWS partner Partner Network (APN). Per funzionalità simili a Lambda per oggetti S3, consulta [Modifica della disponibilità di Lambda per oggetti Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/amazons3-ol-change.html).

Questa sezione descrive in dettaglio come scrivere AWS Lambda funzioni da utilizzare con gli access point Amazon S3 Object Lambda.

Per informazioni sulle end-to-end procedure complete per alcune attività di S3 Object Lambda, consulta quanto segue:
+ [Tutorial: trasformazione dei dati per l'applicazione con S3 Object Lambda](tutorial-s3-object-lambda-uppercase.md)
+ [Tutorial: rilevamento e oscuramento dei dati PII con S3 Object Lambda e Amazon Comprehend](tutorial-s3-object-lambda-redact-pii.md)
+ [Tutorial: utilizzo di Lambda per oggetti S3 per aggiungere filigrane alle immagini in modo dinamico man mano che vengono recuperate](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**
+ [Utilizzo di richieste `GetObject` in Lambda](#olap-getobject-response)
+ [Utilizzo di richieste `HeadObject` in Lambda](#olap-headobject)
+ [Utilizzo di richieste `ListObjects` in Lambda](#olap-listobjects)
+ [Utilizzo di richieste `ListObjectsV2` in Lambda](#olap-listobjectsv2)
+ [Formato e utilizzo del contesto degli eventi](olap-event-context.md)
+ [Utilizzo delle intestazioni Range e partNumber](range-get-olap.md)

## Utilizzo di richieste `GetObject` in Lambda
<a name="olap-getobject-response"></a>

Questa sezione presuppone che il punto di accesso Lambda per oggetti sia configurato per richiamare la funzione Lambda per `GetObject`. S3 Object Lambda include l'operazione API Amazon S3 `WriteGetObjectResponse`, che consente alla funzione Lambda di fornire dati personalizzati e intestazioni di risposta al chiamante `GetObject`. 

`WriteGetObjectResponse` offre un ampio controllo su codice di stato, intestazioni di risposta e corpo della risposta, in base ai requisiti di elaborazione. È possibile utilizzare `WriteGetObjectResponse` per rispondere con l'intero oggetto trasformato, con parti dell'oggetto trasformato o con altre risposte in base al contesto dell'applicazione. Nella sezione seguente sono illustrati esempi univoci di utilizzo dell'operazione API `WriteGetObjectResponse`.
+ **Esempio 1:** risposta con un codice di stato HTTP 403 (Forbidden) (Accesso negato) 
+ **Esempio 2:** Rispondere con un'immagine trasformata
+ **Esempio 3:** Streaming di contenuto compresso

**Esempio 1: risposta con un codice di stato HTTP 403 (Forbidden) (Accesso negato)**

È possibile utilizzare `WriteGetObjectResponse` per rispondere con il codice di stato HTTP 403 (Non consentito) in base al contenuto dell'oggetto.

------
#### [ 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 };
}
```

------

**Esempio 2:** Rispondere con un'immagine trasformata

Durante la trasformazione dell'immagine, è possibile che siano necessari tutti i byte dell'oggetto di fonte prima di poter iniziare a elaborarli. In questo caso, la tua richiesta `WriteGetObjectResponse` restituisce l'intero oggetto all'applicazione richiedente in una sola chiamata.

------
#### [ 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 };
}
```

------

**Esempio 3:** Streaming di contenuto compresso

Durante la compressione degli oggetti, i dati compressi vengono prodotti in modo incrementale. Di conseguenza, puoi utilizzare la richiesta `WriteGetObjectResponse` per restituire i dati compressi non appena sono pronti. Come mostrato in questo esempio, non è necessario conoscere la lunghezza della trasformazione completata.

------
#### [ 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 };
}
```

------

**Nota**  
Sebbene S3 Object Lambda consente fino a 60 secondi per inviare una risposta completa al chiamante tramite la richiesta `WriteGetObjectResponse`, la quantità effettiva di tempo disponibile potrebbe essere inferiore. Ad esempio, il timeout della funzione Lambda potrebbe essere inferiore a 60 secondi. In altri casi, il chiamante potrebbe avere timeout più rigorosi. 

Affinché il chiamante originale riceva una risposta diversa dal codice di stato HTTP 500 (Internal Server Error) (Errore interno del server), la chiamata `WriteGetObjectResponse` deve essere completata. Se la funzione Lambda restituisce un risultato, eccezionalmente o in altro modo, prima che l'operazione API `WriteGetObjectResponse` venga richiamata, il chiamante originale riceverà una risposta 500 (Internal Server Error) (Errore interno del server). Le eccezioni generate durante il tempo necessario per completare la risposta comportano risposte troncate al chiamante. Se la funzione Lambda riceve una risposta con codice di stato HTTP 200 (OK) dalla chiamata API `WriteGetObjectResponse`, il chiamante originale ha inviato la richiesta completa. La risposta della funzione Lambda, indipendentemente dal fatto che un'eccezione sia generata o meno, viene ignorata da S3 Object Lambda.

Quando viene richiamata l'operazione API `WriteGetObjectResponse`, Amazon S3 richiede il token dell'instradamento e della richiesta dal contesto dell'evento. Per ulteriori informazioni, consulta [Formato e utilizzo del contesto degli eventi](olap-event-context.md).

I parametri relativi ai token dell'instradamento e della richiesta sono necessari per collegare la risposta `WriteGetObjectResult` al chiamante originale. Sebbene sia sempre opportuno riprovare le risposte 500 (Internal Server Error) (Errore interno del server), è necessario considerare che il token della richiesta è un token monouso e i successivi tentativi di utilizzo possono comportare risposte con codice di stato 400 (Bad Request) (Richiesta non valida). Anche se la chiamata a `WriteGetObjectResponse` con i token dell'instradamento e della richiesta non ha bisogno di essere effettuata dalla funzione Lambda richiamata, deve essere effettuata da un'identità nello stesso account. La chiamata deve anche essere completata prima che la funzione Lambda finisca l'esecuzione.

## Utilizzo di richieste `HeadObject` in Lambda
<a name="olap-headobject"></a>

Questa sezione presuppone che il punto di accesso Lambda per oggetti sia configurato per richiamare la funzione Lambda per `HeadObject`. Lambda riceverà un payload JSON contenente una chiave chiamata `headObjectContext`. All'interno del contesto, esiste un'unica proprietà chiamata `inputS3Url`, che è un URL prefirmato per il punto di accesso di supporto per `HeadObject`.

L'URL prefirmato includerà le seguenti proprietà, se specificate: 
+ `versionId` (nei parametri della query)
+ `requestPayer` (nell'intestazione `x-amz-request-payer`)
+ `expectedBucketOwner` (nell'intestazione `x-amz-expected-bucket-owner`)

Le altre proprietà non saranno prefirmate e quindi non saranno incluse. Le opzioni non firmate inviate come intestazioni possono essere aggiunte manualmente alla richiesta quando si richiama l'URL prefirmato che si trova nelle intestazioni `userRequest`. Le opzioni di crittografia lato server non sono supportate per `HeadObject`.

Per i parametri URI della sintassi della richiesta, consulta [https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html) nella *Documentazione di riferimento delle API di Amazon Simple Storage Service*.

Il seguente esempio mostra un payload di input Lambda JSON per `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"
}
```

La funzione Lambda dovrebbe restituire un oggetto JSON contenente le intestazioni e i valori che verranno restituiti per la chiamata `HeadObject`.

Il seguente esempio illustra la struttura dell'oggetto JSON della risposta Lambda per `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'esempio seguente mostra come utilizzare l'URL prefirmato per compilare la risposta modificando i valori dell'intestazione secondo necessità prima di restituire l'oggetto 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     
        }
```

------

## Utilizzo di richieste `ListObjects` in Lambda
<a name="olap-listobjects"></a>

Questa sezione presuppone che il punto di accesso Lambda per oggetti sia configurato per richiamare la funzione Lambda per `ListObjects`. Lambda riceverà il payload JSON con un nuovo oggetto denominato `listObjectsContext`. `listObjectsContext` contiene un'unica proprietà `inputS3Url`, che è un URL prefirmato per il punto di accesso di supporto per `ListObjects`.

A differenza di `GetObject` e `HeadObject`, l'URL prefirmato includerà le seguenti proprietà, se specificate:
+ Tutti i parametri della query
+ `requestPayer` (nell'intestazione `x-amz-request-payer`) 
+ `expectedBucketOwner` (nell'intestazione `x-amz-expected-bucket-owner`)

Per i parametri URI della sintassi della richiesta, consulta [https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html) nella *Documentazione di riferimento delle API di Amazon Simple Storage Service*.

**Importante**  
Ti consigliamo di utilizzare la versione più recente, [ListObjectsV2](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html), per lo sviluppo di applicazioni. Per la compatibilità con le versioni precedenti, Amazon S3 continua a supportare `ListObjects`.

Il seguente esempio illustra il payload di input Lambda JSON per `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"
}
```

La funzione Lambda deve restituire un oggetto JSON che contenga il codice di stato, l'elenco dei risultati XML o le informazioni di errore che verranno restituite da Lambda per oggetti S3.

Lambda per oggetti S3 non elabora né convalida `listResultXml`, ma lo inoltra al chiamante `ListObjects`. Per `listBucketResult`, Lambda per oggetti S3 si aspetta che determinate proprietà siano di un tipo specifico e genererà eccezioni se non è in grado di analizzarle. `listResultXml` e `listBucketResult` non possono essere specificati contemporaneamente.

L'esempio seguente illustra come utilizzare l'URL prefirmato per richiamare Amazon S3 e utilizzare il risultato per compilare una risposta, incluso il controllo degli errori.

------
#### [ 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
```

------

Il seguente esempio illustra la struttura dell'oggetto JSON della risposta Lambda per `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'
        },  
        ...  
        ],  
    }
}
```

## Utilizzo di richieste `ListObjectsV2` in Lambda
<a name="olap-listobjectsv2"></a>

Questa sezione presuppone che il punto di accesso Lambda per oggetti sia configurato per richiamare la funzione Lambda per `ListObjectsV2`. Lambda riceverà il payload JSON con un nuovo oggetto denominato `listObjectsV2Context`. `listObjectsV2Context` contiene un'unica proprietà `inputS3Url`, che è un URL prefirmato per il punto di accesso di supporto per `ListObjectsV2`.

A differenza di `GetObject` e `HeadObject`, l'URL prefirmato includerà le seguenti proprietà, se specificate: 
+ Tutti i parametri della query
+ `requestPayer` (nell'intestazione `x-amz-request-payer`) 
+ `expectedBucketOwner` (nell'intestazione `x-amz-expected-bucket-owner`)

Per i parametri URI della sintassi della richiesta, consulta [https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html) nella *Documentazione di riferimento delle API di Amazon Simple Storage Service*.

Il seguente esempio illustra il payload di input Lambda JSON per `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" 
}
```

La funzione Lambda deve restituire un oggetto JSON che contenga il codice di stato, l'elenco dei risultati XML o le informazioni di errore che verranno restituite da Lambda per oggetti S3.

Lambda per oggetti S3 non elabora né convalida `listResultXml`, ma lo inoltra al chiamante `ListObjectsV2`. Per `listBucketResult`, Lambda per oggetti S3 si aspetta che determinate proprietà siano di un tipo specifico e genererà eccezioni se non è in grado di analizzarle. `listResultXml` e `listBucketResult` non possono essere specificati contemporaneamente.

L'esempio seguente illustra come utilizzare l'URL prefirmato per richiamare Amazon S3 e utilizzare il risultato per compilare una risposta, incluso il controllo degli errori.

------
#### [ 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
```

------

Il seguente esempio illustra la struttura dell'oggetto JSON della risposta Lambda per `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'  
            },  
        ...  
        ],  
    }  
}
```

# Formato e utilizzo del contesto degli eventi
<a name="olap-event-context"></a>

**Nota**  
A partire dal 7 novembre 2025, S3 Object Lambda è disponibile solo per i clienti esistenti che attualmente utilizzano il servizio e per alcuni AWS partner Partner Network (APN). Per funzionalità simili a Lambda per oggetti S3, consulta [Modifica della disponibilità di Lambda per oggetti Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/amazons3-ol-change.html).

Amazon S3 Object Lambda fornisce un contesto sulla richiesta che viene effettuata nel caso in cui venga passata alla tua funzione. AWS Lambda Il risultato è illustrato nello screenshot seguente. Le descrizioni dei campi sono riportate dopo l'esempio.

```
{
    "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"
}
```

I seguenti campi sono inclusi nella richiesta:
+ `xAmzRequestId`: l'ID della richiesta di Amazon S3 per questa richiesta. Si consiglia di registrare questo valore per facilitare il debug.
+ `getObjectContext`: i dettagli di input e output per le connessioni ad Amazon S3 e S3 Object Lambda.
  + `inputS3Url`: un URL prefirmato che può essere utilizzato per recuperare l'oggetto originale da Amazon S3. L'URL viene firmato utilizzando l'identità del chiamante originale e quando viene utilizzato l'URL vengono applicate le autorizzazioni dell'utente associato. Se nell'URL sono presenti intestazioni firmate, la funzione Lambda deve includerle nella chiamata ad Amazon S3, ad eccezione dell'intestazione `Host`.
  + `outputRoute` ‐ Un token di routing che viene aggiunto all'URL di S3 Object Lambda quando la funzione Lambda richiama `WriteGetObjectResponse`.
  + `outputToken`: un token opaco utilizzato da S3 Object Lambda per abbinare la chiamata `WriteGetObjectResponse` al chiamante originale.
+ `configuration`: informazioni di configurazione sul punto di accesso Lambda per oggetti.
  + `accessPointArn`: il nome della risorsa Amazon (ARN) del punto di accesso Lambda per oggetti che ha ricevuto questa richiesta.
  + `supportingAccessPointArn`: l'ARN del punto di accesso di supporto specificato nella configurazione del punto di accesso Lambda per oggetti.
  + `payload`: dati personalizzati applicati alla configurazione del punto di accesso Lambda per oggetti. S3 Object Lambda tratta questi dati come una stringa opaca, quindi potrebbe essere necessario decodificarli prima dell'utilizzo.
+ `userRequest`: informazioni sulla chiamata originale a S3 Object Lambda.
  + `url`: l'URL decodificato della richiesta come ricevuto da S3 Object Lambda, esclusi eventuali parametri di query relativi all'autorizzazione.
  + `headers`: una mappa di stringa alle stringhe contenenti le intestazioni HTTP e i relativi valori dalla chiamata originale, escluse eventuali intestazioni relative all'autorizzazione. Se la stessa intestazione viene visualizzata più volte, i valori di ogni istanza della stessa intestazione vengono combinati in un elenco delimitato da virgole. Il formato maiuscolo/minuscolo delle intestazioni originali viene mantenuto in questa mappa.
+ `userIdentity`: dettagli sull'identità che ha effettuato la chiamata a S3 Object Lambda. Per ulteriori informazioni, consulta [Registrazione di eventi di dati per i percorsi](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/logging-data-events-with-cloudtrail.html) nella *Guida per l'utente di AWS CloudTrail *.
  + `type`: il tipo di identità.
  + `accountId`— Account AWS A cui appartiene l'identità.
  + `userName`: il nome descrittivo dell'identità che ha effettuato la chiamata.
  + `principalId`: l'identificatore univoco per l'identità che ha effettuato la chiamata.
  + `arn`: l'ARN del principale che ha effettuato la chiamata. L'ultima sezione dell'ARN contiene l'utente o il ruolo che ha effettuato la chiamata.
  + `sessionContext`: se la richiesta è stata effettuata con le credenziali di sicurezza temporanee, questo elemento fornisce informazioni sulla sessione creata per tali credenziali.
  + `invokedBy`— Il nome di chi Servizio AWS ha effettuato la richiesta, ad esempio Amazon EC2 Auto AWS Elastic Beanstalk Scaling o.
  + `sessionIssuer`: se la richiesta è stata effettuata con le credenziali di sicurezza temporanee, questo elemento fornisce informazioni su come sono state ottenute tali credenziali.
+ `protocolVersion`: l'ID versione del contesto fornito. Il formato di questo campo è `{Major Version}.{Minor Version}`. I numeri di versione secondari sono sempre numeri a due cifre. Qualsiasi rimozione o modifica alla semantica di un campo necessita un aumento della versione principale e richiede l'opt-in attivo. Amazon S3 può aggiungere nuovi campi in qualsiasi momento e in quel punto si potrebbe riscontrare un bump di versione minore. A causa della natura delle implementazioni software, più versioni secondarie potrebbero essere visualizzati in uso contemporaneamente.

# Utilizzo delle intestazioni Range e partNumber
<a name="range-get-olap"></a>

**Nota**  
A partire dal 7 novembre 2025, S3 Object Lambda è disponibile solo per i clienti esistenti che attualmente utilizzano il servizio e per alcuni AWS partner Partner Network (APN). Per funzionalità simili a Lambda per oggetti S3, consulta [Modifica della disponibilità di Lambda per oggetti Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/amazons3-ol-change.html).

Quando vengono utilizzati oggetti di grandi dimensioni in Amazon S3 Object Lambda, è possibile utilizzare l'intestazione HTTP `Range` per scaricare un intervallo di byte specificato da un oggetto. Puoi utilizzare connessioni simultanee ad Amazon S3 per recuperare diversi intervalli di byte all'interno dello stesso oggetto. Puoi inoltre specificare il parametro `partNumber` (un numero intero compreso tra 1 e 10.000) che esegue una richiesta basata su intervallo per la parte specificata dell'oggetto.

Perché ci sono diversi modi in cui potresti voler gestire una richiesta che include i parametri `Range` o `partNumber`, S3 Object Lambda non applica questi parametri all'oggetto trasformato. La AWS Lambda funzione deve invece implementare questa funzionalità in base alle esigenze dell'applicazione.

Per utilizzare i parametri `Range` e `partNumber` con S3 Object Lambda, procedi come segue: 
+ Abilita questi parametri nella configurazione del punto di accesso Lambda per oggetti.
+ Scrivi una funzione Lambda in grado di gestire le richieste contenente questi parametri.

Di seguito viene descritto come realizzarlo.

## Fase 1: configura il punto di accesso Lambda per oggetti
<a name="range-get-olap-step-1"></a>

Per impostazione predefinita, gli punti di accesso Lambda per oggetti rispondono con un errore con codice di stato HTTP 501 (Not Implemented) a qualsiasi richiesta `GetObject` o `HeadObject` contenente un parametro `Range` o `partNumber` nelle intestazioni o nei parametri di query. 

Per abilitare un punto di accesso Lambda per oggetti ad accettare tali richieste, devi includere `GetObject-Range`, `GetObject-PartNumber`, `HeadObject-Range` o `HeadObject-PartNumber` nella sezione `AllowedFeatures` della configurazione del punto di accesso Lambda per oggetti. Per ulteriori informazioni sull'aggiornamento della configurazione del punto di accesso Lambda per oggetti, consulta [Creazione di punti di accesso Object Lambda](olap-create.md). 

## Fase 2: implementa la gestione di `Range` o `partNumber` nella funzione Lambda
<a name="range-get-olap-step-2"></a>

Quando il punto di accesso Lambda per oggetti richiama la funzione Lambda con una richiesta `GetObject` o `HeadObject` basata su intervallo, il parametro `Range` o `partNumber` è incluso nel contesto dell'evento. La posizione del parametro nel contesto dell'evento dipende dal parametro utilizzato e dal modo in cui è stato incluso nella richiesta originale al punto di accesso Lambda per oggetti, come illustrato nella tabella seguente. 


| Parametro | Posizione del contesto dell'evento | 
| --- | --- | 
|  `Range` (intestazione)  |  `userRequest.headers.Range`  | 
|  `Range` (parametro di query)  |  `userRequest.url` (`Range` del parametro di query)  | 
|  `partNumber`  |  `userRequest.url` (`partNumber` del parametro di query)  | 

**Importante**  
L'URL prefirmato fornito per il punto di accesso Lambda per oggetti non contiene il parametro `Range` o `partNumber` della richiesta originale. Vedi le seguenti opzioni su come gestire questi parametri nella tua AWS Lambda funzione.

Dopo aver estratto il valore `Range` o `partNumber`, è possibile adottare uno dei seguenti approcci in base alle esigenze dell'applicazione:

1. **Mappare il valore `Range` o `partNumber` richiesto all'oggetto trasformato (consigliato).** 

   Per gestire le richieste `Range` o `partNumber` nel modo più affidabile, procedi come segue: 
   + Recupera l'oggetto completo da Amazon S3.
   + Trasforma l'oggetto.
   + Applica i parametri `Range` o `partNumber` obbligatori all'oggetto trasformato.

   Per fare ciò, utilizza l'URL prefirmato fornito per recuperare l'intero oggetto da Amazon S3 e quindi elaborare l'oggetto secondo necessità. Per un esempio di funzione Lambda che elabora un `Range` parametro in questo modo, guarda [questo esempio nel repository](https://github.com/aws-samples/amazon-s3-object-lambda-default-configuration/blob/main/function/nodejs_20_x/src/response/range_mapper.ts) AWS Samples GitHub .

1. **Mappatura del `Range` richiesto all'URL prefirmato URL.**

   In alcuni casi, la funzione Lambda può mappare il valore o il `Range` richiesto direttamente all'URL prefirmato per recuperare solo parte dell'oggetto da Amazon S3. Questo approccio è appropriato solo se la trasformazione soddisfa entrambi i seguenti criteri:

   1. La funzione di trasformazione può essere applicata a intervalli di oggetti parziali.

   1. Applicando il parametro `Range` prima o dopo la funzione di trasformazione produce lo stesso oggetto trasformato.

   Ad esempio, una funzione di trasformazione che converte tutti i caratteri di un oggetto con codifica ASCII in maiuscolo soddisfa entrambi i criteri precedenti. La trasformazione può essere applicata a una parte di un oggetto e applicando il parametro `Range` prima della trasformazione si ottiene lo stesso risultato dell'applicazione del parametro dopo la trasformazione.

   Al contrario, una funzione che inverte i caratteri in un oggetto con codifica ASCII non soddisfa questi criteri. Tale funzione soddisfa il criterio 1, poiché può essere applicata a intervalli di oggetti parziali. Tuttavia, non soddisfa il criterio 2, perché l'applicazione del parametro `Range` prima che la trasformazione raggiunga risultati diversi rispetto all'applicazione del parametro dopo la trasformazione. 

   Considera una richiesta di applicare la funzione ai primi tre caratteri di un oggetto con il contenuto `abcdefg`. L'applicazione del parametro `Range` prima della trasformazione recupera solo `abc` e poi inverte i dati, restituendo `cba`. Ma se il parametro viene applicato dopo la trasformazione, la funzione recupera l'intero oggetto, lo inverte e quindi applica il parametro `Range`, restituendo `gfe`. Poiché questi risultati sono diversi, questa funzione non dovrebbe applicare il parametro `Range` durante il recupero dell'oggetto da Amazon S3. Invece, dovrebbe recuperare l'intero oggetto, eseguire la trasformazione e solo successivamente applicare il parametro `Range`. 
**avvertimento**  
In molti casi, l'applicazione del parametro `Range` o dell'URL prefirmato risulterà in un comportamento imprevisto da parte della funzione Lambda o del client richiedente. A meno che non sia sicuro che la tua applicazione funzioni correttamente quando recuperi solo un oggetto parziale da Amazon S3, ti consigliamo di recuperare e trasformare oggetti completi come descritto in precedenza nell'approccio A. 

   Se l'applicazione soddisfa i criteri descritti in precedenza nell'approccio B, è possibile semplificare la AWS Lambda funzione recuperando solo l'intervallo di oggetti richiesto e quindi eseguendo la trasformazione su quell'intervallo. 

   Il seguente esempio di codice Java illustra come eseguire le seguenti operazioni: 
   + Recuperare l'intestazione `Range` dalla richiesta `GetObject`.
   + Aggiungere l'intestazione `Range` all'URL prefirmato che Lambda può utilizzare per recuperare l'intervallo richiesto da 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;
   }
   ```