第45話で、イトは三つの赤lampを同じ修理から切り離した。
NXDOMAINとSERVFAILには、異なるDNS responseがあった。
timeoutには、時間内に観測できたresponseがなかった。
今度のrequestはDNSからaddressを受け取り、通信路を進んだ。
戻ってきた封筒の表には、DNSのRCODEではない数字がある。
404 Not Found
festival projectorは暗いままだ。
イトは、さっき直したDNS cardを引き戻した。
「またpageがない。addressを前のserverへ戻せば開くかも」
DNS rollback leverへ指を掛ける。
本番用program boardが開くまで、あと三分。
404は、HTTPの返事
ピコは404封筒の裏を照らした。
そこには、requestとresponseの組が残っている。
イト
pageが開かないなら、DNS errorと同じじゃないの?
ピコ
DNSでaddressを得られなかった失敗とは違うよ。今回は、送ったHTTP requestに404というHTTP responseが返っている
イト
404なら、origin serverのfileが消えた証拠?
ピコ
そこまでは決められない。まず、何をrequestし、responseをどこで観測したかを残そう
この話も、外のInternetへ出ないfestival.exampleの閉じた学習fixtureで進める。
route gateway、application、move manifest、cacheは、lesson用に状態を固定している。
public siteの障害を再現したものではない。
404が示すこと、示さないこと
RFC 9110では、404 Not Foundは、origin serverがtarget resourceのcurrent representationを見つけなかったか、その存在を開示したくないことを示す。
だから、404は「物理fileが一枚消えた」という意味に限定されない。
application routeに該当がない場合もある。
requested resourceを見せない設計で、404を返す場合もある。
そして、404だけでは、その状態が一時的か恒久的かは分からない。
origin serverが恒久的に存在しないと知っている場合は、410 Goneがpreferredだと同じ仕様は整理している。
ただし、このepisodeでは410の運用設計までは扱わない。
もう一つ、404を受け取ったからといって、必ずorigin application自身がそのresponseを作ったとは限らない。
HTTPの途中には、CDN、reverse proxy、gatewayなどが入り得る。
404はHTTP responseが戻った証拠ではある。
どのcomponentが生成したかは、trace、header、log、fixtureの接続図など、別の証拠で確かめる。
正確なrequest targetを残す
イトは404封筒から、request cardを取り出した。
method: GET
authority / Host:festival.example
path:/program/finale
query: none
response status: 404
observed source: fixture route gateway
RFC 3986は、URIのgeneric syntaxをscheme、authority、path、query、fragmentに分ける。
pathは、authorityの範囲内でresourceをidentifyするためのdataだ。
同じhostへ届いても、/program/finaleと/program/finale-nightは同じtargetではない。
queryがroutingや表示対象に使われるserviceなら、queryの違いも結果を変え得る。
methodも捨てない。
GETでは見つかるtargetでも、別methodを受け付けない場合がある。
その場合は404以外のstatusを返す設計もあるからだ。
「同じURLを開いたつもり」ではなく、wireへ出たrequest条件を残す。
404を消すことが、修理とは限らない
イトはroute gatewayの横に、応急処置の大きなswitchを見つけた。
every missing route → home page / 200
これを入れれば、projectorから404という数字は消える。
でも、利用者が求めたresourceが見つかったわけではない。
存在しないpathがすべてhome pageの200 OKになると、clientも運用者も「targetがない」という状態を区別しにくくなる。
見た目から404を隠すことと、requestされたresourceへ正しく案内することは別だ。
custom 404 pageを用意すること自体はできる。
検索、home、主要categoryなどの戻り道をresponse bodyへ置けば、利用者は次へ進みやすい。
その場合も、本当にtargetが見つからないなら404 statusを保つ。
イトの前に、三つの選択肢が上がる
program boardの開場まで、あと二分。
DNS rollback leverは、まだイトの指の下にある。
404を返したold pathは、poster、menu、外部配布済みQRの三か所から参照されている。
A DNS addressを、昨日のserverへ戻す
今回のfixtureではDNS answerを得たあと、HTTP 404 responseまで戻っている。
request targetやroute ownershipを見ずにaddressを戻せば、正常な別programまで古いserverへ向ける。
B すべての404を、home pageの200へ変える
赤いstatusは消える。
しかし、移転したresourceと、本当に存在しないresourceの違いまで消える。
間違ったlinkも見つけにくくなる。
C DNSを封印し、old / new targetとmove evidenceを照合する
exact old requestと404 responseを残す。
route tableで候補のnew targetを探し、同じmethodでresponseを確認する。
move manifestで、同じresourceが恒久的に移ったのかを確かめる。
equivalent moveが確認できた一件だけにpermanent redirectを設定し、管理できるold linkも直す。
unrelated missing pathは404のままにする。
ピコはDNS leverにも、home-200 switchにも触れなかった。
「404を消す方法ではなく、requestの行き先を直す方法を選んで」
イトはCを選んだ。
DNS rollback leverから手を離し、自分で透明coverを下ろした。
404封筒、exact old request、route table、move manifestを同じ検証台へ置く。
old pathとnew pathは、同じresourceか
route tableには、似たpathが三つあった。
/program/finale-night/program/finalists/program/finale-photo
文字が似ているだけでは、redirect先にできない。
イトは一つずつGETし、statusとrepresentationの識別cardを比べた。
/program/finale-nightだけが200を返し、今日のfinale programを持っている。
move manifestにも、旧/program/finaleから新/program/finale-nightへのpermanent moveが、一件だけ記録されていた。
他の二つは別resourceだ。
イトは、old routeとnew routeの間にだけgold redirect bridgeを掛ける。
DNS cardはblue caseの中に残す。

