tl;dr
ES2015 で書くので前回参照。 S3 バケットに Markdown を置いたら Lambda Function が発火して、別のパスに HTML が出力されるようにしてみる。ソースはこちら。
やりたいこと
ユーザーが Markdown をアップロードするのは /.src/
以下、出力された HTML が出力されるのはバケット直下とします。
例: s3://orenobucket/.src/orenopage/index.md
をアップロードすると s3://orenobucket/orenopage/index.html
が出力される。
Lambda Function を書く
前回、 ES2015 で書いて簡単にデプロイできるようになったので、このリポジトリの内容から引き続き作業する前提で進めます。
まず、 S3 オブジェクトへの読み書きをしなくてはならないので、 AWS SDK を追加。 aws-sdk
は Lambda の Node.js にはグローバルで導入されているので必須ではないですが…
$ npm install aws-sdk --save
さらに、 Lambda が使用する IAM Role で s3:GetObject
と s3:PutObject
ができるようにしておくのを忘れずに。
もちろん Markdown を HTML に変換できなくてはならないので、今回は evilstreak/markdown-js を使用。
$ npm install markdown-js --save
せっかく Babel を使うのだから async/await を使ってみる。このために Babel の Stage 3 用 preset が必要。
$ npm install babel-preset-stage-3 --save-dev
Babel の設定ファイルにも stage-3
preset を追加。
.babelrc
{ "presets": [ "es2015", "stage-3" ] }
できたのがこちら
functions/markdown2html/src/index.js
import lambda from 'apex.js' import util from 'util' import AWS from 'aws-sdk' import {markdown} from 'markdown' import 'babel-polyfill' const s3 = new AWS.S3(); export default lambda(async (evt, ctx) => { let bucketName = evt.Records[0].s3.bucket.name; let srcKey = evt.Records[0].s3.object.key; let destKey = srcKey.replace(/^.src//, '').replace(/.md$/, '.html'); let srcData = await s3.getObject({ Bucket: bucketName, Key: evt.Records[0].s3.object.key, }).promise(); let markdownBody = (new Buffer(srcData.Body)).toString(); let html = `Converted from s3://${bucketName}/${evt.Records[0].s3.object.key} ${markdown.toHTML(markdownBody)} ` let destData = await s3.putObject({ Bucket: bucketName, Key: destKey, Body: html, ContentType: 'text/html', }).promise(); return(destData); });
async/await を使用することで、 S3 周りの非同期処理が極めてすっきり書けていることに注目されたい。
追記: aws-sdk@2.3.0
で Promise がサポートされたので、自前で promisify する必要がなくなりました。最高。
S3 の Notification を設定する
S3 バケットの設定でイベントトリガーを追加する。
試してみる
test/index.md
# THE MOST EPIC MARKDOWN EVER THE MOST EPIC PARAGRAPH!! - THE MOST EPIC LIST ITEM 1 - THE MOST EPIC LIST ITEM 2 - THE MOST EPIC LIST ITEM 3
test/orenopage/index.html
**日本語** もいける? [リンク](http://qiita.com/y13i)もしちゃうよ?
適当に Markdown ファイルを作って S3 にアップロードする。
$ aws s3 cp --recursive test/ s3://orenobucket/.src
ちゃんと動いているっぽい。
$ aws s3 ls s3://orenobucket/ PRE .src/ PRE orenopage/ 2016-05-06 20:56:02 363 index.html
せっかくなので、静的ウェブサイトホスティングを有効化し、 Bucket Policy で Public Read な状態にしてブラウザーから見てみる。
はい。