コンテンツへスキップ
HexaTransfer
ブログへ戻る
技術詳解

ファイル転送API設計:RESTfulベストプラクティス

RESTfulベストプラクティスに基づく堅牢なファイル転送APIを設計。認証、レート制限、マルチパートアップロード、エラー処理を解説。

適切に設計されたファイル転送REST APIは5〜6のリソース(セッション、パーツ、共有、ダウンロード、取消)を公開し、HTTPセマンティクスを正直に使用し(作成にPOST、べき等なチャンクにPUT、取消にDELETE)、実際のバイト移動を署名付きストレージURLにプッシュしてサーバーが帯域幅のボトルネックにならないようにする。認証はTLS 1.3上の短命ベアラートークンを使用し、レート制限は作成とメタデータ読み取りを区別し、チャンク分割アップロードはtus再開可能パターンまたはS3マルチパートセマンティクスに従い、エラーはRFC 7807 Problem Detailsに従いクライアントがプログラム的に処理できるようにする。経済産業省(METI)のセキュアプログラミングガイドラインも、APIレイヤーでの適切なエラー処理と認証実装を求めている。

ファイルでなくアクションを中心にリソースモデルを形成する

よくある間違いはAPIをファイルツリーとしてモデル化することだ。ファイル転送サービスは3つのリソースとしてよりよくモデル化される:

  • /sessions — 進行中のアップロード。POSTで作成され、チャンクのPUTで充填される
  • /shares — 有効期限とダウンロード予算を持つ完了した、アドレス可能な転送
  • /downloads — バイトをフェッチするための短命の署名付きアクセスハンドル

セッションはcompleteアクションで共有になり、共有は時間またはダウンロード予算で期限切れになる。取消は共有へのPATCHまたは取消トークン付きのDELETEだ。「ファイル」や「フォルダー」の名詞はない—それらはストレージの実装詳細であり、公開契約ではない。

認証と認可パターン

ユーザー向けAPIでは、EdDSAで署名された短命JWT(15分TTL)を発行し、セキュアなHttpOnlyクッキーでリフレッシュする。トークンはAuthorization: Bearerに入れ、ログに記録されるクエリ文字列には絶対に入れない。

マシン間では、HMAC-SHA256リクエスト署名がベアラートークンを上回る。鍵を送信せずに鍵の所有を証明するからだ。AWS SigV4が参照設計だ。

署名付きダウンロードURLのTTLは時間でなく分にする。15分のウィンドウは使いやすさと漏洩URLが転送されるリスクのバランスをとる。

チャンク分割アップロードとマルチパートセマンティクス

再開可能なチャンク分割アップロードには2つの信頼できるプロトコルがある:tus(IETF草案、Upload-OffsetUpload-Lengthヘッダー)とS3マルチパート(PartNumberUploadIdETag)。1つを選んで継続すること。独自プロトコルの発明は魅力的に見えて、部分書き込み、順序外チャンク、放棄されたセッションを処理する必要が出たときに悪くなる。

tus.ioのパターンをREST形式で:

POST   /sessions              -> 201, Location: /sessions/abc
HEAD   /sessions/abc          -> 200, Upload-Offset: 104857600
PATCH  /sessions/abc          -> 204, body = 次のチャンク
POST   /sessions/abc/complete -> 201, Location: /shares/xyz
DELETE /sessions/abc          -> 204

チャンクサイズの境界:S3マルチパートと一致する5MB最小、リトライコストを制限する100MB最大、デフォルト8MB。アドバタイズされたオフセットと一致しないチャンクは、期待されるオフセットを説明するProblemドキュメントと共にHTTP 409 Conflictで拒否する。

現実の悪用を反映したレート制限

レート制限はエンドポイントのコストで変わる必要がある:

  • POST /sessions:IPあたり時間20件(高コスト—ストレージを割り当てる)
  • PATCH /sessions/:id:セッションあたり時間10,000件(低コスト—バイトを書き込む)
  • GET /shares/:id:IPあたり時間1,000件(メタデータルックアップ)
  • GET /shares/:id/download:IPあたり時間100件(エグレスコスト)

エッジ(Cloudflare、Fastly)でフロア保護のためにレート制限を適用し、バースト制御のためにアプリケーション(express-rate-limit、Fastifyの@fastify/rate-limit)で2番目の層を適用する。秒単位でRetry-After付きの429を返す。成功レスポンスにもレート制限ヘッダーを含める:

RateLimit-Limit: 20
RateLimit-Remaining: 17
RateLimit-Reset: 2843

クライアントが処理できるエラーレスポンス

RFC 7807 Problem Detailsが標準だ。すべてのエラーはContent-Type: application/problem+jsonを返す:

{
  "type": "https://api.example.com/errors/chunk-offset-mismatch",
  "title": "Chunk offset mismatch",
  "status": 409,
  "detail": "Server expected offset 5242880, received 4194304.",
  "expected_offset": 5242880,
  "session_id": "abc123"
}

type URIはクライアントがパターンマッチングに使うため、文書化され安定している必要がある。カスタムフィールドがマシン処理可能なコンテキストを追加する。エラーにスタックトレース、ファイルパス、または内部IDを決してリークしないこと。

バージョニングと負債の蓄積防止

ヘッダーでなくURLパス(/v1/sessions)でバージョニングする。パスバージョニングはログで可視で、キャッシュ可能で、Accept: application/vnd.example.v1+jsonよりデバッグが容易だ。v2がリリースされてから少なくとも24ヶ月間はv1をサポートする。フィールドを自由に追加する(クライアントは不明なフィールドを無視する必要がある)が、安定バージョンではフィールドを削除したりリネームしたりしない。

HexaTransferのAPIはこれらのパターンに従っている—短いリソース、tus.ioスタイルのチャンクアップロード、Problem Detailsエラー、15分の署名付きダウンロード、RateLimitヘッダー。詳細は https://hexatransfer.com で。無料、アカウント不要、最大10GB。

エンドツーエンド暗号化で大容量ファイルを安全に送信

エンドツーエンド暗号化で最大10GBのファイルを無料で転送。アカウント不要。ファイルはアップロード前にブラウザで暗号化されるため、他の誰にも読まれません。

ファイルを送信