[PYTHON] [AWS] Machen Sie SSI-ähnliche Dinge mit S3 / Lambda

Update 2020.11.16 Alibaba Cloud-Version Ich habe es geschafft.

TL;DR HTML, in dem SSI (include virtual) beschrieben ist, wird in einem bestimmten Bucket von S3 gespeichert, und die Quellen im Include werden von Lambda kombiniert und dann in einem anderen Bucket gespeichert.

Was ich machen wollte

Da S3 ein statischer Site-Hosting-Dienst ist, kann er auf der Serverseite grundsätzlich nicht dynamisch verarbeitet werden. Natürlich kann auch die CDN-Seite (CloudFront), die danach das Ziel für das Caching ist, nicht verwendet werden.

In diesem Fall besteht die Standardmethode meiner Meinung nach darin, eine lokale Entwicklungsumgebung zu erstellen, Dateien lokal zu trennen und sie beim Kompilieren zu kombinieren. S3 + ist jedoch eine vorhandene Site, die ursprünglich SSI verwendet hat. Leider kann dieser Ablauf nicht in allen Projekten eingeführt werden, auch nicht bei der Übertragung auf CloudFront.

Wenn also SSI ursprünglich verwendet wurde, habe ich versucht, es auf der AWS-Seite so anzupassen, dass es so verwendet werden kann, wie es ist, ohne es so zu ersetzen, wie es ist.

Was ich getan habe

(Voraussetzung ist, dass die IAM-Einstellungen abgeschlossen sind.)

Grundsätzlich verweise ich auf diesen Artikel und passe ihn für mich an. Machen Sie etwas SSI-ähnliches mit S3 und Lambda

Auf der Referenzseite war ich ein wenig besorgt, dass ich ".ssi" als Suffix zur Erweiterung der Originaldatei hinzufügen musste. Ein Eimer für die Temperatur wird separat vorbereitet und so eingestellt, dass er ohne Hinzufügen eines Suffix verarbeitet werden kann.

Verfassung

Grundsätzlich nutzen wir nur S3 und Lambda. CloudFront bei Bedarf. ARMS_TECHSTACK (1) (1).png

Einstellmethode

S3 Bereiten Sie zwei Buckets für das temporäre Hochladen von Dateien und einen Bucket für die Veröffentlichung vor.

Öffentlicher Eimer

Der Name kann alles sein. Diesmal ist es "s3-ssi-include".

Eimer für Temp

Der Name kann alles sein. Diesmal ist es "s3-ssi-include-base".

Jede Einstellung

Es wird davon ausgegangen, dass die Zugriffsberechtigungen entsprechend festgelegt sind. Der temporäre Bucket speichert Dateien und wird nur an den öffentlichen Bucket übergeben, sodass keine Veröffentlichung erforderlich ist. Wenn Sie CloudFront auch für Ihren Veröffentlichungsbereich verwenden, müssen Sie es nicht veröffentlichen.

Eimer für Temp

Gehen Sie auf der Detailseite des Bucket for Temp zu "Eigenschaften" -> "Ereignisbenachrichtigung" -> "Ereignisbenachrichtigung erstellen". Die Lambda-Funktion wird jetzt beim Hochladen der Datei gestartet (PUT-Ereignis)

Schließen Sie die Einstellung nach Auswahl von bis einmal ab. Kehren Sie nach dem späteren Erstellen der Lambda-Funktion wieder zu diesem Bildschirm zurück

Es ist notwendig einzustellen.

Lambda

Lambda erkennt das PUT-Ereignis. Wenn SSI (Server Side Include) in der hochgeladenen HTML-Datei beschrieben ist, schließt Lambda es ein und erstellt eine Funktion zum Speichern in einem anderen Bucket. Bearbeiten Sie für S3 die Ressourcenbasisrichtlinie für public für temporäre Berechtigungen und erteilen Sie Berechtigungen. Ich denke, das Folgende wird hilfreich sein. Lambdas ressourcenbasierte Richtlinie, wenn sie von S3 ausgelöst wird

Funktionscode

