LoginSignup
18
18

More than 5 years have passed since last update.

AWS Lambda で S3 に置かれた Markdown を HTML に変換する

Last updated at Posted at 2016-05-06

tl;dr

ES2015 で書くので前回参照。 S3 バケットに Markdown を置いたら Lambda Function が発火して、別のパスに HTML が出力されるようにしてみる。ソースはこちら

やりたいこと

Untitled.png

ユーザーが 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:GetObjects3: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 = `
    <!DOCTYPE html>
    <html>
      <head>
        <title>Converted from s3://${bucketName}/${evt.Records[0].s3.object.key}</title>
      </head>
      <body>
        ${markdown.toHTML(markdownBody)}
      </body>
    </html>
  `

  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 バケットの設定でイベントトリガーを追加する。

S3_Management_Console.png

試してみる

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 な状態にしてブラウザーから見てみる。

Converted_from_s3___wordless-test__src_index_md 2.png

Converted_from_s3___wordless-test__src_orenopage_index_md.png

はい。

参考

18
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
18