301から200へ、二つのresponseを確認する
今回のfixtureはGET pageのpermanent moveだ。
イトはold routeへ301 Moved Permanentlyを設定し、Locationへnew URI referenceを入れた。
RFC 9110の301は、target resourceへ新しいpermanent URIが割り当てられ、future referenceはnew URIを使うべきだと示す。
実際の設計ではmethodの扱いなども見て301 / 308等を選ぶ必要がある。
ここでは閉じたGET fixtureへ限定する。
イトはautomatic followだけを見ず、二段を別々に記録した。
first request: GET
/program/finale
first response: 301
Location:/program/finale-night
second request: GET
/program/finale-night
second response: 200
festival projectorに、goldのfinale programが開く。
posterとmenuのold internal linkも、イトがnew pathへ更新した。
外部配布済みQRは回収できなくても、301 bridgeを通ってnew targetへ着く。
DNS addressは一度も変更していない。
一つの404を、正直に残す
イトは、存在しない/program/moon-stageもtestした。
move manifestに対応するresourceはない。
近い名前のpageへ勝手に飛ばす根拠もない。
このrequestには404を保つ。
response bodyへhome、program一覧、検索へのrouteを置き、迷った利用者が戻れるようにする。
statusは200へ偽装しない。
404は、すべて消すべき赤lampではない。
移転先が確認できないtargetについて、見つからない状態を正しく伝えるresponseでもある。
なお、RFC 9111が説明するように、cacheは200だけでなく404のようなnegative resultを保存することもある。
404は条件によりheuristicに再利用され得るため、修理後の確認ではresponse header、Age、cache経路も観察する。
詳しいcacheの層は、次のepisodeで扱う。
statusを消す前に、targetと根拠を残す
program boardが開いた。
検証台には、三つのものが残っている。
透明coverの下には、変更しなかったDNS address card。
中央には、old 404からnew 200へ伸びる一本だけの301 bridge。
右には、戻り道を持ちながら404 statusを保つtrue missing route。
HTTP 404 responseがあるなら、まずexact request targetとresponse sourceを残す。
同じresourceの移転を確認できたときだけ、その一件をnew URIへ案内する。根拠がなければ、DNSや全routeをまとめて変えない。
「Not Foundは、repair commandじゃない」
イトは404封筒を、DNS trayではなくHTTP response shelfへ戻した。
そのとき、隣のviewerがまだ赤い404 pageを映していることに気づいた。
verification clientでは、301から200へ進んでいる。
同じold URLなのに、片方だけ古いresponseが残っている。
次回:直したのに、古い404が出る
viewerの後ろで、半透明のcache shelfが光った。
中には、修理前の404封筒が一通残っている。
「routeは直ったのに、どうして昔の返事をもう一度使うの?」
イトは、new responseを上から重ねず、古い封筒の時刻を見た。
次回、ピコルート第47話。
イトは、古いcacheを上書きだけで消さなかった|どこに前の材料が残る?

