

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

# CloudFront Exemples de fonctions pour CloudFront
<a name="service_code_examples_cloudfront_functions_examples"></a>

Les exemples de code suivants montrent comment utiliser CloudFront avec AWS SDKs.

**Topics**
+ [Ajout d’en-têtes de sécurité HTTP](example_cloudfront_functions_add_security_headers_section.md)
+ [Ajout d’un en-tête CORS](example_cloudfront_functions_add_cors_header_section.md)
+ [Ajout d’un en-tête de contrôle de cache](example_cloudfront_functions_add_cache_control_header_section.md)
+ [Ajout d’un en-tête d’adresse IP réelle du client](example_cloudfront_functions_add_true_client_ip_header_section.md)
+ [Ajout d’un en-tête d’origine](example_cloudfront_functions_add_origin_header_section.md)
+ [Ajoutez index.html à la demande URLs](example_cloudfront_functions_url_rewrite_single_page_apps_section.md)
+ [Normalisation des paramètres de chaîne de requête](example_cloudfront_functions_normalize_query_string_parameters_section.md)
+ [Redirection vers une nouvelle URL](example_cloudfront_functions_redirect_based_on_country_section.md)
+ [Réécriture d’une URI de demande](example_cloudfront_functions_kvs_conditional_read_section.md)
+ [Sélection d’une origine plus proche de l’utilisateur](example_cloudfront_functions_select_origin_based_on_country_section.md)
+ [Utilisation de paires clé-valeur](example_cloudfront_functions_kvs_key_value_pairs_section.md)
+ [Validation d’un jeton simple](example_cloudfront_functions_kvs_jwt_verify_section.md)

# Ajouter des en-têtes de sécurité HTTP à un événement de réponse du visualiseur CloudFront Functions
<a name="example_cloudfront_functions_add_security_headers_section"></a>

L'exemple de code suivant montre comment ajouter des en-têtes de sécurité HTTP à un événement de réponse de l'afficheur CloudFront Functions.

------
#### [ JavaScript ]

**JavaScript runtime 2.0 pour CloudFront Functions**  
 Il y en a plus à ce sujet GitHub. Trouvez l'exemple complet et apprenez à le configurer et à l'exécuter dans le référentiel d'[exemples de CloudFront fonctions](https://github.com/aws-samples/amazon-cloudfront-functions/tree/main/add-security-headers). 

```
async function handler(event) {
    var response = event.response;
    var headers = response.headers;

    // Set HTTP security headers
    // Since JavaScript doesn't allow for hyphens in variable names, we use the dict["key"] notation 
    headers['strict-transport-security'] = { value: 'max-age=63072000; includeSubdomains; preload'}; 
    headers['content-security-policy'] = { value: "default-src 'none'; img-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'; frame-ancestors 'none'"}; 
    headers['x-content-type-options'] = { value: 'nosniff'}; 
    headers['x-frame-options'] = {value: 'DENY'}; 
    headers['x-xss-protection'] = {value: '1; mode=block'};
    headers['referrer-policy'] = {value: 'same-origin'};
    
    // Return the response to viewers 
    return response;
}
```

------

Pour obtenir la liste complète des guides de développement du AWS SDK et des exemples de code, consultez[Utilisation CloudFront avec un AWS SDK](sdk-general-information-section.md). Cette rubrique comprend également des informations sur le démarrage et sur les versions précédentes du kit SDK.

# Ajouter un en-tête CORS à un événement de réponse de l'afficheur de CloudFront fonctions
<a name="example_cloudfront_functions_add_cors_header_section"></a>

L'exemple de code suivant montre comment ajouter un en-tête CORS à un événement de réponse de l'afficheur CloudFront Functions.

------
#### [ JavaScript ]

**JavaScript runtime 2.0 pour CloudFront Functions**  
 Il y en a plus à ce sujet GitHub. Trouvez l'exemple complet et apprenez à le configurer et à l'exécuter dans le référentiel d'[exemples de CloudFront fonctions](https://github.com/aws-samples/amazon-cloudfront-functions/tree/main/add-cors-header). 

