2
votes

Puis-je utiliser AWS API Gateway en tant que proxy inverse pour un site Web S3?

J'ai un site Web sans serveur sur AWS S3. Mais S3 a une limitation que je veux surmonter: il ne me permet pas d'avoir des URL conviviales.

Par exemple, je voudrais remplacer l'URL:

www.mywebsite.com/user.html?login=daniel

Avec cette URL conviviale:

www.mywebsite.com/user/daniel

Je voudrais donc savoir si je peux utiliser Lambda avec API Gateway pour y parvenir.

Mon idée est:

API Gateway ---> Fonction Lambda ---> récupérer la ressource S3

La passerelle API recevra N'IMPORTE QUELLE requête et transmettra des informations à une fonction Lambda, qui traitera une logique à l'aide de l'URL de la requête (y compris peut-être une requête de base de données), puis récupérera la ressource de S3.

Je sais que l'objectif principal d'AWS API Gateway est d'être une passerelle vers les API REST, mais pouvons-nous également l'utiliser comme proxy pour un site Web entier?


2 commentaires

Quelle est votre ressource S3? Un SPA (Angular / React / Vue) ou autre chose?


SPA (AngularJS)


3 Réponses :


1
votes

La bonne option peut être d'utiliser CloudFront comme proxy inverse, vous pouvez utiliser la requête de réponse Viewer / Origin pour déclencher lambda et récupérer la ressource depuis S3.

https://docs.aws.amazon.com /AmazonCloudFront/latest/DeveloperGuide/lambda-examples.html

https://aws.amazon.com/blogs/networking-and-content-delivery/amazon-s3-amazon-cloudfront-a-match-made-in-the-cloud/


5 commentaires

Lambda @ Edge me permet-il de faire tout ce que je peux faire dans Lambda normal? Y compris faire des requêtes aux tables DynamoDB?


Oui, il peut accéder aux tables DynamoDB, mais la fonction du déclencheur lambda @ edge en fonction de la région où votre demande a atterri, par exemple si vous vous êtes connecté à l'emplacement périphérique CloudFront aux États-Unis (supposons que us-east-1) mais que votre table se trouve dans us-west -2, le lambda dans us-east-1 déclencherait la table dans us-west-2, ce qui pourrait provoquer une latence, etc. (la fonction lambda @ edge est répliquée automatiquement dans toutes les régions)


Mais pourquoi avons-nous besoin de CloudfFront + Lambda @ Edge? Lambda n'est-il pas suffisant pour la réécriture d'URL? Pourquoi ai-je besoin de CDN?


Un exemple simple serait d'écrire la fonction de demande / réponse d'origine lambda @, puis d'utiliser la mise en cache CDN pour servir la réponse redirigée, cela réduirait l'invocation lambda par rapport à APIGW où chaque fois que les déclencheurs lambda et le coût peuvent être réduits.


Donc, peut-être que le mieux serait de ne mettre en cache que les fichiers statiques (images, css, Javascript ...) en créant un sous-domaine séparé pour eux ( static.mywebsite.com ). Et le contenu dynamique ( mywebsite.com ) serait accessible directement avec API Gateway, évitant ainsi des coûts supplémentaires avec CloudFront et Lambda @ Edge?



0
votes

Un bon pari serait d'utiliser CloudFront et Lambda @ Edge.

Lambda @ Edge vous permet d'exécuter la fonction Lambda à l'emplacement périphérique du réseau CDN CloudFront.

CloudFront vous offre la possibilité de vous connecter à divers événements au cours de son cycle de vie et d'appliquer une logique.

Cet article semble décrire quelque chose de similaire à ce dont vous parlez.

https://aws.amazon.com/blogs/networking-and-content-delivery/implementing-default-directory-indexes-in-amazon-s3-backed-amazon- cloudfront-origins-using-lambdaedge /


4 commentaires

Lambda @ Edge me permet-il de faire tout ce que je peux faire dans Lambda normal? Y compris faire des requêtes aux tables DynamoDB?


Oui, vous pouvez faire tout cela.


Mais pourquoi avons-nous besoin de CloudfFront + Lambda @ Edge? Lambda n'est-il pas suffisant pour la réécriture d'URL? Pourquoi ai-je besoin de CDN?


De plus, le coût Lambda @ Edge est 3 fois plus cher que Lambda. Lambda coûte 0,20 USD par million de requêtes, tandis que Lambda @ Edge coûte 0,60 USD par million de requêtes



1
votes

Il est possible d'utiliser API Gateway comme proxy inverse pour un site Web S3.

J'ai pu effectuer les étapes suivantes ci-dessous:

  • Dans AWS API Gateway, créez une "ressource proxy" avec resource path = "{proxy +}"
  • Accédez à AWS Certificate Manager et demandez un certificat générique pour votre site Web (* .mywebsite.com)
  • AWS vous demandera de créer un enregistrement CNAME dans votre registraire de domaine, pour vérifier que vous possédez ce domaine
  • Une fois votre certificat validé, accédez à AWS API Gateway et créez un nom de domaine personnalisé (cliquez sur "Noms de domaine personnalisés" puis sur "Créer un nom de domaine personnalisé"). Dans «nom de domaine», saisissez votre domaine (www.mywebsite.com) et sélectionnez le certificat ACM que vous venez de créer (étape 1 ci-dessus). Créez un "Base Path Mapping" avec path = "/" et dans "destination" sélectionnez votre API et l'étape.
  • Après cela, vous devrez ajouter un autre enregistrement CNAME, avec le "Nom de domaine cible" CloudFront qui a été généré pour ce nom de domaine personnalisé.

Dans le Lambda, nous pouvons acheminer les requêtes:

'use strict';

const AWS = require('aws-sdk');
const s3 = new AWS.S3();
const myBucket = 'myBucket';

exports.handler = async (event) => {

    var responseBody = "";

    if (event.path=="/") {
        responseBody = "<h1>My Landing Page</h1>";
        responseBody += "<a href='/xpto'>link to another page</a>";
        return buildResponse(200, responseBody);
    }

    if (event.path=="/xpto") {
        responseBody = "<h1>Another Page</h1>";
        responseBody += "<a href='/'>home</a>";
        return buildResponse(200, responseBody);
    }

    if (event.path=="/my-s3-resource") {

        var params = { 
            Bucket: myBucket,
            Key: 'path/to/my-s3-resource.html',
        };

        const data = await s3.getObject(params).promise();

        return buildResponse(200, data.Body.toString('utf-8'));
    }

    return buildResponse(404, '404 Error');

};


function buildResponse(statusCode, responseBody) {

    var response = {
        "isBase64Encoded": false,
        "statusCode": statusCode,
        "headers": {
            "Content-Type" : "text/html; charset=utf-8"
        },
        "body": responseBody,
    };

    return response;
}


0 commentaires