Pages HTML dynamiques créées avec AWS Lambda et Python

Chose que tu veux faire

Je souhaite créer une page qui utilise AWS Lambda pour générer __dynamic HTML __. Avec Lambda, vous pouvez exécuter vos scripts Python préférés sans avoir à configurer votre propre serveur, je vais donc essayer de l'utiliser pour créer une page qui génère du HTML dynamique.

Il y a déjà pas mal de discussions sur la création de pages avec Lambda, mais l'intégration du proxy Lambda __API Gateway précédemment annoncée __ Le but de cette fois est de faire en sorte que cela se sente un peu mieux en combinant l'outil de déploiement de Lambda apex. De plus, template engine est indispensable pour cracher du HTML à partir du script, j'ai donc joué avec lui pour vérifier s'il peut réellement être utilisé en combinaison.

Quoi faire

Quant au type de page à créer, cette fois j'ai décidé de construire un __ sanctuaire __. L'un des moteurs de template les plus connus de Python est jinja2, et j'ai décidé de créer un sanctuaire sans serveur. (Mais c'est juste une page Web, juste au cas où)

Je veux en faire un échantillon d'une page dynamique, donc je vais mettre en place un compteur d'accès qui montre le nombre de fidèles. Eh bien, renvoyer l'heure actuelle est un bon exemple de dynamique, mais c'est aussi ennuyeux de faire ce que vous pouvez faire avec Javascript sur le serveur, et je pense que la plupart des choses qui nécessitent un traitement dynamique sont pour déranger la base de données. , J'ai choisi le compteur d'accès comme élément pratique. Gardez un œil sur le fait que le compteur d'accès lui-même est traité comme un fossile.

Diagramme

image https://cloudcraft.co/view/67eed248-a460-46dc-91dd-fdb5a70f529f?key=D4aRY_6kyWIfbEKtYk78TQ

La configuration du serveur que je vais faire cette fois est la suivante. Lambda ne peut pas être atteint directement depuis le navigateur, j'ai donc mordu la passerelle API avant de la rendre accessible. De plus, DynamoDB est installé derrière lui pour enregistrer le nombre d'accès. DynamoDB est également une base de données clé-valeur qui peut être utilisée sans créer d'instance. C'est simple, mais c'est toujours une bonne architecture sans serveur.

Préparation

Apex

Cette fois, j'ai décidé de déployer sur Lambda à l'aide d'un outil appelé Apex. Lorsque vous utilisez des bibliothèques externes avec Lambda, elles doivent être compressées et placées, mais cet outil appelé Apex est très pratique car il facilite le déploiement et l'exécution des scripts installés à partir de la ligne de commande.

Je n'entrerai pas dans les détails ici,

  1. Installez Apex
  2. Définissez la clé AWS dans la variable d'environnement
  3. Initialisez le projet et créez un modèle avec apex init
  4. Implémentez la fonction en référence au modèle
  5. apex deploy

Vous pouvez déployer rapidement comme ça.

DynamoDB Préparez d'abord une table pour l'agrégation d'accès. Dans le cas de DynamoDB, il n'est pas nécessaire de définir toutes les colonnes à utiliser car il est sans schéma, mais il est nécessaire de décider à l'avance de la clé primaire pour l'analyse.

Cette fois, j'ai fait le tableau suivant. image

Nous avons une clé de partition primaire nommée counter_id. En tant qu'utilisation, c'est comme préparer 10 compteurs avec counter_id de 0 à 9 et les spécifier de manière aléatoire à incrémenter. En préparant plusieurs compteurs, l'écriture n'est pas concentrée en un seul endroit et des performances constantes peuvent être maintenues.