import json
import os
import logging
import boto3
from botocore.errorfactory import ClientError
import re
import urllib.parse

logger = logging.getLogger()
logger.setLevel(logging.INFO)
s3 = boto3.client('s3')
def lambda_handler(event, context):
    logger.info('## ENVIRONMENT VARIABLES')
    logger.info(os.environ)
    logger.info('## EVENT')
    logger.info(event)
 
    input_bucket = event['Records'][0]['s3']['bucket']['name']
    output_bucket = os.environ['S3_BUCKET_TARGET']

    logger.info('## INPUT BUKET')
    logger.info(input_bucket)
    
    input_key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
    logger.info('## INPUT KEY')
    logger.info(input_key)

    try:
        #Eingabedatei abrufen
        response = s3.get_object(Bucket=input_bucket, Key=input_key)

        if not input_key.endswith('.html'):
            s3.copy_object(Bucket=output_bucket, Key=input_key, CopySource={'Bucket': input_bucket, 'Key': input_key})
        else:
            input_html = response[u'Body'].read().decode('utf-8')
            output_html = input_html
            #SSI-Beschreibung abrufen
            include_path_base = re.findall(r'<!--#include virtual="/(.*?)" -->.*?\n', input_html, flags=re.DOTALL)
            logger.info('## PATH BASE')
            logger.info(include_path_base)
            if len(include_path_base) > 0:
                for path in include_path_base:
                    include_path = path
                    logger.info('## PATH')
                    logger.info(include_path)
            
                    #SSI-Datei abrufen
                    try:
                        include = s3.get_object(Bucket=input_bucket, Key=include_path)
                        include_html = include[u'Body'].read().decode('utf-8')
                        #Führen Sie SSI aus
                        output_html = output_html.replace('<!--#include virtual="/' + include_path + '" -->', include_html)
                    except ClientError:
                        pass
            
            #Dateiausgabe
            logger.info('## OUTPUT BUKET')
            logger.info(output_bucket)
            
            output_key    = input_key
            logger.info('## OUTPUT KEY')
            logger.info(output_key)
            
            out_s3   = boto3.resource('s3')
            s3_obj   = out_s3.Object(output_bucket, output_key)
            response = s3_obj.put(Body = bytes(output_html, 'UTF-8'))
    except Exception as e:
        logger.info(e)
        raise e

Andere Einstellungen

Umgebungsvariable

Legen Sie den öffentlichen Bucket-Namen (diesmal "s3-ssi-include") in der Umgebungsvariablen "S3_BUCKET_TARGET" auf dem Verwaltungsbildschirm fest.

Speichern Sie es auch einmal und geben Sie die Funktion __Lambda auf der S3-Seite an: Geben Sie die Lambda-Funktion an, die zuvor unter "Aus Lambda-Funktionen auswählen" __ erstellt wurde.

abschließend

Damit ist die Funktion abgeschlossen, mit der Lambda die Include-Datei zum Zeitpunkt des Hochladens der Datei in den S3-Bucket für die Zeit einbettet und in den ursprünglichen öffentlichen S3-Bucket überträgt.

Ich denke, dass es in S3 gespeichert werden kann, als ob es auf einen normalen Webserver hochgeladen worden wäre. Wenn Sie also eine Site migrieren müssen, die SSI zu S3 + CloudFront für die Site-Migration usw. verwendet, wird dies häufig in SSI beschrieben. Sie können Dateien migrieren, ohne sie alle auf einmal ersetzen zu müssen. Wenn Sie die allgemeinen Dateien, die ursprünglich von SSI verwaltet wurden, durch jede Datei ersetzen, werden die gemeinsamen Dateien danach fest codiert, was die Arbeitskräfte und das Risiko des Vorgangs erhöht. Um ehrlich zu sein, möchte ich nicht zu viel tun, da die Gefahr menschlicher Fehler beim Batch-Austausch selbst besteht. Angesichts dessen frage ich mich, ob diese Funktion recht praktisch ist. Der Nachteil ist jedoch, dass es viel kostet, weil es zwei Eimer verwendet, und es ist ein wenig schwer zu verstehen, so dass es notwendig ist, es richtig bekannt zu machen.