```
async function handler(event)  {
    var request = event.request;
    var response  = event.response;
 
    // If Access-Control-Allow-Origin CORS header is missing, add it.
    // Since JavaScript doesn't allow for hyphens in variable names, we use the dict["key"] notation.
    if (!response.headers['access-control-allow-origin'] && request.headers['origin']) {
        response.headers['access-control-allow-origin'] = {value: request.headers['origin'].value};
        console.log("Access-Control-Allow-Origin was missing, adding it now.");
    }

    return response;
}
```

------

Pour obtenir la liste complète des guides de développement du AWS SDK et des exemples de code, consultez[Utilisation CloudFront avec un AWS SDK](sdk-general-information-section.md). Cette rubrique comprend également des informations sur le démarrage et sur les versions précédentes du kit SDK.

# Ajouter un en-tête de contrôle du cache à un événement de réponse du visualiseur CloudFront Functions
<a name="example_cloudfront_functions_add_cache_control_header_section"></a>

L'exemple de code suivant montre comment ajouter un en-tête de contrôle du cache à un événement de réponse de l'afficheur CloudFront Functions.

------
#### [ JavaScript ]

**JavaScript runtime 2.0 pour CloudFront Functions**  
 Il y en a plus à ce sujet GitHub. Trouvez l'exemple complet et apprenez à le configurer et à l'exécuter dans le référentiel d'[exemples de CloudFront fonctions](https://github.com/aws-samples/amazon-cloudfront-functions/tree/main/add-cache-control-header). 

```
async function handler(event) {
    var response = event.response;
    var headers = response.headers;
    
    if (response.statusCode >= 200 && response.statusCode < 400) {
        // Set the cache-control header
        headers['cache-control'] = {value: 'public, max-age=63072000'};
    }
        
    // Return response to viewers
    return response;
}
```

------

Pour obtenir la liste complète des guides de développement du AWS SDK et des exemples de code, consultez[Utilisation CloudFront avec un AWS SDK](sdk-general-information-section.md). Cette rubrique comprend également des informations sur le démarrage et sur les versions précédentes du kit SDK.

# Ajouter un véritable en-tête IP client à un événement de demande du visualiseur CloudFront Functions
<a name="example_cloudfront_functions_add_true_client_ip_header_section"></a>

L'exemple de code suivant montre comment ajouter un véritable en-tête IP client à un événement de demande du visualiseur CloudFront Functions.

------
#### [ JavaScript ]

**JavaScript runtime 2.0 pour CloudFront Functions**  
 Il y en a plus à ce sujet GitHub. Trouvez l'exemple complet et apprenez à le configurer et à l'exécuter dans le référentiel d'[exemples de CloudFront fonctions](https://github.com/aws-samples/amazon-cloudfront-functions/tree/main/add-true-client-ip-header). 

```
async function handler(event) {
    var request = event.request;
    var clientIP = event.viewer.ip;

    //Add the true-client-ip header to the incoming request
    request.headers['true-client-ip'] = {value: clientIP};
    
    return request;
}
```

------

Pour obtenir la liste complète des guides de développement du AWS SDK et des exemples de code, consultez[Utilisation CloudFront avec un AWS SDK](sdk-general-information-section.md). Cette rubrique comprend également des informations sur le démarrage et sur les versions précédentes du kit SDK.

# Ajouter un en-tête d'origine à un événement de demande d'affichage de CloudFront fonctions
<a name="example_cloudfront_functions_add_origin_header_section"></a>

L'exemple de code suivant montre comment ajouter un en-tête d'origine à un événement de demande de l'afficheur CloudFront Functions.

------
#### [ JavaScript ]

**JavaScript runtime 2.0 pour CloudFront Functions**  
 Il y en a plus à ce sujet GitHub. Trouvez l'exemple complet et apprenez à le configurer et à l'exécuter dans le référentiel d'[exemples de CloudFront fonctions](https://github.com/aws-samples/amazon-cloudfront-functions/tree/main/add-origin-header). 