Puisque DynamoDB n'a pas de transactions, j'ai pensé qu'écrire dans la même table en même temps la rendrait incohérente, mais il semble qu'un compteur atomique puisse être réalisé en incrémentant comme une expression en utilisant ʻupdate_item`. (Je viens d'apprendre)

Lors de la lecture, nous obtiendrons tous les compteurs et nous en rendrons la somme. Si vous n'utilisez pas la "cohérence forte", il semble que le résultat écrit ne sera pas reflété immédiatement, mais cette fois nous ne cherchons pas de rigueur, nous utilisons donc une cohérence faible raisonnable.

image Le résultat de l'écriture à plusieurs reprises.

la mise en oeuvre

Je vais le faire immédiatement.

Utilisation de Jinja2 avec Lambda

En plaçant le package Jinja2 et le modèle que je souhaite utiliser dans le dossier des fonctions Apex, j'ai pu utiliser le moteur de modèle avec Lambda sans aucun problème.

Structure des dossiers.txt


├── functions
│   └── jinja
│       ├── jinja2/Tel
│       ├── main.py
│       ├── requirements.txt
│       └── templates
│           ├── index.html
│           └── layout.html
├── project.json

La structure des dossiers vue depuis la racine du projet Apex est ci-dessus. Il existe un dossier appelé jinja dans le dossier appelé functions, qui est le dossier racine de la fonction Lambda définie cette fois. En créant plusieurs dossiers dans cette hiérarchie, il est possible de gérer différentes fonctions Lambda ensemble.

Pour utiliser jinja2, vous devez lancer pip install -t .jinja2 dans le dossier jinja pour installer tout le paquet jinja2. Créez également un dossier pour les fichiers modèles que vous prévoyez d'utiliser.

main.py


# coding: utf-8

from jinja2 import Environment, FileSystemLoader

env = Environment(loader=FileSystemLoader(path.join(path.dirname(__file__), 'templates'), encoding='utf8'))

template = env.get_template('index.html')
html = template.render()

Lors de l'appel, cela ressemble à ceci. Vous pouvez maintenant afficher les modèles dans templates / index.html.

Accéder à DynamoDB

Il est facile d'utiliser la bibliothèque officielle boto3 pour accéder à DynamoDB à partir de la fonction Lambda. Vous pouvez l'utiliser sans avoir à le mettre dans le package Apex (dans certains cas, vous pouvez le mettre explicitement car vous souhaitez corriger la version), et si vous spécifiez le rôle approprié pour Lambda, vous pouvez l'utiliser sans avoir à vous authentifier dans votre code.

main.py


import boto3

dynamodb = boto3.resource('dynamodb')
count_table  = dynamodb.Table('lambda-jinja')
counts = count_table.scan(Limit=10)

Intégration du proxy Lambda pour API Gateway

Avec API Gateway, vous pouvez exécuter Lambda à partir de HTTP et recevoir les résultats. Cependant, avec la passerelle API conventionnelle, il était nécessaire de mapper quel type de requête provenait de quel type de chemin et quel type de réponse était retourné. C'est ~~ relativement gênant ~~ Je ne pouvais pas gérer des cas tels que ne pas pouvoir répondre à des requêtes arbitraires ou réutiliser un script en fonction du chemin, mais récemment un mécanisme merveilleux appelé intégration de proxy a été introduit. c'était fait. Si vous l'utilisez, les informations de requête et de chemin seront transmises au côté fonction, de sorte que les possibilités d'API Gateway + Lambda s'étendent immédiatement. J'ai tout de suite essayé cette fois.

image

Créez une méthode et une ressource pour l'itinéraire avec API Gateway de cette manière et associez-les à Lambda à créer cette fois.

swagger.yaml


---
swagger: "2.0"
basePath: "/jinja"
schemes:
- "https"
paths:
paths:
  /:
    x-amazon-apigateway-any-method:
      produces:
      - "application/json"
      responses:
        200:
          description: "200 response"
          schema:
            $ref: "#/definitions/Empty"
  /{proxy+}:
    x-amazon-apigateway-any-method:
      produces:
      - "application/json"
      parameters:
      - name: "proxy"
        in: "path"
        required: true
        type: "string"
      responses: {}
definitions:
  Empty:
    type: "object"
    title: "Empty Schema"

L'écriture en Swagger ressemble à ceci.

En listant la ressource comme / {proxy +}, il est possible de traiter les requêtes de n'importe quel chemin avec le même Lambda. Je ne pouvais pas récupérer l'accès à la racine uniquement avec / {proxy +}, donc j'ai également défini une méthode séparée pour la racine.

Réponse pour API Gateway

La configuration côté API Gateway était facile, mais il y avait un problème côté Lambda. Je me demandais si je pouvais créer un Lambda qui renvoie du HTML et le connecter à API Gateway, et il renverrait la page, mais c'était un peu différent. Si vous renvoyez simplement du HTML, API Gateway renverra 502. Au début, je déconnais avec les paramètres ContentType et API Gateway, pensant que le format n'était pas JSON, mais que la cause était ailleurs.

Lors de l'utilisation de l'intégration Proxy, le script __ semble devoir renvoyer une réponse dans un format particulier __. C'était une ligne de frappe que si vous ne suivez pas ce format, vous obtiendrez 502 sans aucune question.

Cliquez ici pour le format fixe.

main.py


def handle(event, context):
    html = ...
    return {
        "statusCode": 200,
        "headers": {"Content-Type": "text/html"},
        "body": html
    }

Il est nécessaire de renvoyer le dictionnaire qui définit trois des «statusCode», «headers» et «body» de la fonction appelée par Lambda. API Gateway les examine et crée une réponse HTTP.

De plus, toutes les informations lors d'une demande à API Gateway sont transmises à la fonction handle ʻevent` (premier argument). Dans cet exemple, le type de valeur transmise est affiché par pprint, veuillez donc vous y référer si vous le souhaitez.

Achevée

https://teu24wc5u9.execute-api.ap-northeast-1.amazonaws.com/jinja/ Le sanctuaire a été achevé avec succès. Je voulais faire de la page un peu plus un sanctuaire, mais j'étais épuisée car je n'avais pas le temps. Je suis content de vous avoir dit ce que je veux transmettre techniquement.

