[小ネタ] CloudFrontでクエリ文字列を転送する場合の細かなパターンについて確認してみた
はじめに
清水です。Amazon CloudFrontでクエリ文字列をオリジンに転送する(クエリ文字列パラメータに基づいてコンテンツをキャッシュする)場合で、クエリ文字列部分があまり見慣れない?形式のときの挙動が気になったので確認してみました。具体的には以下のような形式/パターンです。
- パラメータの値が空欄の場合
- パラメータに配列要素が出現する場合
- パラメータが複数回現れる場合
それぞれの場合で、意図した通りにパラメータ内容に基づいてコンテンツがキャッシュされるか(パラメータ内容が別であれば別のキャッシュが使われるのか)ということをcurlコマンドで確認してみました。
なおCloudFrontのクエリ文字列パラメータのコンテンツのキャッシュについては、以下のAmazon CloudFrontの開発者ガイドもご参照ください。
検証した環境については、CloudFrontのオリジンサーバとしてEC2上で稼働するApache + PHPを準備しました。オリジンサーバ側では以下のPHPコードを実行した結果をレスポンスとして返すように設定しています。
<?php foreach (getallheaders() as $name => $value) { echo "$name: $value\n"; } echo "\n"; echo "\n"; date_default_timezone_set('Asia/Tokyo'); echo date("Y/m/d H:i:s"); echo "\n"; echo "\n"; parse_str($_SERVER['QUERY_STRING'], $var); var_dump($var); ?>
なお、前提とするCloudFrontのCache Behavior Settingsはlegacy cache settingsとしています。2020年7月にアップデートのあったキャッシュポリシー、オリジンリクエストポリシーについては考慮していません。
パラメータの値が空欄の場合
まずはパラメータ自体はあるけれど、その値が空欄になっているケースです。具体的には以下のようなパラメータ文字列を想定します。
?param=&color=red&size=large
このクエリ文字列のパラメータparam
について、空欄のケース、実際に値があるケース、そしてparam
パラメータ自体がないケース、それぞれでキャッシュの区別がされるのか?ということを確認してみます。
Behaviorの設定では、Query String Forwarding and CachingをForward all, cache based on whitelist
とし、Query String Whitelistにparam
を指定しました。キャッシュ時間はTTLを60秒と指定しています。(以降、キャッシュ時間はすべてTTL 60秒となるよう設定してます。)
実際にcurlコマンドで確認します。確認したい条件それぞれを1秒ごと、連続して(Enterの入力1回で)実行してみます。
% curl "https://d1234567890.cloudfront.net/qs_whitelist_param/qs.php?param=&color=red&size=large"; \ sleep 1; \ curl "https://d1234567890.cloudfront.net/qs_whitelist_param/qs.php?param=1&color=red&size=large"; \ sleep 1; \ curl "https://d1234567890.cloudfront.net/qs_whitelist_param/qs.php?color=red&size=large"; Host: www.example.com User-Agent: Amazon CloudFront X-Amz-Cf-Id: 50Eu3nQwT_O-mzT3QRQN9kplxAIjJ_-eH3UbBiWqOjBjWmcgc2zp8w== Connection: Keep-Alive X-Forwarded-For: XX.XX.XX.XX Via: 2.0 c29e436c21072b427d47688aaf874625.cloudfront.net (CloudFront) 2020/12/05 22:21:33 array(3) { ["param"]=> string(0) "" ["color"]=> string(3) "red" ["size"]=> string(5) "large" } Host: www.example.com User-Agent: Amazon CloudFront X-Amz-Cf-Id: ejuc4c388Arza2df1sUyqqsNwXuOYrplutom65JPRJ9yl14CzqCPkA== Connection: Keep-Alive X-Forwarded-For: XX.XX.XX.XX Via: 2.0 70e24e789a7f5c3f75693b4d637a2d22.cloudfront.net (CloudFront) 2020/12/05 22:21:34 array(3) { ["param"]=> string(1) "1" ["color"]=> string(3) "red" ["size"]=> string(5) "large" } Host: www.example.com User-Agent: Amazon CloudFront X-Amz-Cf-Id: 1dup2tOS08vuCddUjMR3OE8nuJ21bkCaNF_1VPB4NpAqBHni3j-zVQ== Connection: Keep-Alive X-Forwarded-For: XX.XX.XX.XX Via: 2.0 387e8a9502b77ca6a0fb349ab84d9420.cloudfront.net (CloudFront) 2020/12/05 22:21:35 array(2) { ["color"]=> string(3) "red" ["size"]=> string(5) "large" }
サーバ上でのタイムスタンプが1秒ごとに異なり、サーバ側のレスポンス内容も異なります。別々にキャッシュされるということになりますね。確認のためcurl
コマンドに-I
オプションもつけて確認してみます。
% curl -I "https://d1234567890.cloudfront.net/qs_whitelist_param/qs.php?param=&color=red&size=large"; \ sleep 1; \ curl -I "https://d1234567890.cloudfront.net/qs_whitelist_param/qs.php?param=1&color=red&size=large"; \ sleep 1; \ curl -I "https://d1234567890.cloudfront.net/qs_whitelist_param/qs.php?color=red&size=large"; HTTP/2 200 content-type: text/html; charset=UTF-8 date: Sat, 05 Dec 2020 13:23:12 GMT server: Apache/2.4.27 (Amazon) PHP/5.6.35 x-powered-by: PHP/5.6.35 x-cache: Miss from cloudfront via: 1.1 1220701d35c586acd5385ae55b320c99.cloudfront.net (CloudFront) x-amz-cf-pop: NRT57-C1 x-amz-cf-id: 55e3e9YsyWhmuBZeQgOjHnxpOIlqIeQ8ZFOTUFy3Fo1QnXllMLaJIQ== HTTP/2 200 content-type: text/html; charset=UTF-8 date: Sat, 05 Dec 2020 13:23:13 GMT server: Apache/2.4.27 (Amazon) PHP/5.6.35 x-powered-by: PHP/5.6.35 x-cache: Miss from cloudfront via: 1.1 ad1db92b031434a160947f1147cb5db2.cloudfront.net (CloudFront) x-amz-cf-pop: NRT57-C1 x-amz-cf-id: LcLCJP3wwCrodNZIw48dRj9LRBjEdnP3nLTFF3p9aikWGwHgh2JvJw== HTTP/2 200 content-type: text/html; charset=UTF-8 date: Sat, 05 Dec 2020 13:23:14 GMT server: Apache/2.4.27 (Amazon) PHP/5.6.35 x-powered-by: PHP/5.6.35 x-cache: Miss from cloudfront via: 1.1 a2447ed6669558ff303af177568ddb72.cloudfront.net (CloudFront) x-amz-cf-pop: NRT57-C1 x-amz-cf-id: Ud9vm5a_M9dWS23ZBB7p-tlOgGFeDCjDfkIUShEnlIoacKJa0MK-QA==
それぞれでMiss from cloudfront
になっていますね。
パラメータに配列要素が出現する場合
続いてパラメータに配列要素が出現する場合です、具体的には以下のようなパラメータ文字列を想定しています。
?params%5B%5D=1&color=red&size=large
%5B%5D
はURLデコードすれば[]
となりますので、params[]
としてサーバ側では扱われる想定です。このparams%5B%5D
についてはまず正常に(意図した通りに)Behavior設定できるのかの確認、そして値がそれぞれ異なる場合に意図通りキャッシュが区別されるのかを確認してみます。
まずBehaviorの設定については以下のように、params%5B%5D
を入力します。
%
の入力が少し不安でしがた、、よかった、エラーなどは特に発生しません。入力指定可能文字列はa-z
、A-Z
、0-9
、-._*+%
なのでURLエンコードが考慮されているということですね。
続いてcurlコマンドで、パラメータの値が1の場合、2の場合、そしてパラメータがない場合をそれぞれ確認してみます。
% curl "https://d1234567890.cloudfront.net/qs_whitelist_params/qs.php?params%5B%5D=1&color=red&size=large"; \ sleep 1; \ curl "https://d1234567890.cloudfront.net/qs_whitelist_params/qs.php?params%5B%5D=2&color=red&size=large"; \ sleep 1; \ curl "https://d1234567890.cloudfront.net/qs_whitelist_params/qs.php?&color=red&size=large"; Host: www.example.com User-Agent: Amazon CloudFront X-Amz-Cf-Id: YnTOdiWFJOxPxzQBYf1X43V0hrsRaYyq7alfvISCfK1xddDCkoy4cw== Connection: Keep-Alive X-Forwarded-For: XX.XX.XX.XX Via: 2.0 71f3694b51f52454b351b50afa530cff.cloudfront.net (CloudFront) 2020/12/05 22:31:04 array(3) { ["params"]=> array(1) { [0]=> string(1) "1" } ["color"]=> string(3) "red" ["size"]=> string(5) "large" } Host: www.example.com User-Agent: Amazon CloudFront X-Amz-Cf-Id: ujCL6-sweqmBVhT6iEOf2eZWTxuzYDW-d8KsrZi5i1CtKTAGE_L45Q== Connection: Keep-Alive X-Forwarded-For: XX.XX.XX.XX Via: 2.0 9f77226f296168c3bad08d9b3eb8c8ac.cloudfront.net (CloudFront) 2020/12/05 22:31:06 array(3) { ["params"]=> array(1) { [0]=> string(1) "2" } ["color"]=> string(3) "red" ["size"]=> string(5) "large" } Host: www.example.com User-Agent: Amazon CloudFront X-Amz-Cf-Id: 2iyVKi8bKVrJjz9Ft5o9Ol3YUDjSSNVFfRZRtMM_Ptz-B6HxPnbDcQ== Connection: Keep-Alive X-Forwarded-For: XX.XX.XX.XX Via: 2.0 55eeb944ebfbb0b85df2890d4b80abd1.cloudfront.net (CloudFront) 2020/12/05 22:31:07 array(2) { ["color"]=> string(3) "red" ["size"]=> string(5) "large" }
サーバ側のタイムスタンプがそれぞれバラバラです。(2秒かかっているところがありますが、これは微妙な処理時間などが影響しているのかなと考えています。)またサーバ側のレスポンスの内容からも、別々にキャッシュされているということになりますね。こちらも確認のため、curl
コマンドに-I
オプションをつけた結果も確認してみます。
% curl -I "https://d1234567890.cloudfront.net/qs_whitelist_params/qs.php?params%5B%5D=1&color=red&size=large"; \ sleep 1; \ curl -I "https://d1234567890.cloudfront.net/qs_whitelist_params/qs.php?params%5B%5D=2&color=red&size=large"; \ sleep 1; \ curl -I "https://d1234567890.cloudfront.net/qs_whitelist_params/qs.php?&color=red&size=large"; HTTP/2 200 content-type: text/html; charset=UTF-8 date: Sat, 05 Dec 2020 13:32:50 GMT server: Apache/2.4.27 (Amazon) PHP/5.6.35 x-powered-by: PHP/5.6.35 x-cache: Miss from cloudfront via: 1.1 b392241fa800576d1bfcc2a54be3e253.cloudfront.net (CloudFront) x-amz-cf-pop: NRT57-C1 x-amz-cf-id: tjUThBOC20ATZ96zq_uPxM7z5jMDEo6QYC0TA6-_hc2b3nHLXfdk5A== HTTP/2 200 content-type: text/html; charset=UTF-8 date: Sat, 05 Dec 2020 13:32:51 GMT server: Apache/2.4.27 (Amazon) PHP/5.6.35 x-powered-by: PHP/5.6.35 x-cache: Miss from cloudfront via: 1.1 c29e436c21072b427d47688aaf874625.cloudfront.net (CloudFront) x-amz-cf-pop: NRT57-C1 x-amz-cf-id: NxbPUCIe76Xf3hcFcjPs74Nema8HfbLj-Jg7DgTfzmverypXaxmjPA== HTTP/2 200 content-type: text/html; charset=UTF-8 date: Sat, 05 Dec 2020 13:32:52 GMT server: Apache/2.4.27 (Amazon) PHP/5.6.35 x-powered-by: PHP/5.6.35 x-cache: Miss from cloudfront via: 1.1 c6d377025c9d9baa894e9ccc8a2e4817.cloudfront.net (CloudFront) x-amz-cf-pop: NRT57-C1 x-amz-cf-id: bOk8dR4r4yBx3tw5wO_uAT9PwRpioP0DBoZYoV3YzqVZzwqux76ZSw==
こちらもいずれもMiss from cloudfront
となっていることが確認できました。
パラメータが複数回現れる場合
今度はパラメータが複数回現れる場合です。配列要素が出現する場合とも関連していますが、以下のようのなパラメータ文字列の想定です。
?params%5B%5D=1¶ms%5B%5D=2&color=red&size=large
CloudFrontのBehavior設定は、先ほどのパラメータに配列要素が出現する場合と同様、Query String Forwarding and CachingをForward all, cache based on whitelist
とし、Query String Whitelistにparams%5B%5D
を指定した状態で進めます。
以下それぞれでキャッシュの扱いがどうなるか、確認してみます。
?params%5B%5D=1&color=red&size=large
(params%5B%5D
パラメータは1つ)?params%5B%5D=1¶ms%5B%5D=2&color=red&size=large
(params%5B%5D
パラメータが2つで、1つが同じ)
curlコマンドの実行結果は下記になります。別々にキャッシュされていますね、またサーバ側での受け取る内容も異なっています。(2つ目は2つのパラメータを取得。)
% curl "https://d1234567890.cloudfront.net/qs_whitelist_params/qs.php?params%5B%5D=1&color=red&size=large"; \ sleep 1; \ curl "https://d1234567890.cloudfront.net/qs_whitelist_params/qs.php?params%5B%5D=1¶ms%5B%5D=2&color=red&size=large"; Host: www.example.com User-Agent: Amazon CloudFront X-Amz-Cf-Id: YSErb2SX0zHnWbQrdW7PVFrrU2uWGus_LdGDdrcqKXazwYTUid5TkA== Connection: Keep-Alive X-Forwarded-For: XX.XX.XX.XX Via: 2.0 f509de8dab58b37f59931e5954b5eb66.cloudfront.net (CloudFront) 2020/12/05 22:49:41 array(3) { ["params"]=> array(1) { [0]=> string(1) "1" } ["color"]=> string(3) "red" ["size"]=> string(5) "large" } Host: www.example.com User-Agent: Amazon CloudFront X-Amz-Cf-Id: VS5G7JVDwSpslAjwTWqPij7KOU13GzWDyLWalZQsCeNscOaruBdgiw== Connection: Keep-Alive X-Forwarded-For: XX.XX.XX.XX Via: 2.0 a08449218a1b8c326aa3cbb3062341b5.cloudfront.net (CloudFront) 2020/12/05 22:49:42 array(3) { ["params"]=> array(2) { [0]=> string(1) "1" [1]=> string(1) "2" } ["color"]=> string(3) "red" ["size"]=> string(5) "large" }
% curl -I "https://d1234567890.cloudfront.net/qs_whitelist_params/qs.php?params%5B%5D=1&color=red&size=large"; \ sleep 1; \ curl -I "https://d1234567890.cloudfront.net/qs_whitelist_params/qs.php?params%5B%5D=1¶ms%5B%5D=2&color=red&size=large"; HTTP/2 200 content-type: text/html; charset=UTF-8 date: Sat, 05 Dec 2020 13:50:48 GMT server: Apache/2.4.27 (Amazon) PHP/5.6.35 x-powered-by: PHP/5.6.35 x-cache: Miss from cloudfront via: 1.1 cbeb24fadb75eda03a7b228ef184642e.cloudfront.net (CloudFront) x-amz-cf-pop: NRT57-C1 x-amz-cf-id: xGHekftooPFEJpafoBzojbqFJ9YZV_nCbAcVzw8K3qdX3R6yftEv2g== HTTP/2 200 content-type: text/html; charset=UTF-8 date: Sat, 05 Dec 2020 13:50:49 GMT server: Apache/2.4.27 (Amazon) PHP/5.6.35 x-powered-by: PHP/5.6.35 x-cache: Miss from cloudfront via: 1.1 a08449218a1b8c326aa3cbb3062341b5.cloudfront.net (CloudFront) x-amz-cf-pop: NRT57-C1 x-amz-cf-id: PIF9QNxNQHL-fVsXTOe5Yp7eb7XLaxFTuWmTPMOKTvTbUQP2fEDr7A==
パラメータが複数回現れる場合の出現位置とクエリ文字列転送設定
さてもう一つ、パラメータが複数回現れる場合の出現位置について気になる事象があったのでまとめておきます。
具体的にはクエリ文字列として、以下2点のケースです。
?params%5B%5D=1¶ms%5B%5D=2&color=red&size=large
?params%5B%5D=1&color=red&size=large¶ms%5B%5D=2
ここでCloudFrontのBehaviorの設定として、以下2つの場合を比較してみます。2つ目はすべてのクエリ文字列に基づいてキャッシュ判断するケースですね。
- Query String Forwarding and Cachingを
Forward all, cache based on whitelist
とし、Query String Whitelistにparams%5B%5D
を指定 - Query String Forwarding and Cachingを
Forward all, cache based on all
まずはparams%5B%5D
のみをWhitelistに指定した場合です。こちらは同じキャッシュが使われることとなります。
% curl "https://d1234567890.cloudfront.net/qs_whitelist_params/qs.php?params%5B%5D=1¶ms%5B%5D=2&color=red&size=large"; \ sleep 1; \ curl "https://d1234567890.cloudfront.net/qs_whitelist_params/qs.php?params%5B%5D=1&color=red&size=large¶ms%5B%5D=2"; Host: www.example.com User-Agent: Amazon CloudFront X-Amz-Cf-Id: I_JsnH9l-TMzK4hK7-s_bCepi8bac3o9AJhAsVmLqsjO0n5PsiyvrA== Connection: Keep-Alive X-Forwarded-For: XX.XX.XX.XX Via: 2.0 387e8a9502b77ca6a0fb349ab84d9420.cloudfront.net (CloudFront) 2020/12/05 22:53:15 array(3) { ["params"]=> array(2) { [0]=> string(1) "1" [1]=> string(1) "2" } ["color"]=> string(3) "red" ["size"]=> string(5) "large" } Host: www.example.com User-Agent: Amazon CloudFront X-Amz-Cf-Id: I_JsnH9l-TMzK4hK7-s_bCepi8bac3o9AJhAsVmLqsjO0n5PsiyvrA== Connection: Keep-Alive X-Forwarded-For: XX.XX.XX.XX Via: 2.0 387e8a9502b77ca6a0fb349ab84d9420.cloudfront.net (CloudFront) 2020/12/05 22:53:15 array(3) { ["params"]=> array(2) { [0]=> string(1) "1" [1]=> string(1) "2" } ["color"]=> string(3) "red" ["size"]=> string(5) "large" }
% curl -I "https://d1234567890.cloudfront.net/qs_whitelist_params/qs.php?params%5B%5D=1¶ms%5B%5D=2&color=red&size=large"; \ sleep 1; \ curl -I "https://d1234567890.cloudfront.net/qs_whitelist_params/qs.php?params%5B%5D=1&color=red&size=large¶ms%5B%5D=2"; HTTP/2 200 content-type: text/html; charset=UTF-8 date: Sat, 05 Dec 2020 13:54:46 GMT server: Apache/2.4.27 (Amazon) PHP/5.6.35 x-powered-by: PHP/5.6.35 x-cache: Miss from cloudfront via: 1.1 b944914479fde4ca432e3f8eabb3743d.cloudfront.net (CloudFront) x-amz-cf-pop: NRT57-C1 x-amz-cf-id: -A0qVwSybtlRKDfo4sp4vOeoJP3H8J-AvCVDr-ZL5QWZhxqc0mGlAw== HTTP/2 200 content-type: text/html; charset=UTF-8 date: Sat, 05 Dec 2020 13:54:46 GMT server: Apache/2.4.27 (Amazon) PHP/5.6.35 x-powered-by: PHP/5.6.35 x-cache: Hit from cloudfront via: 1.1 8433e30ac6e907a81aa2471c80b4c8cd.cloudfront.net (CloudFront) x-amz-cf-pop: NRT57-C1 x-amz-cf-id: akMfeBGhbcunGMRMDvVQ8JLvswBe1Wn_MwtTheM1zKMgZC4iCyxlYQ== age: 1
続いて、Forward all, cache based on all
の場合です、こちらは別々のキャッシュとして扱われます。
% curl "https://d1234567890.cloudfront.net/qs_all/qs.php?params%5B%5D=1¶ms%5B%5D=2&color=red&size=large"; \ sleep 1; \ curl "https://d1234567890.cloudfront.net/qs_all/qs.php?params%5B%5D=1&color=red&size=large¶ms%5B%5D=2"; Host: www.example.com User-Agent: Amazon CloudFront X-Amz-Cf-Id: rK7fYGbYvhffw13VM8JjxJ1vC3SNztLjthkJX9FQKFExKj5jpcgq_g== Connection: Keep-Alive X-Forwarded-For: XX.XX.XX.XX Via: 2.0 e42c4e94fd6d4f30c6167aa48ead9ff5.cloudfront.net (CloudFront) 2020/12/05 22:55:20 array(3) { ["params"]=> array(2) { [0]=> string(1) "1" [1]=> string(1) "2" } ["color"]=> string(3) "red" ["size"]=> string(5) "large" } Host: www.example.com User-Agent: Amazon CloudFront X-Amz-Cf-Id: vBwfvcEjghWcG36S1OIKOo25IpifqpX6nxwMLnGVXjsy9QQ_gbny5g== Connection: Keep-Alive X-Forwarded-For: XX.XX.XX.XX Via: 2.0 b944914479fde4ca432e3f8eabb3743d.cloudfront.net (CloudFront) 2020/12/05 22:55:21 array(3) { ["params"]=> array(2) { [0]=> string(1) "1" [1]=> string(1) "2" } ["color"]=> string(3) "red" ["size"]=> string(5) "large" }
% curl -I "https://d1234567890.cloudfront.net/qs_all/qs.php?params%5B%5D=1¶ms%5B%5D=2&color=red&size=large"; \ sleep 1; \ curl -I "https://d1234567890.cloudfront.net/qs_all/qs.php?params%5B%5D=1&color=red&size=large¶ms%5B%5D=2"; HTTP/2 200 content-type: text/html; charset=UTF-8 date: Sat, 05 Dec 2020 13:57:43 GMT server: Apache/2.4.27 (Amazon) PHP/5.6.35 x-powered-by: PHP/5.6.35 x-cache: Miss from cloudfront via: 1.1 c29e436c21072b427d47688aaf874625.cloudfront.net (CloudFront) x-amz-cf-pop: NRT57-C1 x-amz-cf-id: BR3HRyeTVmFlduaad1qZ1NuqGy4O6nW5gp1zDedmRUq3pcc8k8wLRA== HTTP/2 200 content-type: text/html; charset=UTF-8 date: Sat, 05 Dec 2020 13:57:44 GMT server: Apache/2.4.27 (Amazon) PHP/5.6.35 x-powered-by: PHP/5.6.35 x-cache: Miss from cloudfront via: 1.1 25caeecf79d1babf9c1aeb8ae41d4e36.cloudfront.net (CloudFront) x-amz-cf-pop: NRT57-C1 x-amz-cf-id: xLjaYj2ZjxFQVp6RgQSmGOjBH1DhwUFFUsJgw_ReJJ4e49rkAHgVZg==
params%5B%5D
のみをWhitelistに指定した場合で同じキャッシュが使われた理由ですが、他にリクエストとして含んでいるクエリ文字列についてはオリジンに転送するよう設定していません。CloudFrontがクエリ文字列のキャッシュ基準とならない部分を省いて判断しているのでは、と考えています。
つまり、以下2つについてparams%5B%5D
のみをWhitelistに指定しているので、
?params%5B%5D=1¶ms%5B%5D=2&color=red&size=large
?params%5B%5D=1&color=red&size=large¶ms%5B%5D=2
キャッシュ基準では以下のように扱われており、結果キャッシュヒットとなるのかなと考えています。
?params%5B%5D=1¶ms%5B%5D=2
?params%5B%5D=1¶ms%5B%5D=2
まとめ
Amazon CloudFrontでクエリ文字列パラメータに基づいてコンテンツをキャッシュする際の細かなパターンについて確認してみました。パラメータの値が空欄でも空欄として扱われる(パラメータがないことにはならない)し、配列要素が出現したり、複数回出現してもクエリ文字列の通りに扱われています。基本的にはURLに付帯するクエリ文字列の通りに扱われている、と考えておけば大丈夫そうですね!