HTTP 308は恒久移転でもrequest methodを変えたくないURLへ使う
公開日: 執筆:佐藤
HTTP 308は、target resourceが恒久的に新しいURIへ移ったことを示すredirect statusです。301と似ていますが、308ではuser agentがrequest methodをPOSTからGETへ変えてはいけません。form送信やAPIのように、同じmethodとrequest bodyを新しいURLへ渡す必要がある場合に意味を持ちます。通常のpage移転で308を選ぶ前に、移すURLが何を受け、移転先で何を処理するかを確認します。
RFC 7538は、301、302、307の組合せに不足していた、恒久的でmethodを変えないredirectとして308を定めています。308 responseは新しいURIをLocation fieldで示せます。301との違いは、301ではPOSTをGETへ変えることが許され得るのに対し、308ではその変更を許さない点です。redirectの数字だけでなく、requestの中身がどう扱われるかを見ます。
pageを移す301と送信先を移す308を分ける
会社案内やarticle pageのURLが恒久的に替わる場合、読者は通常GET requestでpageを開きます。この場合は、旧URLごとに対応する新URLへ301で送る設計をまず考えます。URLの正本を移し、site内link、sitemap、canonicalを新URLへそろえる仕事が中心です。page移転をすることと、form送信の経路を移すことは別です。
説明用の仮例として、問い合わせformの送信先を/contact/sendから/inquiry/sendへ恒久的に替える場合を考えます。利用者がformを送ると、browserはPOST requestに入力内容を入れて旧URLへ送ります。旧URLが301を返したとき、user agentの扱いによってはPOSTがGETへ変わることがあります。移転先が入力内容を受け取る前提なら、methodが変わらないことを確認する必要があります。
ここで308を返せば、form全体が正しく引き継がれると決めるのは早すぎます。移転先がPOSTを受けるか、入力内容の検証を行うか、同じ送信が二度届いたときにどう扱うか、送信完了画面まで進めるかを別に確認します。status codeはbrowserへ移転先を伝えますが、問い合わせを保存する仕組み、mailを送る仕組み、顧客へ案内する仕事の代わりにはなりません。
APIのendpointを移す場合も同じです。旧URLへPOST、PUTなどを送るclientがあるなら、どのmethodとbodyを新URLへ送る設計かを確認します。送信元のapp、外部service、社内scriptが308を理解するか、Locationに示したURIを使うか、authorization headerなどをどう扱うかは、個別のclientによって変わります。308を返すserver側の設定だけで、すべてのclientが新URLへ移るとは決めません。
methodを保つことと二重送信を防ぐことを分ける
308はmethodをPOSTからGETへ変えないredirectです。しかし、同じPOSTが移転先へ届くことと、その処理を一度だけ行うことは別です。networkが途中で切れた、利用者が送信buttonを続けて押した、clientがretryした場合には、同じ内容が複数回届くことがあります。redirectを導入する前に、移転先で何を一件として扱うかを決めます。
仮例の問い合わせformでは、送信ごとに識別子を付ける、送信buttonを処理中に押せないようにする、server側で同じ内容を確認するなどの方法を考えます。画面上のbuttonを一度しか押せないようにするだけでは、別tabやnetwork retryまで防げません。問い合わせの受付を決める正本はserver側へ残し、redirectの有無と分けて設計します。
注文を受けるURLなら、さらに慎重に扱います。支払いを始めたこと、注文を保存したこと、入金を確認したこと、発送を始めることは別の状態です。308で新URLへ送る設定を替える前に、どの状態でredirectが起き、古いendpointに届いたrequestをどう記録するかを決めます。HTTP responseを替える作業と、注文や支払いの業務を変える作業を一度に行いません。
移転先が一時的に準備中なら、308を使いません。308は恒久的な新URIを示します。test環境へ送る、期間限定の受付URLへ送る、障害時だけ別pageへ案内する場合は、恒久移転とは別に考えます。永久に替えるかどうかを決めないまま、検索engineやbrowserが記録するredirectを設定しないようにします。
Locationと公開画面を実際に確認する
308 responseには、新しいURIを示すLocation fieldを入れられます。設定後は、browserでpageが開くかだけでなく、HTTP responseのstatusとLocationを確認します。formなら、旧URLへPOSTを送り、新URLで意図したmethodとbodyが処理されるかを検証します。APIなら、clientが返されたresponseをどう扱うかを、実際のclientで試します。
制作会社へredirect設定を頼む場合は、旧URL、新URL、使うmethod、対象のformやAPI、切り替える時刻、戻す方法を渡します。「URLを301にしてください」や「308へ替えてください」とだけ頼むと、pageの移転なのか送信先の移転なのかが分かりません。web server、application、CDNなど、どこでredirectを返すかも確認します。
site内linkと外部へ渡したURLも分けます。問い合わせformのactionを新URLへ更新できるなら、公開後も旧URLを経由し続ける理由は薄くなります。APIのclientを自分で管理できるなら、新URIへ更新する計画を作ります。旧URLの308は、移行期間に取りこぼさないための手段であって、URL管理を永遠に放置する理由ではありません。
確認する人も分けます。制作側はHTTP status、Location、applicationの処理を確認します。事業者側は問い合わせや注文が正しく受けられるかを確認します。domainやhosting serviceの管理者は、redirect設定を替えられるaccountと戻し方を確認します。codeを納品してもらうことと、送信内容や受注dataを所有し続けることは別です。
最初の一手は、旧URLへ届くrequestがGETかPOSTか、それ以外のmethodかを書き出すことです。GETで読むpageを移すのか、bodyを持つ送信先を移すのかで、確認する範囲が変わります。308はURLを一律に置き換えるためでなく、恒久移転でもrequest methodを変えない必要がある場合に使います。
関連記事