Mit der Entwicklung von CI / CD und Docker denke ich, dass es weniger Situationen gibt, in denen Sie sich über das oben Gesagte Sorgen machen. Es gibt nicht nur solche Websites auf der Welt, daher frage ich mich, ob es eine so ruhige Nachfrage gibt.

Das ist alles vom Feld.

Recommended Posts

[AWS] Machen Sie SSI-ähnliche Dinge mit S3 / Lambda
[AWS] Verknüpfen Sie Lambda und S3 mit boto3
Stellen Sie mit AWS Lambda Python eine Verbindung zu s3 her
PyTorch mit AWS Lambda [Lambda-Import]
[AWS] Was tun, wenn Sie mit Lambda pfeifen möchten?
Ausgabe von CloudWatch-Protokollen an S3 mit AWS Lambda (Pythyon ver)
[AWS] API mit API Gateway + Lambda erstellen
Einfacher AWS S3-Test mit MinIO
Benachrichtigen Sie HipChat mit AWS Lambda (Python)
Senden Sie mit ESP32-WROOM-32 aufgenommene Bilder an AWS (API Gateway → Lambda → S3).
[AWS] Verwenden von INI-Dateien mit Lambda [Python]
Ich habe gerade FizzBuzz mit AWS Lambda gemacht
[AWS] Erstellen Sie mit CodeStar eine Python Lambda-Umgebung und führen Sie Hello World aus
Laden Sie das, was Sie angefordert haben, mit AWS Lambda Python in S3 hoch
[AWS SAM] Erstellen Sie eine API mit DynamoDB + Lambda + API Gateway
Regelmäßiges Serverless Scraping mit AWS Lambda + Scrapy Teil 1.8
Zeigen Sie Bilder in S3 mit API Gateway + Lambda an
Serverlose Anwendung mit AWS SAM! (APIGATEWAY + Lambda (Python))
[AWS] Versuchen Sie, API Gateway + Lambda mit X-Ray zu verfolgen
Exportieren Sie den RDS-Snapshot mit Lambda (Python) nach S3.
Ich habe versucht, AWS Lambda mit anderen Diensten zu verbinden
Automatisierung des Infrastrukturbaus mit CloudFromation + Tropical + AWS Lambda
[AWS] Spielen mit Schrittfunktionen (SAM + Lambda) Teil 3 (Zweig)
Stellen Sie die Python 3-Funktion mit Serverless Framework unter AWS Lambda bereit
Erstellen Sie in Docker eine Ebene für AWS Lambda Python
[AWS] Spielen mit Schrittfunktionen (SAM + Lambda) Teil 1 (Basic)
Ich möchte Lambda mit Python auf Mac AWS!
Verwalten Sie die Aufbewahrung von Amazon CloudWatch-Protokollgruppen mit AWS Lambda
Dinge zu tun, wenn Sie anfangen, sich mit Django zu entwickeln
Machen Sie mit AWS Lambda und Python gewöhnliche Tweets flottenartig
[AWS] Spielen mit Schrittfunktionen (SAM + Lambda) Teil 2 (Parameter)
Bilden Sie Lambda-Schichten mit Lambda
Aggregierte AWS S3-Daten
Mach Houdini mit Python3! !! !!
Tweet von AWS Lambda
S3 Uploader mit Boto
Probieren Sie AWS Lambda Destinations aus
[AWS] Versuchen Sie, die Python-Bibliothek mit SAM + Lambda (Python) zur Ebene hinzuzufügen.
Versuchen Sie, Start / Stop für EC2-Instanzen mit AWS Lambda zu automatisieren
Ich habe gerade eine virtuelle Umgebung mit der AWS-Lambda-Schicht erstellt
Erstellen Sie mit AWS SAM schnell eine API mit Python, Lambda und API Gateway
[Python] Exportieren Sie regelmäßig mit Lambda aus CloudWatch-Protokollen nach S3
Site-Überwachung und Alarmbenachrichtigung mit AWS Lambda + Python + Slack