キャッシュさせないCloudFrontディストリビューションを設定してみた(CloudFormationテンプレート付)

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは植木和樹@上越妙高オフィスです。今回は題名通り「キャッシュしない」CloudFront設定を行ってみました。

CDN(Contents Delivery Network)であるCloudFrontにキャッシュさせないのって意味があるの?と思われるかもしれませんが、理由は色々あります。

  • 基本キャッシュしてほしくないけど、一部のパス(CSSとか画像とか)は同じドメインでキャッシュさせたい
  • LINEやTwitterでの告知するページだけキャッシュさせたいので、事前にCloudFrontは準備しておきたい
  • パス毎にオリジンを変えたい(L7ロード・バランシングしたい)
  • Amazon WAF使いたいけどキャッシュはしたくない(私の今回の目的です)

ネットで調べると同じ思いの方は結構いらっしゃるようですね。

一撃設定CloudFormation

キャッシュさせないCloudFrontを一発で作るCloudFormationテンプレートを作ったので、興味がある方はご利用ください。

キャッシュしないCloudFrontを設定する

AWSマネージメントコンソールにログインした状態で、上のボタンをクリックするとNoCachedCloudFrontという名前でCloudFormationスタックを作成する画面が開きます。パラメーターとしてOriginの入力が求められるので、オリジンサーバーのホスト名を入力してからスタックを作成してください。(10分くらいかかります)

設定の概要

広く知られている設定をまとめています。

  • Allowed HTTP Methodsをすべてに(GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE)
  • Forward HeadersをAllに
  • Object CachingでMinimum TTL, Maximum TTL, Default TTLをすべて0(秒)に
  • Forward CookiesをAllに
  • Forward Query StringsをYesに
  • Error Pagesで主要HTTP Error CodeのTTLを1(秒)に

検証

(検証1) Cookie(PHPSESSID)が有効なこと

PHPで作成したカウンターページです。ページをリロードする度にカウントアップすれば成功です。

test_cookie.php

<?php
session_start();
if (!isset($_SESSION['count'])) {
  $_SESSION['count'] = 0;
} else {
  $_SESSION['count']++;
}
echo $_SESSION['count'];
?>

(検証2) クエリーパラメータを通すこと、HTTPステータスコード 302(リダイレクト)がキャッシュされないこと

クリックするたびにファイルのロック/アンロックが切り替われば成功です。

test_302.php

<?php
function h($str) {
  echo htmlspecialchars($str);
}

$filename = "/tmp/mylock";
file_exists($filename) or touch($filename);
$state = file_get_contents ($filename);

if(isset($_GET["action"])){
  $state = ($state xor 1);
  file_put_contents($filename, $state);
  $redirect = $_SERVER['REQUEST_SCHEME']."://".$_SERVER['SERVER_NAME'].$_SERVER['PHP_SELF'];
  header("Location: $redirect", true, '302');
  exit;
}

$link = $_SERVER['PHP_SELF'];
$link .= '?action=';
$link .= $state ? 'unlock' : 'lock';
?>
<html>
<body>
State: <?php h($state ? "locked" : "unlocked") ?><br/>
<a href="<?php h($link) ?>">
<?php h($state ? "unlock" : "lock") ?>
</a>
</body>
</html>

(検証3) POSTされたページはキャッシュされないこと

test_post.php

テキストフィールドに名前を入力した名前が表示されれば成功です。毎回違う名前を入力してキャッシュされないことを確認してみてください。

<?php
function h($str) {
  echo htmlspecialchars($str);
}

$name = !empty($_POST["name"]) ? $_POST["name"] : "no-name";
?>
<html>
<body>
<form method="POST">
<input type="text" name="name">
<button type="submit">Send</button>
</form>
<?php h($name) ?>
</body>
</html>

検証足りないよ! キャッシュされちゃうよ! という方いらっしゃいましたらご指摘ください。

まとめ

Webシステムを利用される方は、まずは前段にCloudFrontを利用されることを検討した方が良いでしょう。リリースした後にCloudFrontを組み込むと、思いがけずキャッシュされたり、キャッシュ要否を制御しやすいパス構成になっていなかったりと苦労することが多いようです。最初にCloudFrontだけでも設定しておけば、一部のパスから徐々に導入もできますのでオススメです。

「AWSを使う時はまずCloudFront」ぜひご検討ください。