HTTPではファイルを取得する際に、ファイルの特定範囲のみを要求するRangeリクエストを行うことができます。
ファイルをアップロードする際にContent-Rangeヘッダ(MDN)を使用してもよいのでしょうか?ファイルを分割してそのRangeごとに少しずつ送れば、途中でネットワーク断があってもそこからやり直せるので便利そうです。
例えば、次のようなPUTリクエストは正しいのでしょうか?
PUT UPLOAD_URL HTTP/1.1 Content-Length: 524888 Content-Type: video/* Content-Range: bytes 0-524287/2000000 {bytes 0-524287}
仕様の観点で、紐解いていこうかと思います。
RFC7231
HTTP/1.1のセマンティクスを定義するRFC7231では、PUTリクエストについて下記の通り書いています (URL)
Content-Rangeヘッダーフィールドを含むPUTリクエストに対して400(Bad Request)レスポンスを送信する必要があります
つまり、仕様上は利用が許可されていません。
利用例
しかし、IETF HTTP WG のメーリングリスト(URL)では、下記のようなサービスで、Content-RangeヘッダーのついたPUTリクエストがサポートされていることが報告されています。
- Amazon S3 Glacier
- Google Drive
- Google Cloud Storage
Youtubeでも「再開可能アップロード」としてこの方法を利用しています。
developers.google.com
これをうけ、HTTPの仕様改定にともないこのPUTリクエストについて仕様上どう扱うか議論になりました。
この、HTTPセマンティクスの改訂版仕様について触れていきます。
HTTPセマンティクス仕様の改訂版
HTTP/1.1とセマンティクスの仕様であるRFC7230 〜 RFC7235は、現在改定作業中です。
これは、HTTP/1.1のフォーマット仕様と、HTTPセマンティクスを分離するための作業です。これによってHTTP/2(http2bis)やHTTP/3(draft-ietf-quic-http)の仕様からセマンティクスのみ参照することができます。また、その他にも細かい仕様バグが修正されています。まだ、RFCとはなっていませんが、下記から参照することができます。
先日、この新しいHTTPセマンティクス仕様で、Content-Rangeヘッダのついた PUTリクエストの制限を緩和する変更が入りました。
github.com
新しい仕様では下記の通り書かれています (意訳) (URL)
一部のサーバはContent-RangeヘッダがつくPUTリクエストをサポートしていますが、サポートには一貫性がありません。
このように既存実装の存在を配慮しつつ、利用を緩和しています。
サーバがContent-Rangeヘッダの通り解釈できず、まるごと上書きしてしまう可能もあるため、事前にサーバが対応していることを知っている時のみに使用するのが良さそうです。
おまけ
部分的アップロードに関しては、じつは別の仕様があったりしました。書かれている通りPATCHメソッドを使うことが想定されています。
asnokaze.hatenablog.com