React axiosとAWS Lambdaを用いて、webページからwebアプリを実行する方法を紹介する。
フロントエンド(React)の作成
- axiosをインストールする
npm install axios --save
- axiosをimportして、webアプリのURLへPOSTする
import React from 'react' import axios from 'axios' const Breadcrumbs = () => { const [responseData, setResponseData] = React.useState(null) const handleSubmission = async (event) => { try { await axios .post( 'https://*****************************', event, { headers: { 'Content-type': 'text/plain', }, }, ) .then((res) => { setResponseData(res.data) }) } catch (err) { console.error(err) alert('[ERROR] POSTに失敗しました。') } } }
-
'https://*****************************'
の部分を以下で作成するwebアプリのURLに置き換える。
バックエンド(Lambda関数)の作成
lambdaへPythonコードをアップロードする
- 下記のPythonコードを作成する
CORS(Cross-Origin Resource Sharing)で、どのWebサイトにもOriginを越えるアクセスを許可するため、返却するヘッダーにAccess-Control-Allow-OriginとAccess-Control-Allow-Headersを加えることに注意する。
lambda_function.py
import os
import sys
import time
import json
import base64
import io
import csv
import boto3
import cgi
from requests_toolbelt.multipart import decoder
def lambda_handler(event, context):
if 'content-type' in event['headers'].keys():
body = event["body"].encode('utf-8')
content_type = event['headers']['content-type']
c_type, c_data = cgi.parse_header(event['headers']['content-type'])
elif 'Content-Type' in event['headers'].keys():
body = event["body"].encode('utf-8')
content_type = event['headers']['Content-Type']
c_type, c_data = cgi.parse_header(event['headers']['Content-Type'])
else:
raise RuntimeError('content-type or Content-Type not found')
data = json.loads(body)
return {
'statusCode': 200,
'headers': {
+ "Access-Control-Allow-Origin": "*",
+ "Access-Control-Allow-Headers": "Content-Type",
},
'body': json.dumps('正常にアップロードされました!')
}
- 同じフォルダで下記コマンドを実行して、ローカルにPython moduleをインストールする
pip install -t . --platform manylinux2014_x86_64 --implementation cp --python 3.9 --only-binary=:all: --upgrade requests-toolbelt
- zipで圧縮する
- 「コード」->「アップロード元」->「.zipファイル」で圧縮したzipファイルを選択して、アップロードする
LambdaにS3とDynamoDBのフルアクセス権限を付与する
- 「設定」>「アクセス権限」>実行ロールのロール名のリンクをクリックする
- 「許可」>「許可を追加」>「ポリシーをアタッチ」をクリックする
- AmazonS3FullAccessとAmazonDynamoDBFullAccessにチェックを入れ、「ポリシーをアタッチ」をクリックする
タイムアウトとメモリの設定を変更する
- 「設定」->「一般設定」からメモリを500MBとタイムアウトを15分に変更する
APIgatewayでwebAPIを作成する
- トリガーを作成をクリックして、ソースを選択からAPIGatewayをクリックする
- Create New APIを選択する
- REST APIを選択する
- 追加を押す
- APIGatewayで作成したAPIの名前をクリックする
- 「アクション」->「メゾッドの作成」->でPOSTを選択する
- 作成したPOSTをクリックし、統合レスポンスをクリックする
- マッピングテンプレートをクリックして、マッピングテンプレートの追加を押す
-
application/json;charset=UTF-8
を追記して、右のチェックを押す - 右側のテンプレートの欄に、
$input.json('$')
を記入する
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html - 保存を押す
非同期APIにする場合
- [Resources] (リソース) で [POST] を選択し、[Integration Request] (統合リクエスト) を選択する
- [HTTP Headers] (HTTP ヘッダー) を展開し、[Add header] (ヘッダーを追加) を選択する
- [Name] (名前) に X-Amz-Invocation-Type、 [Mapped from] (マッピング元) に'Event'と入力する
- REST API を再デプロイする
- 以上
非同期APIではLambdaで受け取るeventの形式が異なり、データサイズが同期が6MBに対して、248KBしかないたため、注意。
あと、なぜかCORSをわざわざAPI gatewayで有効化しないといけない。
補足
Lmabdaのファイルの開き方はいくつかある
パターン1
import csv
import io
import requests
def lambda_handler(event, context):
csv_file = event['body']
data = io.StringIO(csv_file)
reader = csv.DictReader(data)
for row in reader:
print(row['column_1'], row['column_2'], row['column_3'], ...)
return {
'statusCode': 200,
'body': 'CSV file processed successfully'
}
パターン2
import io
def lambda_handler(event, context):
file_data = event['body']
decoded_file = file_data.decode('utf-8')
lines = decoded_file.split('\n')
for line in lines:
print(line)
return {
'statusCode': 200,
'body': 'File processed successfully'
}
参考記事