4. HTML問い合わせフォームの作成¶
作業対象 [what]¶
- S3サービス
標準時間¶
8分
前提条件¶
作業権限条件 [who]¶
本作業は、以下の作業権限を有する人が行います。
作業権限条件: S3への権限
S3に対してフル権限があること。
作業権限条件: Congnito Identityへの権限
Cognito Identityに対してRead権限があること。
作業環境条件 [where]¶
本作業は、以下の作業環境で行います。
作業環境条件1: OSとバージョン
Amazon Linuxの以下のバージョンで動作確認済
コマンド:
cat /etc/issue | head -1
結果(例):
Amazon Linux AMI release 2016.09
作業環境条件2: シェルとバージョン
bashの以下のバージョンで動作確認済
コマンド:
bash --version -v | head -1
結果(例):
GNU bash, バージョン 4.2.46(1)-release (x86_64-redhat-linux-gnu)
作業環境条件3: AWS CLIのバージョン
以下のバージョンで動作確認済
- AWS CLI 1.11.117
コマンド:
aws --version
結果(例):
aws-cli/1.11.144 Python/2.7.12 Linux/4.4.11-23.53.amzn1.x86_64 botocore/1.7.2
バージョンが古い場合は最新版に更新しましょう。
コマンド:
sudo -H pip install -U awscli
開始条件¶
作業に必要なモノ・情報 [resource]¶
作業開始には、以下が全て揃っていることが必要です。
リソース1: コンテンツファイル用ディレクトリ
今回は"${HOME}/tmp/conf-html-handson20170904"をコンテンツファイル用ディレクトリとします。
ls ${HOME}/tmp/conf-html-handson20170904
存在しない場合は作成します。
mkdir -p ${HOME}/tmp/conf-html-handson20170904
リソース2: コンテンツ用S3バケット名
- コンテンツ用S3バケットの名称です。
- 今回は"handson20170904web-XXXXXXXXXXXX"とします。
リソース3: データ保存用S3バケット名
- データ保存用S3バケットの名称です。
- 今回は"handson20170904data-XXXXXXXXXXXX"とします。
リソース4: Cognito識別子プール名
- 利用するCognito識別子プールのの名称です。
- 今回は"handson20170904pool"とします。
タスクの実施¶
0. パラメータの指定¶
まず変数の確認をします。
変数の確認:
cat << ETX 0.a. AWS_DEFAULT_PROFILE: actual: ${AWS_DEFAULT_PROFILE} expect: <S3のフル権限が許可されているプロファイル> 0.b. AWS_DEFAULT_REGION: actual: ${AWS_DEFAULT_REGION} expect: ap-northeast-1 0.1. DIR_CONTENTS: actual: ${DIR_CONTENTS} expect: ${HOME}/tmp/conf-html-handson20170904 0.2. S3_BUCKET_NAME: actual: ${S3_BUCKET_NAME} expect: handson20170904web-XXXXXXXXXXXX 0.3. S3_BUCKET_DATA: actual: ${S3_BUCKET_DATA} expect: handson20170904data-XXXXXXXXXXXX 0.4. COGNITO_IDPOOL_NAME: actual: ${COGNITO_IDPOOL_NAME} expect: handson20170904pool ETX
変数が入っていない、適切でない場合は、それぞれの手順番号について作業を行います。
0.a. プロファイルの指定¶
プロファイルの一覧を確認します。
コマンド:
cat ~/.aws/credentials \ | grep '\[' \ | sed 's/\[//g' | sed 's/\]//g'
結果(例):
iamFull-prjz-mbpr13 <S3のフル権限が許可されているプロファイル>
変数の設定:
export AWS_DEFAULT_PROFILE='<S3のフル権限が許可されているプロファイル>'
0.3. データ保存用S3バケット名の指定¶
データ保存用S3バケット名を指定します。
変数の設定:
S3_BUCKET_DATA='handson20170904data-XXXXXXXXXXXX'
再確認¶
設定されている変数の内容を再確認します。
変数の確認:
cat << ETX 0.a. AWS_DEFAULT_PROFILE: actual: ${AWS_DEFAULT_PROFILE} expect: <S3のフル権限が許可されているプロファイル> 0.b. AWS_DEFAULT_REGION: actual: ${AWS_DEFAULT_REGION} expect: ap-northeast-1 0.1. DIR_CONTENTS: actual: ${DIR_CONTENTS} expect: ${HOME}/tmp/conf-html-handson20170904 0.2. S3_BUCKET_NAME: actual: ${S3_BUCKET_NAME} expect: handson20170904web-XXXXXXXXXXXX 0.3. S3_BUCKET_DATA: actual: ${S3_BUCKET_DATA} expect: handson20170904data-XXXXXXXXXXXX 0.4. COGNITO_IDPOOL_NAME: actual: ${COGNITO_IDPOOL_NAME} expect: handson20170904pool ETX
1. 前処理¶
1.1. 処理対象の状態確認¶
主処理の実施は、以下の状態であることを前提とします。
前提と異なることが判明した場合、直ちに処理を中止します。
事前条件1: コンテンツファイル用ディレクトリが存在する。
「コンテンツファイル用ディレクトリが存在する。」ことを確認します。
コマンド:
ls -d ${DIR_CONTENTS}
結果(例):
${HOME}/tmp/conf-html-handson20170904
事前条件2: S3バケット"handson20170904web-XXXXXXXXXXXX"が存在する。
「S3バケット"handson20170904web-XXXXXXXXXXXX"が存在する。」ことを確認します。
コマンド:
aws s3api list-buckets \ --query "Buckets[?Name == \`${S3_BUCKET_NAME}\`].Name"
結果(例):
[ "handson20170904web-XXXXXXXXXXXX" ]
事前条件3: S3バケット"handson20170904data-XXXXXXXXXXXX"が存在する。
「S3バケット"handson20170904data-XXXXXXXXXXXX"が存在する。」ことを確認します。
コマンド:
aws s3api list-buckets \ --query "Buckets[?Name == \`${S3_BUCKET_DATA}\`].Name"
結果(例):
[ "handson20170904data-XXXXXXXXXXXX" ]
事前条件4: Cognito識別子プール"handson20170904pool"が存在する。
「Cognito識別子プール"handson20170904pool"が存在する。」ことを確認します。
コマンド:
aws cognito-identity list-identity-pools \ --max-results 60 \ --query "IdentityPools[?IdentityPoolName==\`${COGNITO_IDPOOL_NAME}\`].IdentityPoolName"
結果(例):
[ "handson20170904pool" ]
1.2. 主処理に必要な情報の取得¶
IDプールIDの取得
コマンド:
COGNITO_IDPOOL_ID=$( \ aws cognito-identity list-identity-pools \ --max-results 60 \ --query "IdentityPools[?IdentityPoolName==\`${COGNITO_IDPOOL_NAME}\`].IdentityPoolId" \ --output text \ ) \ && echo ${COGNITO_IDPOOL_ID}
結果(例):
ap-northeast-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
問合せフォームの作成
変数の設定:
FILE_FORM="${DIR_CONTENTS}/contact.html"
変数の確認:
cat << ETX AWS_DEFAULT_REGION: ${AWS_DEFAULT_REGION} COGNITO_IDPOOL_ID: ${COGNITO_IDPOOL_ID} S3_BUCKET_DATA: ${S3_BUCKET_DATA} FILE_FORM: ${FILE_FORM} ETX
ファイルの作成:
cat << EOF > ${FILE_FORM} <!DOCTYPE html> <meta charset="UTF-8"> <script src="https://sdk.amazonaws.com/js/aws-sdk-2.108.0.min.js"></script> <title>お問い合わせフォーム</title> <script> var func = function(id) { return document.getElementById(id); }; AWS.config.region = "${AWS_DEFAULT_REGION}"; AWS.config.credentials = new AWS.CognitoIdentityCredentials({IdentityPoolId: "${COGNITO_IDPOOL_ID}"}); AWS.config.credentials.get(function(err) { if (!err) { console.log("Cognito Identify Id: " + AWS.config.credentials.identityId); } }); function uploadFile() { AWS.config.region = '${AWS_DEFAULT_REGION}'; var s3BucketName = "${S3_BUCKET_DATA}"; var now = new Date(); var obj = {"title": func("title").value, "mail": func("mail").value ,"contents": func("contents").value, "date": now.toLocaleString()}; var s3 = new AWS.S3({params: {Bucket: s3BucketName}}); var blob = new Blob([JSON.stringify(obj, null, 2)], {type:'text/plain'}); s3.putObject({Key: "uploads/" +now.getTime()+".txt", ContentType: "text/plain", Body: blob, ACL: "public-read"}, function(err, data){ if(data !== null){ window.location.href = './thanks.html'; } else{ alert("Upload Failed" + err.message); } }); } </script> <div> <div> <form> <table> <tr> <th>件名</th> <td><input id="title" type="text" name="title" maxlength="40" value="" /></td> </tr> <tr> <th>メールアドレス</th> <td><input id="mail" type="email" name="mail" size="20" maxlength="50" /></td> </tr> <tr> <th>お問い合わせ内容</th> <td><textarea id="contents" cols="70" rows="6" name="contents"></textarea></td> </tr> </table> <div> <input onClick="uploadFile();" type="button" value="送信" id="button" /> </div> </form> </div> </div> EOF cat ${FILE_FORM}
インデックスページの作成
変数の設定:
FILE_INDEX="${DIR_CONTENTS}/index.html"
変数の確認:
cat << ETX FILE_INDEX: ${FILE_INDEX} ETX
ファイルの作成:
cat << EOF > ${FILE_INDEX} <!DOCTYPE html> <meta charset="UTF-8"> <title>ようこそ</title> <h1>ようこそ</h1> <p><a href="./contact.html">お問い合わせ</a></p> EOF cat ${FILE_INDEX}
Thanksページの作成
変数の設定:
FILE_THANKS="${DIR_CONTENTS}/thanks.html"
変数の確認:
cat << ETX FILE_THANKS: ${FILE_THANKS} ETX
ファイルの作成:
cat << EOF > ${FILE_THANKS} <!DOCTYPE html> <meta http-equiv="refresh" content="5;URL=./index.html"> <meta charset="UTF-8"> <title>お問い合わせありがとうございました。</title> <h1>お問い合わせありがとうございました。</h1> <p><a href="./index.html">トップページに戻る</a></p> EOF cat ${FILE_THANKS}
2. 主処理¶
フォームの転送¶
変数の確認:
cat << ETX DIR_CONTENTS: actual: ${DIR_CONTENTS} expect: ${HOME}/tmp/conf-html-handson20170904 S3_BUCKET_NAME: actual: ${S3_BUCKET_NAME} expect: handson20170904web-XXXXXXXXXXXX ETX
コマンド:
cd ${DIR_CONTENTS} \ && aws s3 sync . s3://${S3_BUCKET_NAME}/
3. 後処理¶
3.1. 状態確認に必要な情報の取得¶
問い合わせフォームのURLの取得
変数の設定:
S3_BUCKET_REGION=$( \ aws s3api get-bucket-location \ --bucket ${S3_BUCKET_NAME} \ --output text \ ) \ && echo ${S3_BUCKET_REGION}
結果(例):
ap-northeast-1
変数の設定:
URL_S3_BUCKET="http://${S3_BUCKET_NAME}.s3-website-${S3_BUCKET_REGION}.amazonaws.com" \ && echo ${URL_S3_BUCKET}
結果(例)
http://handson20170904web-XXXXXXXXXXXX.s3-ap-northeast-1.amazonaws.com
変数の設定:
URL_CONTACT="${URL_S3_BUCKET}/contact.html" \ && echo ${URL_CONTACT}
結果(例)
http://handson20170904web-XXXXXXXXXXXX.s3-ap-northeast-1.amazonaws.com/contact.html
ブラウザで上記のURLを開きます。
3.2. 完了条件の確認¶
- コンタクトフォームの下記の項目に入力をします。
- 件名: こんにちは
- メールアドレス: info@example.jp
- お問い合わせ内容: ご無沙汰しております。
- "送信"(ボタン)を押します。
- SNSに登録したメールアドレスに通知が来ます。
- 題名: Amazon S3 Notification
- 本文: JSON形式
3.3. 後処理に必要な作業¶
S3バケットの確認
コマンド:
aws s3 ls ${S3_BUCKET_DATA}/uploads/
結果(例):
2017-09-04 01:23:45 142 1504447230062.txt
問い合わせの取得
コマンド:
mkdir -p ${HOME}/tmp/${S3_BUCKET_NAME} \ && cd ${HOME}/tmp/${S3_BUCKET_NAME}
コマンド:
aws s3 cp --recursive s3://${S3_BUCKET_DATA}/uploads . \
結果(例):
download: s3://handson20170904web-XXXXXXXXXXXX/uploads/1504447230062.txt to ./1504447230062.txt
コマンド:
cat *.txt
結果(例):
{ "title": "こんにちは", "mail": "info@example.jp", "contents": "ご無沙汰しております。", "date": "2017/9/4 20:00:30" }
問い合わせの消去
コマンド:
cd \ && rm -r ${HOME}/tmp/${S3_BUCKET_NAME}