Esempi di funzioni Lambda@Edge - Amazon CloudFront

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à.

Esempi di funzioni Lambda@Edge

Guarda i seguenti esempi per utilizzare le funzioni Lambda con Amazon. CloudFront

Nota

Se scegli runtime Node.js 18 o versione successiva per la tua funzione Lambda @Edge, viene creato automaticamente un index.mjs file. Per utilizzare i seguenti esempi di codice, rinomina invece il index.mjs file inindex.js.

Esempi generali

Gli esempi seguenti mostrano i modi più comuni di usare Lambda @Edge in. CloudFront

Esempio: test A/B

È possibile utilizzare l'esempio seguente per testare due diverse versioni di un'immagine senza creare reindirizzamenti o modificare il. URL Questo esempio legge i cookie nella richiesta del visualizzatore e modifica la richiesta di conseguenza. URL Se il visualizzatore non invia un cookie con uno dei valori previsti, l'esempio assegna casualmente il visualizzatore a uno dei. URLs

Node.js
'use strict'; exports.handler = (event, context, callback) => { const request = event.Records[0].cf.request; const headers = request.headers; if (request.uri !== '/experiment-pixel.jpg') { // do not process if this is not an A-B test request callback(null, request); return; } const cookieExperimentA = 'X-Experiment-Name=A'; const cookieExperimentB = 'X-Experiment-Name=B'; const pathExperimentA = '/experiment-group/control-pixel.jpg'; const pathExperimentB = '/experiment-group/treatment-pixel.jpg'; /* * Lambda at the Edge headers are array objects. * * Client may send multiple Cookie headers, i.e.: * > GET /viewerRes/test HTTP/1.1 * > User-Agent: curl/7.18.1 (x86_64-unknown-linux-gnu) libcurl/7.18.1 OpenSSL/1.0.1u zlib/1.2.3 * > Cookie: First=1; Second=2 * > Cookie: ClientCode=abc * > Host: example.com * * You can access the first Cookie header at headers["cookie"][0].value * and the second at headers["cookie"][1].value. * * Header values are not parsed. In the example above, * headers["cookie"][0].value is equal to "First=1; Second=2" */ let experimentUri; if (headers.cookie) { for (let i = 0; i < headers.cookie.length; i++) { if (headers.cookie[i].value.indexOf(cookieExperimentA) >= 0) { console.log('Experiment A cookie found'); experimentUri = pathExperimentA; break; } else if (headers.cookie[i].value.indexOf(cookieExperimentB) >= 0) { console.log('Experiment B cookie found'); experimentUri = pathExperimentB; break; } } } if (!experimentUri) { console.log('Experiment cookie has not been found. Throwing dice...'); if (Math.random() < 0.75) { experimentUri = pathExperimentA; } else { experimentUri = pathExperimentB; } } request.uri = experimentUri; console.log(`Request uri set to "${request.uri}"`); callback(null, request); };
Python
import json import random def lambda_handler(event, context): request = event['Records'][0]['cf']['request'] headers = request['headers'] if request['uri'] != '/experiment-pixel.jpg': # Not an A/B Test return request cookieExperimentA, cookieExperimentB = 'X-Experiment-Name=A', 'X-Experiment-Name=B' pathExperimentA, pathExperimentB = '/experiment-group/control-pixel.jpg', '/experiment-group/treatment-pixel.jpg' ''' Lambda at the Edge headers are array objects. Client may send multiple cookie headers. For example: > GET /viewerRes/test HTTP/1.1 > User-Agent: curl/7.18.1 (x86_64-unknown-linux-gnu) libcurl/7.18.1 OpenSSL/1.0.1u zlib/1.2.3 > Cookie: First=1; Second=2 > Cookie: ClientCode=abc > Host: example.com You can access the first Cookie header at headers["cookie"][0].value and the second at headers["cookie"][1].value. Header values are not parsed. In the example above, headers["cookie"][0].value is equal to "First=1; Second=2" ''' experimentUri = "" for cookie in headers.get('cookie', []): if cookieExperimentA in cookie['value']: print("Experiment A cookie found") experimentUri = pathExperimentA break elif cookieExperimentB in cookie['value']: print("Experiment B cookie found") experimentUri = pathExperimentB break if not experimentUri: print("Experiment cookie has not been found. Throwing dice...") if random.random() < 0.75: experimentUri = pathExperimentA else: experimentUri = pathExperimentB request['uri'] = experimentUri print(f"Request uri set to {experimentUri}") return request

Esempio: sovrascrivi un'intestazione di risposta

L'esempio seguente mostra come modificare il valore di un'intestazione di risposta in base al valore di un'altra intestazione.

Node.js
'use strict'; exports.handler = (event, context, callback) => { const response = event.Records[0].cf.response; const headers = response.headers; const headerNameSrc = 'X-Amz-Meta-Last-Modified'; const headerNameDst = 'Last-Modified'; if (headers[headerNameSrc.toLowerCase()]) { headers[headerNameDst.toLowerCase()] = [ headers[headerNameSrc.toLowerCase()][0], ]; console.log(`Response header "${headerNameDst}" was set to ` + `"${headers[headerNameDst.toLowerCase()][0].value}"`); } callback(null, response); };
Python
import json def lambda_handler(event, context): response = event["Records"][0]["cf"]["response"] headers = response["headers"] headerNameSrc = "X-Amz-Meta-Last-Modified" headerNameDst = "Last-Modified" if headers.get(headerNameSrc.lower(), None): headers[headerNameDst.lower()] = [headers[headerNameSrc.lower()][0]] print(f"Response header {headerNameDst.lower()} was set to {headers[headerNameSrc.lower()][0]}") return response

Genera risposte: esempi

Gli esempi seguenti mostrano come utilizzare Lambda @Edge per generare risposte.

Esempio: pubblica contenuti statici (risposta generata)

L'esempio seguente mostra come utilizzare una funzione Lambda per distribuire contenuto Web statico e quindi ridurre il carico sul server di origine e la latenza complessiva.

Nota

Puoi generare HTTP risposte per gli eventi di richiesta del visualizzatore e di richiesta di origine. Per ulteriori informazioni, consulta Genera HTTP risposte nei trigger di richiesta.

Puoi anche sostituire o rimuovere il corpo della HTTP risposta negli eventi di risposta di origine. Per ulteriori informazioni, consulta Aggiorna HTTP le risposte nei trigger di risposta di Origin.

Node.js
'use strict'; const content = ` <\!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Simple Lambda@Edge Static Content Response</title> </head> <body> <p>Hello from Lambda@Edge!</p> </body> </html> `; exports.handler = (event, context, callback) => { /* * Generate HTTP OK response using 200 status code with HTML body. */ const response = { status: '200', statusDescription: 'OK', headers: { 'cache-control': [{ key: 'Cache-Control', value: 'max-age=100' }], 'content-type': [{ key: 'Content-Type', value: 'text/html' }] }, body: content, }; callback(null, response); };
Python
import json CONTENT = """ <\!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Simple Lambda@Edge Static Content Response</title> </head> <body> <p>Hello from Lambda@Edge!</p> </body> </html> """ def lambda_handler(event, context): # Generate HTTP OK response using 200 status code with HTML body. response = { 'status': '200', 'statusDescription': 'OK', 'headers': { 'cache-control': [ { 'key': 'Cache-Control', 'value': 'max-age=100' } ], "content-type": [ { 'key': 'Content-Type', 'value': 'text/html' } ] }, 'body': CONTENT } return response

Esempio: generare un HTTP reindirizzamento (risposta generata)

L'esempio seguente mostra come generare un HTTP reindirizzamento.

Nota

È possibile generare HTTP risposte per gli eventi di richiesta del visualizzatore e di richiesta di origine. Per ulteriori informazioni, consulta Genera HTTP risposte nei trigger di richiesta.

Node.js
'use strict'; exports.handler = (event, context, callback) => { /* * Generate HTTP redirect response with 302 status code and Location header. */ const response = { status: '302', statusDescription: 'Found', headers: { location: [{ key: 'Location', value: 'https://docs.aws.amazon.com/lambda/latest/dg/lambda-edge.html', }], }, }; callback(null, response); };
Python
def lambda_handler(event, context): # Generate HTTP redirect response with 302 status code and Location header. response = { 'status': '302', 'statusDescription': 'Found', 'headers': { 'location': [{ 'key': 'Location', 'value': 'https://docs.aws.amazon.com/lambda/latest/dg/lambda-edge.html' }] } } return response

Stringhe di query: esempi

Gli esempi seguenti mostrano i modi in cui è possibile utilizzare Lambda @Edge con le stringhe di query.

Esempio: aggiungere un'intestazione basata su un parametro della stringa di query

L'esempio seguente mostra come ottenere la coppia chiave-valore di un parametro di stringa di query e aggiungere quindi un'intestazione in base a tali valori.

Node.js
'use strict'; const querystring = require('querystring'); exports.handler = (event, context, callback) => { const request = event.Records[0].cf.request; /* When a request contains a query string key-value pair but the origin server * expects the value in a header, you can use this Lambda function to * convert the key-value pair to a header. Here's what the function does: * 1. Parses the query string and gets the key-value pair. * 2. Adds a header to the request using the key-value pair that the function got in step 1. */ /* Parse request querystring to get javascript object */ const params = querystring.parse(request.querystring); /* Move auth param from querystring to headers */ const headerName = 'Auth-Header'; request.headers[headerName.toLowerCase()] = [{ key: headerName, value: params.auth }]; delete params.auth; /* Update request querystring */ request.querystring = querystring.stringify(params); callback(null, request); };
Python
from urllib.parse import parse_qs, urlencode def lambda_handler(event, context): request = event['Records'][0]['cf']['request'] ''' When a request contains a query string key-value pair but the origin server expects the value in a header, you can use this Lambda function to convert the key-value pair to a header. Here's what the function does: 1. Parses the query string and gets the key-value pair. 2. Adds a header to the request using the key-value pair that the function got in step 1. ''' # Parse request querystring to get dictionary/json params = {k : v[0] for k, v in parse_qs(request['querystring']).items()} # Move auth param from querystring to headers headerName = 'Auth-Header' request['headers'][headerName.lower()] = [{'key': headerName, 'value': params['auth']}] del params['auth'] # Update request querystring request['querystring'] = urlencode(params) return request

Esempio: normalizza i parametri della stringa di query per migliorare il rapporto di accessi alla cache

L'esempio seguente mostra come migliorare il rapporto di accessi alla cache apportando le seguenti modifiche alle stringhe di query prima di CloudFront inoltrare le richieste all'origine:

  • Ordina alfabeticamente le coppie chiave-valore in base al nome del parametro

  • Cambia le coppie chiave-valore da maiuscolo in minuscolo

Per ulteriori informazioni, consulta Contenuto della cache in base ai parametri della stringa di query.

Node.js
'use strict'; const querystring = require('querystring'); exports.handler = (event, context, callback) => { const request = event.Records[0].cf.request; /* When you configure a distribution to forward query strings to the origin and * to cache based on an allowlist of query string parameters, we recommend * the following to improve the cache-hit ratio: * - Always list parameters in the same order. * - Use the same case for parameter names and values. * * This function normalizes query strings so that parameter names and values * are lowercase and parameter names are in alphabetical order. * * For more information, see: * https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/QueryStringParameters.html */ console.log('Query String: ', request.querystring); /* Parse request query string to get javascript object */ const params = querystring.parse(request.querystring.toLowerCase()); const sortedParams = {}; /* Sort param keys */ Object.keys(params).sort().forEach(key => { sortedParams[key] = params[key]; }); /* Update request querystring with normalized */ request.querystring = querystring.stringify(sortedParams); callback(null, request); };
Python
from urllib.parse import parse_qs, urlencode def lambda_handler(event, context): request = event['Records'][0]['cf']['request'] ''' When you configure a distribution to forward query strings to the origin and to cache based on an allowlist of query string parameters, we recommend the following to improve the cache-hit ratio: Always list parameters in the same order. - Use the same case for parameter names and values. This function normalizes query strings so that parameter names and values are lowercase and parameter names are in alphabetical order. For more information, see: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/QueryStringParameters.html ''' print("Query string: ", request["querystring"]) # Parse request query string to get js object params = {k : v[0] for k, v in parse_qs(request['querystring'].lower()).items()} # Sort param keys sortedParams = sorted(params.items(), key=lambda x: x[0]) # Update request querystring with normalized request['querystring'] = urlencode(sortedParams) return request

Esempio: reindirizzare gli utenti non autenticati a una pagina di accesso

L'esempio seguente mostra come reindirizzare gli utenti a una pagina di accesso se non hanno immesso le loro credenziali.

Node.js
'use strict'; function parseCookies(headers) { const parsedCookie = {}; if (headers.cookie) { headers.cookie[0].value.split(';').forEach((cookie) => { if (cookie) { const parts = cookie.split('='); parsedCookie[parts[0].trim()] = parts[1].trim(); } }); } return parsedCookie; } exports.handler = (event, context, callback) => { const request = event.Records[0].cf.request; const headers = request.headers; /* Check for session-id in request cookie in viewer-request event, * if session-id is absent, redirect the user to sign in page with original * request sent as redirect_url in query params. */ /* Check for session-id in cookie, if present then proceed with request */ const parsedCookies = parseCookies(headers); if (parsedCookies && parsedCookies['session-id']) { callback(null, request); return; } /* URI encode the original request to be sent as redirect_url in query params */ const encodedRedirectUrl = encodeURIComponent(`https://${headers.host[0].value}${request.uri}?${request.querystring}`); const response = { status: '302', statusDescription: 'Found', headers: { location: [{ key: 'Location', value: `https://www.example.com/signin?redirect_url=${encodedRedirectUrl}`, }], }, }; callback(null, response); };
Python
import urllib def parseCookies(headers): parsedCookie = {} if headers.get('cookie'): for cookie in headers['cookie'][0]['value'].split(';'): if cookie: parts = cookie.split('=') parsedCookie[parts[0].strip()] = parts[1].strip() return parsedCookie def lambda_handler(event, context): request = event['Records'][0]['cf']['request'] headers = request['headers'] ''' Check for session-id in request cookie in viewer-request event, if session-id is absent, redirect the user to sign in page with original request sent as redirect_url in query params. ''' # Check for session-id in cookie, if present, then proceed with request parsedCookies = parseCookies(headers) if parsedCookies and parsedCookies['session-id']: return request # URI encode the original request to be sent as redirect_url in query params redirectUrl = "https://%s%s?%s" % (headers['host'][0]['value'], request['uri'], request['querystring']) encodedRedirectUrl = urllib.parse.quote_plus(redirectUrl.encode('utf-8')) response = { 'status': '302', 'statusDescription': 'Found', 'headers': { 'location': [{ 'key': 'Location', 'value': 'https://www.example.com/signin?redirect_url=%s' % encodedRedirectUrl }] } } return response

Esempi di personalizzazione del contenuto in base alle intestazioni del paese o del tipo di dispositivo

Gli esempi seguenti mostrano come utilizzare Lambda @Edge per personalizzare il comportamento in base alla posizione o al tipo di dispositivo utilizzato dallo spettatore.

Esempio: reindirizza le richieste degli spettatori verso un paese specifico URL

L'esempio seguente mostra come generare una risposta di HTTP reindirizzamento con una specifica nazione URL e restituire la risposta allo spettatore. Ciò è utile quando intendi fornire risposte relative a un paese. Ad esempio:

  • Se hai sottodomini specifici di un paese, ad esempio us.example.com e tw.example.com, puoi generare una risposta di reindirizzamento quando un visualizzatore richiede example.com.

  • Se stai eseguendo lo streaming di video, ma non disponi dei diritti per lo streaming di contenuto in un determinato paese, puoi reindirizzare gli utenti in quel paese a una pagina che spiega perché non sono in grado di riprodurre il video.

Tieni presente quanto segue:

  • Devi configurare la tua distribuzione in modo tale che la memorizzazione nella cache venga eseguita in base all'intestazione CloudFront-Viewer-Country. Per ulteriori informazioni, consulta Cache Based on Selected Request Headers (Cache in base a intestazioni di richiesta selezionate).

  • CloudFront aggiunge l'CloudFront-Viewer-Countryintestazione dopo l'evento di richiesta del visualizzatore. Per utilizzare questo esempio, devi creare un trigger per l'evento di richiesta origine.

Node.js
'use strict'; /* This is an origin request function */ exports.handler = (event, context, callback) => { const request = event.Records[0].cf.request; const headers = request.headers; /* * Based on the value of the CloudFront-Viewer-Country header, generate an * HTTP status code 302 (Redirect) response, and return a country-specific * URL in the Location header. * NOTE: 1. You must configure your distribution to cache based on the * CloudFront-Viewer-Country header. For more information, see * https://docs.aws.amazon.com/console/cloudfront/cache-on-selected-headers * 2. CloudFront adds the CloudFront-Viewer-Country header after the viewer * request event. To use this example, you must create a trigger for the * origin request event. */ let url = 'https://example.com/'; if (headers['cloudfront-viewer-country']) { const countryCode = headers['cloudfront-viewer-country'][0].value; if (countryCode === 'TW') { url = 'https://tw.example.com/'; } else if (countryCode === 'US') { url = 'https://us.example.com/'; } } const response = { status: '302', statusDescription: 'Found', headers: { location: [{ key: 'Location', value: url, }], }, }; callback(null, response); };
Python
# This is an origin request function def lambda_handler(event, context): request = event['Records'][0]['cf']['request'] headers = request['headers'] ''' Based on the value of the CloudFront-Viewer-Country header, generate an HTTP status code 302 (Redirect) response, and return a country-specific URL in the Location header. NOTE: 1. You must configure your distribution to cache based on the CloudFront-Viewer-Country header. For more information, see https://docs.aws.amazon.com/console/cloudfront/cache-on-selected-headers 2. CloudFront adds the CloudFront-Viewer-Country header after the viewer request event. To use this example, you must create a trigger for the origin request event. ''' url = 'https://example.com/' viewerCountry = headers.get('cloudfront-viewer-country') if viewerCountry: countryCode = viewerCountry[0]['value'] if countryCode == 'TW': url = 'https://tw.example.com/' elif countryCode == 'US': url = 'https://us.example.com/' response = { 'status': '302', 'statusDescription': 'Found', 'headers': { 'location': [{ 'key': 'Location', 'value': url }] } } return response

Esempio: servi versioni diverse di un oggetto in base al dispositivo

L'esempio seguente mostra come servire diverse versioni di un oggetto in base al tipo di dispositivo che l'utente sta utilizzando, ad esempio, un dispositivo mobile o un tablet. Tieni presente quanto segue:

  • Devi configurare la tua distribuzione in modo tale che la memorizzazione nella cache venga eseguita in base all'intestazione CloudFront-Is-*-Viewer. Per ulteriori informazioni, consulta Cache Based on Selected Request Headers (Cache in base a intestazioni di richiesta selezionate).

  • CloudFront aggiunge le CloudFront-Is-*-Viewer intestazioni dopo l'evento di richiesta del visualizzatore. Per utilizzare questo esempio, devi creare un trigger per l'evento di richiesta origine.

Node.js
'use strict'; /* This is an origin request function */ exports.handler = (event, context, callback) => { const request = event.Records[0].cf.request; const headers = request.headers; /* * Serve different versions of an object based on the device type. * NOTE: 1. You must configure your distribution to cache based on the * CloudFront-Is-*-Viewer headers. For more information, see * the following documentation: * https://docs.aws.amazon.com/console/cloudfront/cache-on-selected-headers * https://docs.aws.amazon.com/console/cloudfront/cache-on-device-type * 2. CloudFront adds the CloudFront-Is-*-Viewer headers after the viewer * request event. To use this example, you must create a trigger for the * origin request event. */ const desktopPath = '/desktop'; const mobilePath = '/mobile'; const tabletPath = '/tablet'; const smarttvPath = '/smarttv'; if (headers['cloudfront-is-desktop-viewer'] && headers['cloudfront-is-desktop-viewer'][0].value === 'true') { request.uri = desktopPath + request.uri; } else if (headers['cloudfront-is-mobile-viewer'] && headers['cloudfront-is-mobile-viewer'][0].value === 'true') { request.uri = mobilePath + request.uri; } else if (headers['cloudfront-is-tablet-viewer'] && headers['cloudfront-is-tablet-viewer'][0].value === 'true') { request.uri = tabletPath + request.uri; } else if (headers['cloudfront-is-smarttv-viewer'] && headers['cloudfront-is-smarttv-viewer'][0].value === 'true') { request.uri = smarttvPath + request.uri; } console.log(`Request uri set to "${request.uri}"`); callback(null, request); };
Python
# This is an origin request function def lambda_handler(event, context): request = event['Records'][0]['cf']['request'] headers = request['headers'] ''' Serve different versions of an object based on the device type. NOTE: 1. You must configure your distribution to cache based on the CloudFront-Is-*-Viewer headers. For more information, see the following documentation: https://docs.aws.amazon.com/console/cloudfront/cache-on-selected-headers https://docs.aws.amazon.com/console/cloudfront/cache-on-device-type 2. CloudFront adds the CloudFront-Is-*-Viewer headers after the viewer request event. To use this example, you must create a trigger for the origin request event. ''' desktopPath = '/desktop'; mobilePath = '/mobile'; tabletPath = '/tablet'; smarttvPath = '/smarttv'; if 'cloudfront-is-desktop-viewer' in headers and headers['cloudfront-is-desktop-viewer'][0]['value'] == 'true': request['uri'] = desktopPath + request['uri'] elif 'cloudfront-is-mobile-viewer' in headers and headers['cloudfront-is-mobile-viewer'][0]['value'] == 'true': request['uri'] = mobilePath + request['uri'] elif 'cloudfront-is-tablet-viewer' in headers and headers['cloudfront-is-tablet-viewer'][0]['value'] == 'true': request['uri'] = tabletPath + request['uri'] elif 'cloudfront-is-smarttv-viewer' in headers and headers['cloudfront-is-smarttv-viewer'][0]['value'] == 'true': request['uri'] = smarttvPath + request['uri'] print("Request uri set to %s" % request['uri']) return request

Esempi di selezione dinamica dell'origine in funzione del contenuto

Gli esempi seguenti mostrano come utilizzare Lambda @Edge per eseguire il routing verso origini diverse in base alle informazioni contenute nella richiesta.

Esempio: utilizza un trigger di richiesta di origine per passare da un'origine personalizzata a un'origine Amazon S3

Questa funzione mostra come utilizzare un trigger di richiesta origine per passare da un'origine personalizzata a un'origine Amazon S3 da cui il contenuto viene recuperato, in base alle proprietà della richiesta.

Node.js
'use strict'; const querystring = require('querystring'); exports.handler = (event, context, callback) => { const request = event.Records[0].cf.request; /** * Reads query string to check if S3 origin should be used, and * if true, sets S3 origin properties. */ const params = querystring.parse(request.querystring); if (params['useS3Origin']) { if (params['useS3Origin'] === 'true') { const s3DomainName = 'my-bucket.s3.amazonaws.com'; /* Set S3 origin fields */ request.origin = { s3: { domainName: s3DomainName, region: '', authMethod: 'none', path: '', customHeaders: {} } }; request.headers['host'] = [{ key: 'host', value: s3DomainName}]; } } callback(null, request); };
Python
from urllib.parse import parse_qs def lambda_handler(event, context): request = event['Records'][0]['cf']['request'] ''' Reads query string to check if S3 origin should be used, and if true, sets S3 origin properties ''' params = {k: v[0] for k, v in parse_qs(request['querystring']).items()} if params.get('useS3Origin') == 'true': s3DomainName = 'my-bucket.s3.amazonaws.com' # Set S3 origin fields request['origin'] = { 's3': { 'domainName': s3DomainName, 'region': '', 'authMethod': 'none', 'path': '', 'customHeaders': {} } } request['headers']['host'] = [{'key': 'host', 'value': s3DomainName}] return request

Esempio: utilizza un trigger di richiesta di origine per modificare la regione di origine di Amazon S3

Questa funzione mostra come utilizzare un trigger di richiesta origine per modificare l'origine Amazon S3 da cui viene recuperato il contenuto, in base alle proprietà della richiesta.

In questo esempio viene utilizzato il valore dell'intestazione CloudFront-Viewer-Country per aggiornare il nome di dominio del bucket S3 in un bucket in una regione più vicina al visualizzatore. Questa modifica può essere utile per vari motivi:

  • Riduce le latenze quando la regione specificata è più vicina al paese del visualizzatore.

  • Consente il controllo dei dati verificando che siano serviti da un'origine nello stesso paese in cui è stata effettuata la richiesta.

Per utilizzare questo esempio, è necessario eseguire le operazioni indicate di seguito:

  • Configurare la tua distribuzione in modo tale che la memorizzazione nella cache venga eseguita in base all'intestazione CloudFront-Viewer-Country. Per ulteriori informazioni, consulta Cache Based on Selected Request Headers (Cache in base a intestazioni di richiesta selezionate).

  • Crea un trigger per questa funzione nell'evento origin request. CloudFrontaggiunge l'CloudFront-Viewer-Countryintestazione dopo l'evento viewer request, quindi per usare questo esempio, devi assicurarti che la funzione venga eseguita per una richiesta di origine.

Node.js
'use strict'; exports.handler = (event, context, callback) => { const request = event.Records[0].cf.request; /** * This blueprint demonstrates how an origin-request trigger can be used to * change the origin from which the content is fetched, based on request properties. * In this example, we use the value of the CloudFront-Viewer-Country header * to update the S3 bucket domain name to a bucket in a Region that is closer to * the viewer. * * This can be useful in several ways: * 1) Reduces latencies when the Region specified is nearer to the viewer's * country. * 2) Provides data sovereignty by making sure that data is served from an * origin that's in the same country that the request came from. * * NOTE: 1. You must configure your distribution to cache based on the * CloudFront-Viewer-Country header. For more information, see * https://docs.aws.amazon.com/console/cloudfront/cache-on-selected-headers * 2. CloudFront adds the CloudFront-Viewer-Country header after the viewer * request event. To use this example, you must create a trigger for the * origin request event. */ const countryToRegion = { 'DE': 'eu-central-1', 'IE': 'eu-west-1', 'GB': 'eu-west-2', 'FR': 'eu-west-3', 'JP': 'ap-northeast-1', 'IN': 'ap-south-1' }; if (request.headers['cloudfront-viewer-country']) { const countryCode = request.headers['cloudfront-viewer-country'][0].value; const region = countryToRegion[countryCode]; /** * If the viewer's country is not in the list you specify, the request * goes to the default S3 bucket you've configured. */ if (region) { /** * If you've set up OAI, the bucket policy in the destination bucket * should allow the OAI GetObject operation, as configured by default * for an S3 origin with OAI. Another requirement with OAI is to provide * the Region so it can be used for the SIGV4 signature. Otherwise, the * Region is not required. */ request.origin.s3.region = region; const domainName = `my-bucket-in-${region}.s3.${region}.amazonaws.com`; request.origin.s3.domainName = domainName; request.headers['host'] = [{ key: 'host', value: domainName }]; } } callback(null, request); };
Python
def lambda_handler(event, context): request = event['Records'][0]['cf']['request'] ''' This blueprint demonstrates how an origin-request trigger can be used to change the origin from which the content is fetched, based on request properties. In this example, we use the value of the CloudFront-Viewer-Country header to update the S3 bucket domain name to a bucket in a Region that is closer to the viewer. This can be useful in several ways: 1) Reduces latencies when the Region specified is nearer to the viewer's country. 2) Provides data sovereignty by making sure that data is served from an origin that's in the same country that the request came from. NOTE: 1. You must configure your distribution to cache based on the CloudFront-Viewer-Country header. For more information, see https://docs.aws.amazon.com/console/cloudfront/cache-on-selected-headers 2. CloudFront adds the CloudFront-Viewer-Country header after the viewer request event. To use this example, you must create a trigger for the origin request event. ''' countryToRegion = { 'DE': 'eu-central-1', 'IE': 'eu-west-1', 'GB': 'eu-west-2', 'FR': 'eu-west-3', 'JP': 'ap-northeast-1', 'IN': 'ap-south-1' } viewerCountry = request['headers'].get('cloudfront-viewer-country') if viewerCountry: countryCode = viewerCountry[0]['value'] region = countryToRegion.get(countryCode) # If the viewer's country in not in the list you specify, the request # goes to the default S3 bucket you've configured if region: ''' If you've set up OAI, the bucket policy in the destination bucket should allow the OAI GetObject operation, as configured by default for an S3 origin with OAI. Another requirement with OAI is to provide the Region so it can be used for the SIGV4 signature. Otherwise, the Region is not required. ''' request['origin']['s3']['region'] = region domainName = 'my-bucket-in-{0}.s3.{0}.amazonaws.com'.format(region) request['origin']['s3']['domainName'] = domainName request['headers']['host'] = [{'key': 'host', 'value': domainName}] return request

Esempio: utilizza un trigger di richiesta di origine per passare da un'origine Amazon S3 a un'origine personalizzata

Questa funzione mostra come utilizzare un trigger di richiesta origine per passare all'origine personalizzata da cui viene recuperato il contenuto in base alle proprietà della richiesta.

Node.js
'use strict'; const querystring = require('querystring'); exports.handler = (event, context, callback) => { const request = event.Records[0].cf.request; /** * Reads query string to check if custom origin should be used, and * if true, sets custom origin properties. */ const params = querystring.parse(request.querystring); if (params['useCustomOrigin']) { if (params['useCustomOrigin'] === 'true') { /* Set custom origin fields*/ request.origin = { custom: { domainName: 'www.example.com', port: 443, protocol: 'https', path: '', sslProtocols: ['TLSv1', 'TLSv1.1'], readTimeout: 5, keepaliveTimeout: 5, customHeaders: {} } }; request.headers['host'] = [{ key: 'host', value: 'www.example.com'}]; } } callback(null, request); };
Python
from urllib.parse import parse_qs def lambda_handler(event, context): request = event['Records'][0]['cf']['request'] # Reads query string to check if custom origin should be used, and # if true, sets custom origin properties params = {k: v[0] for k, v in parse_qs(request['querystring']).items()} if params.get('useCustomOrigin') == 'true': # Set custom origin fields request['origin'] = { 'custom': { 'domainName': 'www.example.com', 'port': 443, 'protocol': 'https', 'path': '', 'sslProtocols': ['TLSv1', 'TLSv1.1'], 'readTimeout': 5, 'keepaliveTimeout': 5, 'customHeaders': {} } } request['headers']['host'] = [{'key': 'host', 'value': 'www.example.com'}] return request

Esempio: utilizza un trigger di richiesta di origine per trasferire gradualmente il traffico da un bucket Amazon S3 a un altro

Questa funzione dimostra come trasferire gradualmente il traffico da un bucket Amazon S3 a un altro in modo controllato.

Node.js
'use strict'; function getRandomInt(min, max) { /* Random number is inclusive of min and max*/ return Math.floor(Math.random() * (max - min + 1)) + min; } exports.handler = (event, context, callback) => { const request = event.Records[0].cf.request; const BLUE_TRAFFIC_PERCENTAGE = 80; /** * This Lambda function demonstrates how to gradually transfer traffic from * one S3 bucket to another in a controlled way. * We define a variable BLUE_TRAFFIC_PERCENTAGE which can take values from * 1 to 100. If the generated randomNumber less than or equal to BLUE_TRAFFIC_PERCENTAGE, traffic * is re-directed to blue-bucket. If not, the default bucket that we've configured * is used. */ const randomNumber = getRandomInt(1, 100); if (randomNumber <= BLUE_TRAFFIC_PERCENTAGE) { const domainName = 'blue-bucket.s3.amazonaws.com'; request.origin.s3.domainName = domainName; request.headers['host'] = [{ key: 'host', value: domainName}]; } callback(null, request); };
Python
import math import random def getRandomInt(min, max): # Random number is inclusive of min and max return math.floor(random.random() * (max - min + 1)) + min def lambda_handler(event, context): request = event['Records'][0]['cf']['request'] BLUE_TRAFFIC_PERCENTAGE = 80 ''' This Lambda function demonstrates how to gradually transfer traffic from one S3 bucket to another in a controlled way. We define a variable BLUE_TRAFFIC_PERCENTAGE which can take values from 1 to 100. If the generated randomNumber less than or equal to BLUE_TRAFFIC_PERCENTAGE, traffic is re-directed to blue-bucket. If not, the default bucket that we've configured is used. ''' randomNumber = getRandomInt(1, 100) if randomNumber <= BLUE_TRAFFIC_PERCENTAGE: domainName = 'blue-bucket.s3.amazonaws.com' request['origin']['s3']['domainName'] = domainName request['headers']['host'] = [{'key': 'host', 'value': domainName}] return request

Esempio: utilizza un trigger di richiesta di origine per modificare il nome di dominio di origine in base all'intestazione del paese

Questa funzione mostra come è possibile modificare il nome di dominio dell'origine in base all'intestazione CloudFront-Viewer-Country, affinché il contenuto venga distribuito da un'origine più vicina al paese del visualizzatore.

L'implementazione di questa funzionalità per la distribuzione può offrire i seguenti vantaggi:

  • Riduzione delle latenze quando la regione specificata è più vicina al paese del visualizzatore.

  • Possibilità di controllare i dati verificando che siano distribuiti da un'origine nello stesso paese in cui è stata effettuata la richiesta.

Per attivare questa funzionalità, è necessario configurare la distribuzione in modo che la memorizzazione nella cache venga eseguita in base all'intestazione CloudFront-Viewer-Country. Per ulteriori informazioni, consulta Cache Based on Selected Request Headers (Cache in base a intestazioni di richiesta selezionate).

Node.js
'use strict'; exports.handler = (event, context, callback) => { const request = event.Records[0].cf.request; if (request.headers['cloudfront-viewer-country']) { const countryCode = request.headers['cloudfront-viewer-country'][0].value; if (countryCode === 'GB' || countryCode === 'DE' || countryCode === 'IE' ) { const domainName = 'eu.example.com'; request.origin.custom.domainName = domainName; request.headers['host'] = [{key: 'host', value: domainName}]; } } callback(null, request); };
Python
def lambda_handler(event, context): request = event['Records'][0]['cf']['request'] viewerCountry = request['headers'].get('cloudfront-viewer-country') if viewerCountry: countryCode = viewerCountry[0]['value'] if countryCode == 'GB' or countryCode == 'DE' or countryCode == 'IE': domainName = 'eu.example.com' request['origin']['custom']['domainName'] = domainName request['headers']['host'] = [{'key': 'host', 'value': domainName}] return request

Aggiornare gli stati di errore: esempi

Gli esempi seguenti forniscono indicazioni su come utilizzare Lambda @Edge per modificare lo stato di errore restituito agli utenti.

Esempio: utilizza un trigger di risposta all'origine per aggiornare il codice di stato dell'errore su 200

Questa funzione mostra come puoi aggiornare lo stato della risposta a 200 e generare contenuto di corpo statico da restituire al visualizzatore nel seguente scenario:

  • La funzione viene attivata in una risposta di origine

  • Lo stato delle risposta dal server di origine è codice di stato di errore (4xx e 5xx)

Node.js
'use strict'; exports.handler = (event, context, callback) => { const response = event.Records[0].cf.response; /** * This function updates the response status to 200 and generates static * body content to return to the viewer in the following scenario: * 1. The function is triggered in an origin response * 2. The response status from the origin server is an error status code (4xx or 5xx) */ if (response.status >= 400 && response.status <= 599) { response.status = 200; response.statusDescription = 'OK'; response.body = 'Body generation example'; } callback(null, response); };
Python
def lambda_handler(event, context): response = event['Records'][0]['cf']['response'] ''' This function updates the response status to 200 and generates static body content to return to the viewer in the following scenario: 1. The function is triggered in an origin response 2. The response status from the origin server is an error status code (4xx or 5xx) ''' if int(response['status']) >= 400 and int(response['status']) <= 599: response['status'] = 200 response['statusDescription'] = 'OK' response['body'] = 'Body generation example' return response

Esempio: utilizza un trigger di risposta di origine per aggiornare il codice di stato dell'errore a 302

Questa funzione dimostra come aggiornare il codice di HTTP stato a 302 per reindirizzare a un altro percorso (comportamento della cache) con un'origine configurata diversa. Tieni presente quanto segue:

  • La funzione viene attivata in una risposta di origine

  • Lo stato delle risposta dal server di origine è codice di stato di errore (4xx e 5xx)

Node.js
'use strict'; exports.handler = (event, context, callback) => { const response = event.Records[0].cf.response; const request = event.Records[0].cf.request; /** * This function updates the HTTP status code in the response to 302, to redirect to another * path (cache behavior) that has a different origin configured. Note the following: * 1. The function is triggered in an origin response * 2. The response status from the origin server is an error status code (4xx or 5xx) */ if (response.status >= 400 && response.status <= 599) { const redirect_path = `/plan-b/path?${request.querystring}`; response.status = 302; response.statusDescription = 'Found'; /* Drop the body, as it is not required for redirects */ response.body = ''; response.headers['location'] = [{ key: 'Location', value: redirect_path }]; } callback(null, response); };
Python
def lambda_handler(event, context): response = event['Records'][0]['cf']['response'] request = event['Records'][0]['cf']['request'] ''' This function updates the HTTP status code in the response to 302, to redirect to another path (cache behavior) that has a different origin configured. Note the following: 1. The function is triggered in an origin response 2. The response status from the origin server is an error status code (4xx or 5xx) ''' if int(response['status']) >= 400 and int(response['status']) <= 599: redirect_path = '/plan-b/path?%s' % request['querystring'] response['status'] = 302 response['statusDescription'] = 'Found' # Drop the body as it is not required for redirects response['body'] = '' response['headers']['location'] = [{'key': 'Location', 'value': redirect_path}] return response

Accedi al corpo della richiesta: esempi

Gli esempi seguenti mostrano come utilizzare Lambda @Edge per lavorare con POST le richieste.

Nota

Per utilizzare questi esempi, è necessario abilitare l'opzione include body (Includi corpo) nell'associazione della funzione Lambda della distribuzione. Non è abilitato per impostazione predefinita.

  • Per abilitare questa impostazione nella CloudFront console, seleziona la casella di controllo Includi corpo nella Lambda Function Association.

  • Per abilitare questa impostazione in CloudFront API o con AWS CloudFormation, imposta il IncludeBody campo su true inLambdaFunctionAssociation.

Esempio: utilizza un trigger di richiesta per leggere un HTML modulo

Questa funzione dimostra come è possibile elaborare il corpo di una POST richiesta generata da un HTML modulo (modulo web), ad esempio un modulo «contattaci». Ad esempio, potresti avere un HTML modulo come il seguente:

<html> <form action="https://example.com" method="post"> Param 1: <input type="text" name="name1"><br> Param 2: <input type="text" name="name2"><br> input type="submit" value="Submit"> </form> </html>

Per la funzione di esempio che segue, la funzione deve essere attivata in una richiesta del CloudFront visualizzatore o in una richiesta di origine.

Node.js
'use strict'; const querystring = require('querystring'); /** * This function demonstrates how you can read the body of a POST request * generated by an HTML form (web form). The function is triggered in a * CloudFront viewer request or origin request event type. */ exports.handler = (event, context, callback) => { const request = event.Records[0].cf.request; if (request.method === 'POST') { /* HTTP body is always passed as base64-encoded string. Decode it. */ const body = Buffer.from(request.body.data, 'base64').toString(); /* HTML forms send the data in query string format. Parse it. */ const params = querystring.parse(body); /* For demonstration purposes, we only log the form fields here. * You can put your custom logic here. For example, you can store the * fields in a database, such as Amazon DynamoDB, and generate a response * right from your Lambda@Edge function. */ for (let param in params) { console.log(`For "${param}" user submitted "${params[param]}".\n`); } } return callback(null, request); };
Python
import base64 from urllib.parse import parse_qs ''' Say there is a POST request body generated by an HTML such as: <html> <form action="https://example.com" method="post"> Param 1: <input type="text" name="name1"><br> Param 2: <input type="text" name="name2"><br> input type="submit" value="Submit"> </form> </html> ''' ''' This function demonstrates how you can read the body of a POST request generated by an HTML form (web form). The function is triggered in a CloudFront viewer request or origin request event type. ''' def lambda_handler(event, context): request = event['Records'][0]['cf']['request'] if request['method'] == 'POST': # HTTP body is always passed as base64-encoded string. Decode it body = base64.b64decode(request['body']['data']) # HTML forms send the data in query string format. Parse it params = {k: v[0] for k, v in parse_qs(body).items()} ''' For demonstration purposes, we only log the form fields here. You can put your custom logic here. For example, you can store the fields in a database, such as Amazon DynamoDB, and generate a response right from your Lambda@Edge function. ''' for key, value in params.items(): print("For %s use submitted %s" % (key, value)) return request

Esempio: utilizza un trigger di richiesta per modificare un modulo HTML

Questa funzione dimostra come modificare il corpo di una POST richiesta generata da un HTML modulo (modulo web). La funzione viene attivata in una richiesta del CloudFront visualizzatore o in una richiesta di origine.

Node.js
'use strict'; const querystring = require('querystring'); exports.handler = (event, context, callback) => { var request = event.Records[0].cf.request; if (request.method === 'POST') { /* Request body is being replaced. To do this, update the following /* three fields: * 1) body.action to 'replace' * 2) body.encoding to the encoding of the new data. * * Set to one of the following values: * * text - denotes that the generated body is in text format. * Lambda@Edge will propagate this as is. * base64 - denotes that the generated body is base64 encoded. * Lambda@Edge will base64 decode the data before sending * it to the origin. * 3) body.data to the new body. */ request.body.action = 'replace'; request.body.encoding = 'text'; request.body.data = getUpdatedBody(request); } callback(null, request); }; function getUpdatedBody(request) { /* HTTP body is always passed as base64-encoded string. Decode it. */ const body = Buffer.from(request.body.data, 'base64').toString(); /* HTML forms send data in query string format. Parse it. */ const params = querystring.parse(body); /* For demonstration purposes, we're adding one more param. * * You can put your custom logic here. For example, you can truncate long * bodies from malicious requests. */ params['new-param-name'] = 'new-param-value'; return querystring.stringify(params); }
Python
import base64 from urllib.parse import parse_qs, urlencode def lambda_handler(event, context): request = event['Records'][0]['cf']['request'] if request['method'] == 'POST': ''' Request body is being replaced. To do this, update the following three fields: 1) body.action to 'replace' 2) body.encoding to the encoding of the new data. Set to one of the following values: text - denotes that the generated body is in text format. Lambda@Edge will propagate this as is. base64 - denotes that the generated body is base64 encoded. Lambda@Edge will base64 decode the data before sending it to the origin. 3) body.data to the new body. ''' request['body']['action'] = 'replace' request['body']['encoding'] = 'text' request['body']['data'] = getUpdatedBody(request) return request def getUpdatedBody(request): # HTTP body is always passed as base64-encoded string. Decode it body = base64.b64decode(request['body']['data']) # HTML forms send data in query string format. Parse it params = {k: v[0] for k, v in parse_qs(body).items()} # For demonstration purposes, we're adding one more param # You can put your custom logic here. For example, you can truncate long # bodies from malicious requests params['new-param-name'] = 'new-param-value' return urlencode(params)