理系学生日記

おまえはいつまで学生気分なのか

忍者TOOLS

ありがとうLDR

Live Dwango Reader が、2017/8/31 に、ついにサービス終了するそうです。

いつか来るとは思っていましたが、ついにこの日が来たのだと、そういう感覚でした。すごく残念です。本当に残念です。

大学生の頃からの情報収集手段だった

ぼくの情報収集手段の最たるものは、いつも LDR でした。これは、大学のときからずっとだと思います。 OPML から雑に数えると、LDR に登録していたフィードの数は 1,400 くらいでした。

$ grep -i '<outline ' export.xml | grep xmlUrl | wc -l
1391

ぼくにとって、このフィードを一番効率的に捌けたのは常に LDR でした。 vi と同じようなキーバインドで流れるようにフィードを消化していけたし、「Pin を立てる」という概念で、気になったフィードの抽出と、そのフィードの消化(読みこみ)のフェーズを分ける運用も簡単でした。

API が公開 (仕様が公開されていたというよりは、LDR で使用されている JavaScript を読み解くことで、API をどう使えば良いかが分かった) ので、容易にツールを作ることもできました。

最初はブラウザベースで使用していましたが、スマートフォンアプリも発達し、他アプリとの連携も簡単にできるようになりました。 今は、ブラウザベースからスマートフォンのアプリ経由になりましたが、それでも LDR を使用し続けています。

Taskchute の記録を見る限り、今でも 1 日 24 分ほど、LDR に費していました。 タイトルレベルであれば、今でも軽く千を超えるエントリを 1 日で目を通しています。これも LDR という優れた RSS リーダがあったからだと思います。 他の RSS リーダを使っていたとすると、もしかすると情報収集の手段として RSS を選択していなかったかもしれません。

LDR の操作性は、それほどまでに一線を画していたように思います。

RSS の未来

2013 年に Google Reader がサービス停止し、そして今回の LDR のサービス停止と、RSS という技術にとっては冬の時代を迎えているのかもしれません(もちろん、Podcast なんかはまだまだ続くと思いますが)。

それでも、ぼくは Pull 型の情報収集手段、自分の興味ある分野を aggregate してくれる技術としては、これからも RSS にしがみつきます。 今のところはまだ、RSS が最良の手段だと思っていますし、依存し続けると思います。

本気で LDR から移行を考えなければならないのは悲しいですが、Feedly、Aol Reader など、使用性を試していきたいと思います。 あそこまで優れたサービスを無償で提供しつづけてくれた Livedoor、そのサービスを引き受けてくれた Dwango、10 年以上、本当にありがとうございました。