```
async function handler(event) {
    var request = event.request;
    var headers = request.headers;
    var host = request.headers.host.value;
   
   // If origin header is missing, set it equal to the host header.
   if (!headers.origin)
       headers.origin = {value:`https://${host}`};
       
   return request;
}
```

------

Pour obtenir la liste complète des guides de développement du AWS SDK et des exemples de code, consultez[Utilisation CloudFront avec un AWS SDK](sdk-general-information-section.md). Cette rubrique comprend également des informations sur le démarrage et sur les versions précédentes du kit SDK.

# Ajouter index.html à une demande URLs sans nom de fichier dans un événement de demande du visualiseur CloudFront Functions
<a name="example_cloudfront_functions_url_rewrite_single_page_apps_section"></a>

L'exemple de code suivant montre comment ajouter index.html à une demande URLs sans nom de fichier dans un événement de demande de l'afficheur CloudFront Functions.

------
#### [ JavaScript ]

**JavaScript runtime 2.0 pour CloudFront Functions**  
 Il y en a plus à ce sujet GitHub. Trouvez l'exemple complet et apprenez à le configurer et à l'exécuter dans le référentiel d'[exemples de CloudFront fonctions](https://github.com/aws-samples/amazon-cloudfront-functions/tree/main/url-rewrite-single-page-apps). 

```
async function handler(event) {
    var request = event.request;
    var uri = request.uri;
    
    // Check whether the URI is missing a file name.
    if (uri.endsWith('/')) {
        request.uri += 'index.html';
    } 
    // Check whether the URI is missing a file extension.
    else if (!uri.includes('.')) {
        request.uri += '/index.html';
    }

    return request;
}
```

------

Pour obtenir la liste complète des guides de développement du AWS SDK et des exemples de code, consultez[Utilisation CloudFront avec un AWS SDK](sdk-general-information-section.md). Cette rubrique comprend également des informations sur le démarrage et sur les versions précédentes du kit SDK.

# Normaliser les paramètres de chaîne de requête dans une demande d'affichage de CloudFront fonctions
<a name="example_cloudfront_functions_normalize_query_string_parameters_section"></a>

L'exemple de code suivant montre comment normaliser les paramètres de chaîne de requête dans une demande d'affichage de CloudFront fonctions.

------
#### [ JavaScript ]

**JavaScript runtime 2.0 pour CloudFront Functions**  
 Il y en a plus à ce sujet GitHub. Trouvez l'exemple complet et apprenez à le configurer et à l'exécuter dans le référentiel d'[exemples de CloudFront fonctions](https://github.com/aws-samples/amazon-cloudfront-functions/tree/main/normalize-query-string-parameters). 

```
function handler(event) {
     var qs=[];
     for (var key in event.request.querystring) {
         if (event.request.querystring[key].multiValue) {
             event.request.querystring[key].multiValue.forEach((mv) => {qs.push(key + "=" + mv.value)});
         } else {
             qs.push(key + "=" + event.request.querystring[key].value);
         }
     };
     
     event.request.querystring = qs.sort().join('&');
     
      
     return event.request;
}
```

------

Pour obtenir la liste complète des guides de développement du AWS SDK et des exemples de code, consultez[Utilisation CloudFront avec un AWS SDK](sdk-general-information-section.md). Cette rubrique comprend également des informations sur le démarrage et sur les versions précédentes du kit SDK.

# Redirection vers une nouvelle URL dans un événement de demande de l'afficheur CloudFront Functions
<a name="example_cloudfront_functions_redirect_based_on_country_section"></a>

L'exemple de code suivant montre comment rediriger vers une nouvelle URL dans un événement de demande de l'afficheur CloudFront Functions.

------
#### [ JavaScript ]

**JavaScript runtime 2.0 pour CloudFront Functions**  
 Il y en a plus à ce sujet GitHub. Trouvez l'exemple complet et apprenez à le configurer et à l'exécuter dans le référentiel d'[exemples de CloudFront fonctions](https://github.com/aws-samples/amazon-cloudfront-functions/tree/main/redirect-based-on-country). 

```
async function handler(event) {
    var request = event.request;
    var headers = request.headers;
    var host = request.headers.host.value;
    var country = 'DE' // Choose a country code
    var newurl = `https://${host}/de/index.html`; // Change the redirect URL to your choice 
  
    if (headers['cloudfront-viewer-country']) {
        var countryCode = headers['cloudfront-viewer-country'].value;
        if (countryCode === country) {
            var response = {
                statusCode: 302,
                statusDescription: 'Found',
                headers:
                    { "location": { "value": newurl } }
                }

            return response;
        }
    }
    return request;
}
```

------

Pour obtenir la liste complète des guides de développement du AWS SDK et des exemples de code, consultez[Utilisation CloudFront avec un AWS SDK](sdk-general-information-section.md). Cette rubrique comprend également des informations sur le démarrage et sur les versions précédentes du kit SDK.

# Réécriture d'une URI de demande en fonction de la KeyValueStore configuration d'un événement de demande du visualiseur de CloudFront fonctions
<a name="example_cloudfront_functions_kvs_conditional_read_section"></a>

L'exemple de code suivant montre comment réécrire un URI de demande en fonction de la KeyValueStore configuration d'un événement de demande de l'afficheur CloudFront Functions.

------
#### [ JavaScript ]

**JavaScript runtime 2.0 pour CloudFront Functions**  
 Il y en a plus à ce sujet GitHub. Trouvez l'exemple complet et apprenez à le configurer et à l'exécuter dans le référentiel d'[exemples de CloudFront fonctions](https://github.com/aws-samples/amazon-cloudfront-functions/tree/main/kvs-conditional-read). 

```
import cf from 'cloudfront'; 