Pouvez-vous voir que le nombre d'adorateurs affichés augmente chaque fois qu'ils sont consultés? J'ai pu créer une page Web dynamique sans créer une seule instance.

Le chemin d'accès est

/jinja/
/jinja/hoge
/jinja/fuga
/jinja/piyopiyo

Tout sera accepté. Les informations de demande «chemin» au bas de la page doivent également être prises correctement. Avec cela, il est facile d'ajouter votre propre processus de routage et d'afficher différentes pages.

En raison des restrictions d'API Gateway, la partie / jinja / est une chaîne de version et ne peut pas être supprimée.

Pour accéder par root, il semble bon de mettre CloudFront etc. devant API Gateway. Vous ne pouvez pas héberger des fichiers statiques avec API Gateway uniquement.

À la fin

J'ai essayé de créer une page dynamique avec Lambda avec un départ assez proche, mais c'était bien de pouvoir le faire en toute sécurité. J'avais peur d'utiliser quelque chose pour l'API en tant que page Web à cause du nom API Gateway, mais en fin de compte, il est puissant que même un service Web à part entière puisse être utilisé avec Lambda + API Gateway. Je l'ai senti. Le seul inconvénient de Lambda est que vous ne pouvez utiliser que Python2 ... Veuillez soutenir 3 dès que possible: priez:

https://github.com/pistatium/lambda_jinja_sample La source pour cette fois est ici.

prime

Notre organisation Qiita A été faite la dernière fois. Je voudrais faire de mon mieux pour écrire autre que AdventCalender.

Recommended Posts

Pages HTML dynamiques créées avec AWS Lambda et Python
Créez des tweets ordinaires comme une flotte avec AWS Lambda et Python
Notifier HipChat avec AWS Lambda (Python)
Surveillance du site et notification d'alerte avec AWS Lambda + Python + Slack
[AWS] Utilisation de fichiers ini avec Lambda [Python]
[AWS] Associez Lambda et S3 à boto3
Connectez-vous à s3 avec AWS Lambda Python
Touchez AWS avec Serverless Framework et Python
[AWS] Créez un environnement Python Lambda avec CodeStar et faites Hello World
Surveillance simple du serveur avec AWS Lambda (Python) et notification des résultats avec Slack
LINE BOT avec Python + AWS Lambda + API Gateway
Application sans serveur avec AWS SAM! (APIGATEWAY + Lambda (Python))
Version Amazon API Gateway et AWS Lambda Python
J'ai essayé de faire LINE BOT avec Python et Heroku
Déployer la fonction Python 3 avec Serverless Framework sur AWS Lambda
Créer une couche pour AWS Lambda Python dans Docker
Je veux AWS Lambda avec Python sur Mac!
Comment publier des pages GitHub avec Pelican, un générateur HTML statique créé par Python
Programmation avec Python et Tkinter
Chiffrement et déchiffrement avec Python
Exploitez TwitterBot avec Lambda, Python
Python et matériel - Utilisation de RS232C avec Python -
[Python] Scraping dans AWS Lambda
J'ai fait un blackjack avec du python!
PyTorch avec AWS Lambda [importation Lambda]
python avec pyenv et venv
J'ai fait un blackjack avec Python.
Othello fait avec python (comme GUI)
J'ai créé wordcloud avec Python.
Fonctionne avec Python et R
Résolution avec Ruby et Python AtCoder ABC178 D Méthode de planification dynamique
[AWS] Essayez d'ajouter la bibliothèque Python à la couche avec SAM + Lambda (Python)
Résolution avec Ruby et Python AtCoder ABC011 C Méthode de planification dynamique
Résolution avec Ruby et Python AtCoder ABC153 E Méthode de planification dynamique
Créez rapidement une API avec Python, lambda et API Gateway à l'aide d'AWS SAM
Créez facilement une infrastructure réseau et EC2 avec AWS CDK Python
Communiquez avec FX-5204PS avec Python et PyUSB
Briller la vie avec Python et OpenCV
J'ai fait un circuit simple avec Python (AND, OR, NOR, etc.)
Robot fonctionnant avec Arduino et python
Installez Python 2.7.9 et Python 3.4.x avec pip.
Bases de SNS Python faites avec Flask
Réseau neuronal avec OpenCV 3 et Python 3
Récapitulatif si vous utilisez AWS Lambda (Python)
Modulation et démodulation AM avec python
Scraping avec Node, Ruby et Python
Afficher les photos en Python et html
[AWS] Créer une API avec API Gateway + Lambda
Proxy dynamique avec python, ruby, PHP
Grattage avec Python, Selenium et Chromedriver
Extraction de texte avec AWS Textract (Python3.6)
Détection de visage avec Lambda (Python) + Rekognition
Grattage avec Python et belle soupe
Ecrire une fonction AWS Lambda en Python
Numer0n avec des objets fabriqués avec Python
J'ai fait une loterie avec Python.