シェルスクリプトにおける [ と [[

シェルスクリプトで条件分岐を書くとき、[ を使ったり [[ を使ったりすることになると思います。

POSIX の test にも記載がありあすが、[test と同じ機能を持つことになっており、同じ実装であることも多いです (ただし、[ として実行されるか、test として実行されるかに依って挙動が変わり得る)。

一方で、[[ は POSIX で定義はされていない、Bash 等の高機能シェルでの拡張になります。

[[[ は、当然ながら同じような機能を持っています。そりゃ、後者は前者の拡張ですからね。一方で、「拡張」であるが故に、[[[ で異なる挙動も存在します。

演算子

たとえば比較の演算としては以下のような挙動のちがいがあったりします。なお、[ への有無については、POSIX 定義という観点であって、シェル実装によっては普通に使えるものもあります。

機能 [ [[ 備考
文字列の大小比較 a \> b a > b [ の場合、リダイレクトと誤解されないようにエスケープが必要です
AND 条件 s1 -a s2 s1 && s2 実際のところ、-a は POSIX で 時代遅れであり、POSIX 標準に準拠する場合は使わないようが良いよ とされてます
OR 条件 s1 -o s2 s1 || s2 同上
パターンマッチ なし $a = a*
正規表現マッチ なし $a =~ ^hoge
ファイルの新旧チェック なし $file1 -nt $file2

このあたりの差異の背景には、POSIX にも記載があります。

Some additional primaries newly invented or from the KornShell appeared in an early proposal as part of the conditional command ([[]]): s1 > s2, s1 < s2, str = pattern, str != pattern, f1 -nt f2, f1 -ot f2, and f1 -ef f2. They were not carried forward into the test utility when the conditional command was removed from the shell because they have not been included in the test utility built into historical implementations of the sh utility.

test

その他の挙動

  • [[ では変数をクオテーションで囲まなくて良い
$ var=''
$ [ $var = '' ] # [ = '' ] と展開されてしまうので NG。クオテーションが必要。
sh: [: =: unary operator expected
$ [[ $var = '' ]
$ file="file name"
$ [ -f $file ]    # スペースを含んでいるので、クオテーションで囲まないと失敗する
sh: [: file: binary operator expected
$ [[ -f $file ]]  # 成功する
  • [[ の場合、( 等をエスケープする必要がありません。
$ [ -f "$file1" -a \( -d "$dir1" -o -d "$dir2" \) ] # グルーピング用の括弧もエスケープの必要有
$ [[ -f $file1 && ( -d $dir1 || -d $dir2 ) ]]

※先述の通り、-a-o は POSIX としては、obsolete とされています。

  • [[ の場合、文字列の大小比較でエスケープする必要がない
$ [ a < b ] # シェルにリダイレクトと解釈される
sh: b: No such file or directory
$ [[ a < b ]]


$ [ a > b ] # こちらはエラーすら出ないで、「正常に」ファイルが作成されてしまう。
$ ls b
b

ポータビリティ

状況にも依りますが、ぼく自身はそこまでポータビリティを重視してシェルスクリプトを書かないといけないとは思っていません。 環境がかわったら、シェルスクリプトから呼びだされるコマンドの挙動もちがうでしょうし、そのまま別環境へ移植というのはまぁ無いだろうと思っています。 それに、ポータビリティを重視するにしても、シェルの個別拡張を使用せずに POSIX だけで書こうというのはすごく難しいですし。。。

そういう考え方なので、[[ の方を使うかな。

参考文献

Fire TV Stick のある生活

このあいだ開催されていた Amazon の PrimeDay で Amazon Fire TV Stick を購入しました。

Fire TV Stick (New モデル)

Fire TV Stick (New モデル)

もともとこの手の機器として、Chromecast を持っていました。 Chromecast 自体に不満はなかったのですが、部屋の TV に接続するようになったので、リビングの TV 用のものが欲しくなり、ちょうど PrimeDay でかなり安くなっていたので購入した次第です。

ところがこれ、マジで購入して良かった。ライフチェンジングなかんじでした。 基本的に非常に満足していて、この買って良かった感は、録画機器の無い時代に購入した torne 以来です。

ChromeCast との違い

Chromecast というのは基本的に、スタンドアローンで動作しません。 Chromecast というその名称が冠するとおり、モバイル端末その他の端末から、映像や音声を Cast (投影) することでテレビにその内容を映し出します。

一方で、Kindle Fire TV は単独で動きます。 モバイル端末の助けなしに、HDMI 端子に差し込むだけで、アプリケーションのダウンロード、PrimeVideo や AbemaTV のテレビへの投影を行ってくれます。

「モバイルの小さい画面での操作から解放されたこと」、これが Kindle Fire TV で大きく改善されたことになります。

音声検索の精度が思いの他良い

Fire TV Stick は、スタンドアローンで動作するが故にリモコンが同梱されていて、そのリモコンには音声検索機能が搭載されています。 さすがは Alexa の Amazon と言うべきか、この音声検索がすこぶる正確です。

リモコンでキーボードを操作するのはさすがに至難なのですが、音声検索が優秀すぎるが故に、そういったストレスを感じることがありません。テクノロジー、確実に進化している…。われわれにキーボードなんてインタフェースはいらんかったんや!! (なお、無線 LAN のパスワード入力ではキーボード不可避)

f:id:kiririmode:20170722163030j:plain

チャネル

あんまり考えなしに衝動で買ってしまったので、Hulu とか Netflix、 Amazon Prime Video くらいしか見れないんだろうなと思っていたんですが、良い意味で裏切られました。 ネイティブなアプリがダウンロード可能で、それをインストールすることで動画に限らずチャネルを増やすことができます。

残念ながら日本のチャネルは多くないんですが、Netflix、hulu あたりはもちろんありますし、DAZN もあります。 ぼくにとって嬉しかったのは、

とかがあることですね。 とくにdアニメストアは、なぜか絶対無いよなと思い込んでいたので、良い意味で裏切られました。

要望

あとは、PC からの直投影もサポートしてくれると嬉しいんですよね…(Chromecast はこれができる)

CDIにおけるProducerメソッド

JavaEE 良くわかっていないのですが、それでもプロジェクトが JavaEE 標準だーウオーという状況っぽいので、ちょっと勉強をしはじめております。 ぼくが Java に対して得意意識を持てないのは、こういうところの知識がないのもあるので、そのへんを払拭していこうとがんばらなければ。

今日ははじめて、@Produces というアノテーションを知りました。

@Produces

DI というと、今までずっと「コンテナがオブジェクトを注入する際、どのクラスのオブジェクトを注入するのかはコンテナが決定する」と思ってたんですよね。 開発者は、コンテナに対して型情報といわゆる限定子(非推奨みたいだけど @Named とか、@Qualifier を使って作成したものとか)を教えることで、何を注入してほしいのかを伝えるものだと。

じつはそのあたりには別解があって、コンテナではなく、開発者自身がオブジェクトを生成し、それを注入するようにできる方法があります。 それが Producer メソッドと呼ばれるメソッドをつくる方法で、Producer メソッドの作り方というのが、@Produces アノテーションをメソッドに付与することだと。

Producer メソッドを作ると、DI コンテナが注入対象のフィールドだったり引数だったりを見つけると、その注入対象の型を返却してくれる Producer メソッドを呼んでくれるようになります。

このため、Producer メソッドで注入すべきオブジェクトを生成して、それを返却してやるだけで、動的に注入するオブジェクトのクラスを切り替えたりもできるようになると。なるほど便利だ。

このように、Producer メソッドでは、実行時に注入する型を変える他にも

  • Bean ではないようなオブジェクトを注入する
  • 注入するオブジェクトに対して、コンストラクタでの初期化以外のカスタマイズを実行する

といった特徴を持たせることができます。 百聞は一見にしかずなのですが、Weld 2.4.3.Final - CDI Reference Implementation に Producer メソッドで、プリミティブとしての int を生成し注入するための Producer メソッドの実装例がありました。

import javax.enterprise.inject.Produces;


@ApplicationScoped
public class RandomNumberGenerator {


   private java.util.Random random = new java.util.Random(System.currentTimeMillis());

   @Produces @Named @Random int getRandomNumber() {
      return random.nextInt(100);
   }
}

こちらは、Strategy パターンの型を、動的に切り替える例

import javax.enterprise.inject.Produces;

@SessionScoped
public class Preferences implements Serializable {

   private PaymentStrategyType paymentStrategy;

   ...

   @Produces @Preferred
   public PaymentStrategy getPaymentStrategy() {

       switch (paymentStrategy) {
           case CREDIT_CARD: return new CreditCardPaymentStrategy();
           case CHECK: return new CheckPaymentStrategy();
           case PAYPAL: return new PayPalPaymentStrategy();
           default: return null;
       }
   }
}

たいへんに、なるほど〜〜〜感あります。

ただ、これを多用すると、DI における依存性解決がコードから読み取りにくくなるので、まぁ用法用量を守ってお使いくださいという感じなんでしょう。

Fallout 4

PS4 を買ってから BIO HAZARD 7人喰いの大鷲トリコ | プレイステーション® オフィシャルサイト とやってきて、次が Fallout 4 Game | PS4 - PlayStation だったんですが、これをようやくクリアしました。 ちなみにですが、いまは ゼルダの伝説 ブレス オブ ザ ワイルド | Nintendo をやっていて、あと何十時間かかるのかしりませんが、その後で NieR:Automata | SQUARE ENIX をやる予定です。

Bethesda.net が出しているソフトとして、先に wikipedia:The Elder Scrolls シリーズの The Elder Scrolls V: Skyrim Special Edition Game | PS4 - PlayStation をやっていて、 はじめてオープンワールドのゲームとはどういうものかを実感しました。広大かつ隅々まで書き込まれた世界感と、それを支える堆く積み重なったストーリー背景は、時間泥棒と言われるに相応しいものでした。

ファンタジー的な世界感のオープンワールドゲームである The Elder Scrolls シリーズに対し、wikipedia:Fallout シリーズはよりぼくたちの住む現実に近い世界を描いたオープンワールドのゲームになっています。 2077 年に勃発したアメリカ、ソ連、中国等の核保有国による核戦争により文明が崩壊した後の世界が舞台。主人公は核シェルターで冷凍保存されていた最中に、シェルター内で妻が殺され、息子が誘拐され、その息子を追って核戦争集結後の世界に出るというのがメインストーリーになっています。

メインストーリーはあるんですが bethesda のオープンワールドはサイドストーリーがたいへんに充実しています。 ストーリーに大きく関わる 4 つの組織が、それぞれの正義を持って互いに対立・衝突することになるのですが、主人公がどの組織に所属するかによってもストーリーは異なっていて、 どの組織に所属したとしてもそれぞれの想いとジレンマを感じることができるのは、この現実社会と変わりません。

もちろん、それら組織に所属しないでも十分に楽しむことができて、最近は押井守監督がたいへんなプレイスタイルを発表してくださっています。

クリアしたと書きましたけど、まだ組織のうちの 1 つミニッツメンのストーリーをクリアしただけなのですが、もう 100 時間くらいやっているかんじです。 次はゼルダを進行させる予定です。

宇宙の眼

積ん読していたフィリップ・K・ディックの「宇宙の眼」をようやく完読しました。

フィリップ・K・ディックを知らない人はいると思いますが、「アンドロイドは電気羊の夢を見るか?」とかは有名だと思うし、映画化されたものを見ても

  • ブレードランナー
  • トータル・リコール
  • マイノリティー・リポート

など、有名なヤツが多い。あと、上記 3 作品だけ見ても、だいたいの作品イメージが掴めると思います。時代こそ違いますが、サイバーパンク的な SF 作品が多い印象。 「宇宙の眼」自体も、作品としては 1957 年のものではあるんですが、今読んでも古さはまったく感じませんでした。

宇宙の眼 ハヤカワ文庫SF

宇宙の眼 ハヤカワ文庫SF

作品は、ベバトロン(陽子ビーム加速器)を見学していた 8 人が、装置の事故により加速器に落ちてしまうところからはじまります。 8 人は怪我を負いながらも通常の生活に復帰するわけですけど、その復帰した現実が、事故前の現実とは異なる文化・宗教感の現実ものになっていて、8 人が対立しつつ、ときに協力しつつ、なぜ狂気のような現実に変わってしまったのかを探り元の現実に戻ろうとするのが大筋で、パラレルワールドの走りなのかと思います。

個人が主観だけでつくる現実は、どんなに破綻していようと、また破綻させようと、不思議な既視感があり、ぼく自分も頭の中でそういう破綻した現実を勝手に作っているんじゃないかと思います。 それが表面に出てきて実際にそこに実在する人間が所属してしまうと、気づかなかった破綻面が見えてきて、wikipedia:宇宙検閲官仮説 をちょっと想起させました。

ひさしぶりに「小説」を読みましたが、やっぱり娯楽としてすごく質が良いなと思います。技術書とかを読むのとはまた違う達成感があって良い。

AWS ソリューションアーキテクトの勉強をはじめる

本格的に AWS の勉強を始めようかということを思っています。 同期が昔に言っていて影響を受けたのは、"体系的に学ぶときは資格試験対策をするのが一番早い"ということもあって、最初のターゲットをソリューションアーキテクトに合わせて勉強を進めています。

AWS 認定

ソリューションアーキテクトに代表される AWS 認定については、アソシエイトレベルとプロフェッショナルレベルがあります。

プロフェッショナルレベルの前にはアソシエイトレベルの取得が必須ということで、まずはターゲットとしてアソシエイトレベルを設定しました。 試験ガイドを見るに、

  1. AWS の知識
  2. IT 全般の知識

が必要ということでした.ネットの海を暫く彷徨ってみたところ、アソシエイトレベルに関しては大量の情報がありましたので、比較的に裾野の広い資格なんだろうと思います。 とはいえ、落ちたという話も散見されるので、ナメてかからないようにしないと…。

勉強法

まだ受けてもいないのでこれからという感じです。 ただ、以下のスライドや、その他の Blog、Qiita 記事を確認すると、だいたい以下の資料を読むのがベストなかんじがしました。

あとは、以下のような試験対策本も出てるみたいですが、1 年前の出版というところがどうだろうか…。

参考文献

cocoaアプリでEmacsキーバインドを使いたい

Chrome の入力フィールドでもカジュアルに(※)Emacs のキーバインドを使いたいと思うことがあります。 Mac の場合、Emacs のキーバインドがデフォルトである程度実現されているわけですが、Ctrl-y で yank (ペースト) するとかは実現できていません。

それを実現する手段というのがあったのでご紹介します。 ご紹介しますと言いながら、以下のエントリ以上に詳しくかける気がしない。

全部読めない忙しい貴兄に対して要約しますと、しなければならないことは以下の 2 つだけです。

  1. ~/Library/KeyBindings/DefaultKeyBinding.dict を作成する
    • ~/Library/KeyBindings/ がなければディレクトリを作りましょう
  2. DefaultKeyBinding.dict に、キーと NSResponder クラスのメソッドとのバインディングを定義する

これにより Emacs の基本的なキーバインドが実現できるわけですが、Emacs のキーバインドを 1 から実現しようとすると、結構つらい。かなりつらい。 このあたりは Github に転がっているので、いくつかご紹介します。

これらを参考にすると、だいたい Emacs っぽいキーバインドになります。 Ctrl-Space (setMark:) とか効かないのは原因がよくわかりません。おしえてください。

ちなみに

Chrome において、テキスト入力の部分を Emacs のキーバインドではなく直接 Emacs で編集したい場合は、Edit with Emacs あたりを使えば良いと思います。 このエントリも、Edit with Emacs で書いてます。

Varyヘッダとキャッシュについて

さっき Cache-Control ヘッダの話を書いたんですが、もちろんキャッシュ制御に関しては Cache-Control ヘッダだけで収まる話ではなく、他にも多々のヘッダが影響を与えます。 その一つに、Vary ヘッダがあるので、今日はその話でも。

Vary ヘッダ

Vary ヘッダは、RFC7231 で定義されているヘッダです。 vary というと「変わる」という意味を持つ動詞ですが、Vary ヘッダはその名の通り、「どのヘッダによってコンテンツが変わったのか」を示すレスポンスヘッダです。

例えば、よくあるタイプのスマートフォン対応の 1 つとして、User-Agent ヘッダを見て、PC 用 HTML を返却するか、スマフォ用 HTML を返却するかを切り替える実装を良く見ます。 この場合、レスポンスヘッダに Vary: User-Agent ヘッダを付けるのが常套手段です。ちなみにこれ、Google も SEO として推奨してるからな。B2C 系システムつくるときは気をつけろよ(戒め)。

他にも、リクエストヘッダの Accept-Encoding を見てページの言語を切り替えるような場合は、Vary: Accept-Encoding を付けることになります。だいたいイメージ湧いたでしょうか。

Vary ヘッダとキャッシュ

Vary ヘッダとキャッシュの関係性は、上で書いた内容と強く関連します。

キャッシュというのは通常、リクエストメソッドとターゲット URI をキーとしてレスポンスを保存します。 しかし、例えば User-Agent リクエストヘッダで HTML を出し分けるようなシステムの場合、メソッドと URI だけでなく、User-Agent ヘッダの値もキャッシュのキーにしなければ、クライアントに依っては正しいキャッシュを手に入れられなくなるケースがあります。 つまり、Vary レスポンスヘッダは、「キャッシュに対してキャッシュキーの追加を指示する」という意味があります。

Vary ヘッダがなかったらどうなるかというと、わりと悲惨でして。 いや、User-Agent くらいだったら良いんですよ、PC でスマフォサイトが見れたりしちゃうけど。 これがもし、Accept-Encoding とかで起こっちゃうと、こんなかんじになって、レンダリングすらされなくなっちゃいます。

  1. クライアント A から Accept-Encoding: gzip つきのリクエストが送信され、サーバは gzip 圧縮されたコンテンツを返す。これがキャッシュサーバにキャッシュされる。
  2. gzip を理解しないクライアント B が同じ URL にリクエストを発行する (Accept-Encoding ヘッダは含まれていない) と、キャッシュサーバが gzip 圧縮されたキャッシュを返す

このあたりについては、Fastry がベストプラクティスの記事を書いてくれているので、参考にすると良いと思いました。

参考文献

セキュリティ対策としての Cache-Conrol ヘッダについて

今日はブラウザのキャッシュ制御の話。キャッシュについては主に性能面で語られて、情報漏洩に繋がる重要な制御であることは見逃されがちです。

情報漏洩自体はよくないことで、被害にあってしまった人はそんなこと言ってられないけれど、その原因を包みかくさず公開することで他山の石というか、間違いなく日本のセキュリティ意識は向上すると思います。 ぼく自身も、みなさんも、そろそろ Cache-Control: no-cache, no-store, must-revalidate しとけば良いんやろ、というゴミのような意識を改善しなければならないということで、ここにキャッシュについてまとめてみます。

Cache の種類

ブラウザで関連するキャッシュには主に 2 つほどあります。

  1. private cache
  2. shared cache

ともに名前が示す通りですが、前者が 1 ユーザのためのキャッシュでブラウザが保持するキャッシュと思ってもらえればだいたいイメージがわくはず。 後者は忘れられがちですが、複数ユーザが共有するキャッシュで、プロキシサーバとかに保存されたり、CDN や 場合によっては LB に保存されたりして、複数ユーザに共有されます。

Cache-Control ヘッダ

HTTP 1.1 においては、このキャッシュ制御は Cache-Control ヘッダによって行われます。 Cache-Control ヘッダは、HTTP リクエストにも HTTP レスポンスにも付与可能ですが、今日のエントリはサーバ側を主軸としているので、レスポンスに付与するケースに限定して議論します。

レスポンスに付与できる Cache-Control のディレクティブとしては以下のようなものがありますが、今日は 1〜5 までをまとめてみます。

  1. no-store
  2. no-cache
  3. must-revalidate
  4. public
  5. private
  6. max-age
  7. s-maxage
  8. no-transform
  9. proxy-revalidate

no-store

もっとも直感的に分かりやすいディレクティブで、private cache に対しても shared cache に対しても、「キャッシュするな(MUST NOT)」という指示になります。

余談ですが、メルカリのエンジニアブログによると、メルカリの使っていた CDN は、このディレクティブが使われている場合であってもキャッシュをするような振舞いに見えます。no-store 過信できんということか。

キャッシュをしないのは

Cache-Control: private

が含まれている場合のみ CDN切り替え作業における、Web版メルカリの個人情報流出の原因につきまして - Mercari Engineering Blog

no-cache

メルカリが使用していたという no-cache ですが、これを"キャッシュさせない"という制御に使うのは悪手だったのかなと思っています。 ディレクティブがクソ分かりづらいですが、これは「キャッシュするな」ではなく、キャッシュしても良いけどそれを使うときはちゃんと “検証” してね、というものだからです。

IPA から引用します。

一見「キャッシュを使うな」のように見えるこのヘッダが実際に意味するところは少々ニュアンスが異なる。このヘッダの意味は、いちどキャッシュに記録されたコンテンツは、現在でも有効か否かを本来のWebサーバに問い合わせて確認がとれない限り再利用してはならない、という意味である。 IPA ISEC セキュア・プログラミング講座:Webアプリケーション編 第5章 暴露対策:プロキシキャッシュ対策

ここでの “検証” (Validation) っていうのは、RFC7232 の Conditional Requests ってヤツです。もうちょっというと If-Modified-Since とか ETag ヘッダとかが馴染み深いと思います。 no-cache ディレクティブは、これらのヘッダを使って、サーバ側に「自分が持っているキャッシュが最新か否か」を問い合わせることを強制するってことですね。

must-revalidate

must-revalidateno-cache とよく混同されますし、事実、かなり分かりづらいです。ぼく自身もこの違いってよく分かっていません。 古くなったキャッシュは origin server に検証することなく使ってはならない、というディレクティブだと解釈しているんですが、合ってるかな。

Cache-Controlヘッダは仕様通り実装されていない?(2) - Qiita

の記事の検証結果を見る限り、合ってると思うんだけどな。

以下の記事も面白いので、興味がある方はご覧ください。

public

public はわりと危険なヘッダです。 「キャッシュしても良いよ」という意味ではあるのですが、このディレクティブを付与すると、通常はキャッシュされない Authorization ヘッダ付きのレスポンスだってキャッシュしちゃいます。 (このあたりは、must-revalidate とか、s-maxage とかも関係するけど、詳細は RFC7234 を見てくれ)

private

メルカリのエンジニアブログに記載のある CDN は、このディレクティブがあるときだけキャッシュしないという仕様なようですが、 private ディレクティブは「shared cache にはキャッシュするな」を示すものです。

Cache-Control: private, no-store, no-cache, must-revalidate

今回のエントリ記述のモチベーションは、Cache-Control: private, no-store, no-cache, must-revalidate っていう決まり文句みたいなのはどういう意味を持っているんだろう、というとこからはじまりました (しばらくグダグダしてたら、メルカリの漏洩があって、ようやくまとめた)。 最初は、「それぞれのディレクティブが別のことを指定しており、総体としてセキュアな指定になっている」と思っていたんですが、メルカリの使っている CDN の仕様も鑑みると 「とりあえずキャッシュさせたくなかったら、安全ぽいヤツいろいろ指定してみよ」みたいな形で指定するものだと理解するようになりました。

参考文献