// (Optional) Replace KVS_ID with actual KVS ID
const kvsId = "KVS_ID";
// enable stickiness by setting a cookie from origin or using another edge function
const stickinessCookieName = "appversion";
// set to true to enable console logging
const loggingEnabled = false;
   
// function rewrites the request uri based on configuration in KVS
// example config in KVS in key:value format
// "latest": {"a_weightage": .8, "a_url": "v1", "b_url": "v2"}
// given above key and value in KVS the request uri will be rewritten 
// for example http(s)://domain/latest/something/else will be rewritten as http(s)://domain/v1/something/else or http(s)://domain/v2/something/else depending on weightage
// if no configuration is found, then the request is returned as is
async function handler(event) {
    // NOTE: This example function is for a viewer request event trigger. 
    // Choose viewer request for event trigger when you associate this function with a distribution. 
    const request = event.request;
    const pathSegments = request.uri.split('/');
    const key = pathSegments[1];
    
    // if empty path segment or if there is valid stickiness cookie 
    // then skip call to KVS and let the request continue.
    if (!key || hasValidSticknessCookie(request.cookies[stickinessCookieName], key)) {
        return event.request;
    }

    try {
        // get the prefix replacement from KVS
        const replacement = await getPathPrefixByWeightage(key);
        if (!replacement) {
            return event.request;
        }
        //Replace the first path with the replacement 
        pathSegments[1] = replacement;
        log(`using prefix ${pathSegments[1]}`)
        const newUri = pathSegments.join('/');
        log(`${request.uri} -> ${newUri}`);
        request.uri = newUri;

        return request;
    } catch (err) {
        // No change to the path if the key is not found or any other error
        log(`request uri: ${request.uri}, error: ${err}`);
    }
    // no change to path - return request 
    return event.request;
}

// function to get the prefix from KVS
async function getPathPrefixByWeightage(key) {
    const kvsHandle = cf.kvs(kvsId);
    // get the weightage config from KVS
    const kvsResponse = await kvsHandle.get(key);
    const weightageConfig = JSON.parse(kvsResponse);
    // no configuration - return null    
    if (!weightageConfig || !isFinite(weightageConfig.a_weightage)) {
        return null;
    } 
    // return the url based on weightage
    // return null if no url is configured
    if (Math.random() <= weightageConfig.a_weightage) {
        return weightageConfig.a_url ? weightageConfig.a_url: null;
    } else {
        return weightageConfig.b_url ? weightageConfig.b_url : null;
    }
}

// function to check if the stickiness cookie is valid
function hasValidSticknessCookie(stickinessCookie, pathSegment) {
    // if the value exists and it matches pathSegment
    return (stickinessCookie && stickinessCookie.value === pathSegment)
}

