Posted at

S3にファイルをアップロードしたときに自動的にCache-Controlを設定する


はじめに

ふとPage Speed Insightを眺めていたら、ブラウザキャッシュが効いてないファイルが・・・ :thinking:

そういえば、S3に置いてるファイルってCache-Control設定されてないやん!:open_mouth:

ということで、AWS Lambdaを使って、S3にアップロードされたときに自動的にCache-Controlを設定する仕組みを作っていきます :muscle:


Lambdaを作成する

まずは要のLambda functionを作っていきます。

一から作るよりもテンプレートを使ったほうが手っ取り早いので、

関数の作成 > 設計図 > s3-get-object を選択して「設定」をポチります。

適当な関数名をつけて、ロールもテンプレートから新しく作成しちゃいましょう。

(このロールのままだと権限が不足してるのであとで編集していきます :point_up:

スクリーンショット 2018-10-11 15.54.32.png

S3のイベントタイプは「PUT」を選択し、「関数の作成」をポチります。

スクリーンショット_2018-10-11_15_47_19.png

するとこんな感じで関数ができあがります。

スクリーンショット 2018-10-11 16.35.42.png

テンプレートの関数を編集して、Cache-Controlを付与するように書き換えます。

(今回はmax-age=86400にしました)

console.log('Loading function');

const aws = require('aws-sdk');

const s3 = new aws.S3({ apiVersion: '2006-03-01' });

exports.handler = async (event, context) => {

const bucket = event.Records[0].s3.bucket.name;
const key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' '));
console.log('Bucket: ', bucket);
console.log('Key: ', key);

try {
const data = await s3.getObject({Bucket: bucket, Key: key}).promise();

const contentType = data.ContentType ? data.ContentType : 'application/octet-stream';
const params = {
Bucket: bucket,
CopySource: `${bucket}/${key}`,
Key: key,
ContentType: contentType,
CacheControl: "max-age=86400",
MetadataDirective: "REPLACE"
};

const newData = await s3.copyObject(params).promise();

console.log('success!');
} catch (err) {
console.log(err);
throw new Error(err.message);
}
};

いったんここで「保存」をポチっておきます。 :sleeping:


ロールを編集する

テンプレートから作成したロールのままだとS3の読み込み権限しかないので、書き込み権限を追加します。

IAM > ロール に移動し、作成したロール(今回だとlambdaS3Role)のS3ポリシーに書き込み権限を追加します。

VisualEditorでポチポチ設定できます。お手軽〜 :smile:

スクリーンショット 2018-10-11 16.09.08.png

結果、S3に関するポリシーにs3:PutObjectが追加されました :point_down:

スクリーンショット_2018-10-11_16_10_16.png


動作確認する

では、Lambdaもロールも完成したので、動作確認しましょう。

実際に画像をUPLOADしてみると、Cache-Controlが設定されました :tada:

スクリーンショット_2018-10-11_16_12_17.png

めでたしめでたし :hugging:


参考