function log(message) {
    if (loggingEnabled) {
        console.log(message);
    }
}
```

------

Pour obtenir la liste complète des guides de développement du AWS SDK et des exemples de code, consultez[Utilisation CloudFront avec un AWS SDK](sdk-general-information-section.md). Cette rubrique comprend également des informations sur le démarrage et sur les versions précédentes du kit SDK.

# Acheminer les demandes vers une origine plus proche du visualiseur dans un événement de demande du visualiseur CloudFront Functions
<a name="example_cloudfront_functions_select_origin_based_on_country_section"></a>

L'exemple de code suivant montre comment acheminer les demandes vers une origine plus proche du visualiseur dans le cadre d'un événement de demande du visualiseur CloudFront Functions.

------
#### [ JavaScript ]

**JavaScript runtime 2.0 pour CloudFront Functions**  
 Il y en a plus à ce sujet GitHub. Trouvez l'exemple complet et apprenez à le configurer et à l'exécuter dans le référentiel d'[exemples de CloudFront fonctions](https://github.com/aws-samples/amazon-cloudfront-functions/tree/main/select-origin-based-on-country). 

```
import cf from 'cloudfront';

function handler(event) {
    const request = event.request;
    const headers = request.headers;
    const country = headers['cloudfront-viewer-country'] &&
        headers['cloudfront-viewer-country'].value;

    //List of Regions with S3 buckets containing content
    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'
    };

    const DEFAULT_REGION = 'us-east-1';

    const selectedRegion = (country && countryToRegion[country]) || DEFAULT_REGION;

    const domainName =
        `cloudfront-functions-demo-bucket-in-${selectedRegion}.s3.${selectedRegion}.amazonaws.com`;

    cf.updateRequestOrigin({
        "domainName": domainName,
        "originAccessControlConfig": {
            "enabled": true,
            "region": selectedRegion,
            "signingBehavior": "always",
            "signingProtocol": "sigv4",
            "originType": "s3"
        },
    });

    return request;
}
```

------

Pour obtenir la liste complète des guides de développement du AWS SDK et des exemples de code, consultez[Utilisation CloudFront avec un AWS SDK](sdk-general-information-section.md). Cette rubrique comprend également des informations sur le démarrage et sur les versions précédentes du kit SDK.

# Utiliser des paires clé-valeur dans une demande d'affichage de CloudFront fonctions
<a name="example_cloudfront_functions_kvs_key_value_pairs_section"></a>

L'exemple de code suivant montre comment utiliser des paires clé-valeur dans une demande d'affichage de CloudFront fonctions.

------
#### [ JavaScript ]

**JavaScript runtime 2.0 pour CloudFront Functions**  
 Il y en a plus à ce sujet GitHub. Trouvez l'exemple complet et apprenez à le configurer et à l'exécuter dans le référentiel d'[exemples de CloudFront fonctions](https://github.com/aws-samples/amazon-cloudfront-functions/tree/main/kvs-key-value-pairs). 

```
import cf from 'cloudfront';

// This fails if there is no key value store associated with the function
const kvsHandle = cf.kvs();

// Remember to associate the KVS with your function before referencing KVS in your code.
// https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/kvs-with-functions-associate.html
async function handler(event) {
    const request = event.request;
    // Use the first segment of the pathname as key
    // For example http(s)://domain/<key>/something/else
    const pathSegments = request.uri.split('/')
    const key = pathSegments[1]
    try {
        // Replace the first path of the pathname with the value of the key
        // For example http(s)://domain/<value>/something/else
        pathSegments[1] = await kvsHandle.get(key);
        const newUri = pathSegments.join('/');
        console.log(`${request.uri} -> ${newUri}`)
        request.uri = newUri;
    } catch (err) {
        // No change to the pathname if the key is not found
        console.log(`${request.uri} | ${err}`);
    }
    return request;
}
```

------

Pour obtenir la liste complète des guides de développement du AWS SDK et des exemples de code, consultez[Utilisation CloudFront avec un AWS SDK](sdk-general-information-section.md). Cette rubrique comprend également des informations sur le démarrage et sur les versions précédentes du kit SDK.

# Valider un jeton simple dans une demande d'affichage de CloudFront fonctions
<a name="example_cloudfront_functions_kvs_jwt_verify_section"></a>

L'exemple de code suivant montre comment valider un jeton simple dans une demande d' CloudFront affichage de fonctions.

------
#### [ JavaScript ]

**JavaScript runtime 2.0 pour CloudFront Functions**  
 Il y en a plus à ce sujet GitHub. Trouvez l'exemple complet et apprenez à le configurer et à l'exécuter dans le référentiel d'[exemples de CloudFront fonctions](https://github.com/aws-samples/amazon-cloudfront-functions/tree/main/kvs-jwt-verify). 

```
import crypto from 'crypto';
import cf from 'cloudfront';

//Response when JWT is not valid.
const response401 = {
    statusCode: 401,
    statusDescription: 'Unauthorized'
};

// Remember to associate the KVS with your function before calling the const kvsKey = 'jwt.secret'. 
// https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/kvs-with-functions-associate.html
const kvsKey = 'jwt.secret';
// set to true to enable console logging
const loggingEnabled = false;


function jwt_decode(token, key, noVerify, algorithm) {
    // check token
    if (!token) {
        throw new Error('No token supplied');
    }
    // check segments
    const segments = token.split('.');
    if (segments.length !== 3) {
        throw new Error('Not enough or too many segments');
    }

    // All segment should be base64
    const headerSeg = segments[0];
    const payloadSeg = segments[1];
    const signatureSeg = segments[2];

    // base64 decode and parse JSON
    const payload = JSON.parse(_base64urlDecode(payloadSeg));

    if (!noVerify) {
        const signingMethod = 'sha256';
        const signingType = 'hmac';

        // Verify signature. `sign` will return base64 string.
        const signingInput = [headerSeg, payloadSeg].join('.');

        if (!_verify(signingInput, key, signingMethod, signingType, signatureSeg)) {
            throw new Error('Signature verification failed');
        }

        // Support for nbf and exp claims.
        // According to the RFC, they should be in seconds.
        if (payload.nbf && Date.now() < payload.nbf*1000) {
            throw new Error('Token not yet active');
        }

        if (payload.exp && Date.now() > payload.exp*1000) {
            throw new Error('Token expired');
        }
    }

    return payload;
}

//Function to ensure a constant time comparison to prevent
//timing side channels.
function _constantTimeEquals(a, b) {
    if (a.length != b.length) {
        return false;
    }

    let xor = 0;
    for (let i = 0; i < a.length; i++) {
    xor |= (a.charCodeAt(i) ^ b.charCodeAt(i));
    }

    return 0 === xor;
}

function _verify(input, key, method, type, signature) {
    if(type === "hmac") {
        return _constantTimeEquals(signature, _sign(input, key, method));
    }
    else {
        throw new Error('Algorithm type not recognized');
    }
}

function _sign(input, key, method) {
    return crypto.createHmac(method, key).update(input).digest('base64url');
}

function _base64urlDecode(str) {
    return Buffer.from(str, 'base64url')
}

async function handler(event) {
    let request = event.request;

    //Secret key used to verify JWT token.
    //Update with your own key.
    const secret_key = await getSecret()

    if(!secret_key) {
        return response401;
    }

    // If no JWT token, then generate HTTP redirect 401 response.
    if(!request.querystring.jwt) {
        log("Error: No JWT in the querystring");
        return response401;
    }

    const jwtToken = request.querystring.jwt.value;

    try{ 
        jwt_decode(jwtToken, secret_key);
    }
    catch(e) {
        log(e);
        return response401;
    }

    //Remove the JWT from the query string if valid and return.
    delete request.querystring.jwt;
    log("Valid JWT token");
    return request;
}

// get secret from key value store 
async function getSecret() {
    // initialize cloudfront kv store and get the key value 
    try {
        const kvsHandle = cf.kvs();
        return await kvsHandle.get(kvsKey);
    } catch (err) {
        log(`Error reading value for key: ${kvsKey}, error: ${err}`);
        return null;
    }

}

function log(message) {
    if (loggingEnabled) {
        console.log(message);
    }
}
```

------

Pour obtenir la liste complète des guides de développement du AWS SDK et des exemples de code, consultez[Utilisation CloudFront avec un AWS SDK](sdk-general-information-section.md). Cette rubrique comprend également des informations sur le démarrage et sur les versions précédentes du kit SDK.