Spring Framework 7.1.0-M1は、単なる機能追加にとどまらず、Webアプリケーションの境界部分を見直すきっかけになるリリースです。特に重要なのが、リバースプロキシ配下で利用するForwardedヘッダーの扱いです。
最重要変更:Forwardedヘッダーの種類を明示する
Spring MVCのForwardedHeaderFilterと、WebFluxのForwardedHeaderTransformerでは、これまで標準のForwardedヘッダーと、互換形式であるX-Forwarded-*ヘッダーの両方を自動的に確認する動作が可能でした。
Spring Framework 7.1では、どちらの形式を信頼するのかをboolean引数で指定するコンストラクターが追加されます。従来のデフォルトコンストラクターも当面は利用できますが、非推奨となり、将来的な削除が予定されています。
この変更の本質は、APIの書き換えではありません。アプリケーションが「どのプロキシから、どのヘッダー形式を受け取るのか」を明確にし、曖昧な自動判定を避けることにあります。
例えば、標準のForwardedヘッダーを利用する構成では、アプリケーション側で次のように明示します。
@Bean
ForwardedHeaderFilter forwardedHeaderFilter() {
// 引数の意味とtrue/falseの対応は、採用するSpring FrameworkのAPI仕様を確認する
return new ForwardedHeaderFilter(true);
}
WebFluxでは、同様の考え方でForwardedHeaderTransformerを設定します。実際のboolean値は、標準のForwardedを使うのか、X-Forwarded-*を使うのかというプロキシ側の仕様に合わせて決定してください。
URL生成やHTTPS判定に直結する
Forwardedヘッダーは、単にログへ記録する情報ではありません。Springはこれらの値をもとに、次のような処理を行います。
httpsなどのスキーム判定- 外部公開用ホスト名・ポートの判定
- リダイレクト先URLの生成
HttpServletRequestから見えるクライアント情報の補正- リンクやLocationヘッダーの外部向けURL生成
例えば、ロードバランサーでTLSを終端し、内部ではHTTPでSpringアプリケーションへ転送する構成を考えます。Forwarded情報が正しく処理されなければ、アプリケーションが自分自身をhttp://internal-serviceとして認識し、HTTPSサイト上でHTTPのリダイレクトを返す、内部ホスト名を含むURLを生成する、といった問題が発生します。
さらに、アプリケーションが複数のヘッダー形式を無条件に受け入れると、外部から送信されたヘッダーをプロキシの情報として誤認するリスクがあります。信頼できるプロキシが付与した値と、クライアントが事前に付けた値を区別できなければ、ホストヘッダー汚染やURL生成の不正利用につながる可能性があります。
移行時に確認すべきプロキシ構成
Spring Framework 7.1への移行前に、アプリケーションだけでなく、プロキシチェーン全体を確認する必要があります。
1. 利用するヘッダー形式を一つに決める
Nginx、ALB、Ingress、CDNなど、各レイヤーがどのヘッダーを設定・上書き・削除するのかを整理します。標準のForwardedを採用するのか、既存環境との互換性を優先してX-Forwarded-*を採用するのかを決定し、Spring側の設定と一致させます。
2. クライアント由来のヘッダーを信頼しない
プロキシがヘッダーを上書きせず、そのままバックエンドへ渡している場合、クライアントが偽装した値をアプリケーションが信頼してしまう可能性があります。プロキシ側で対象ヘッダーをいったん削除してから、実際の接続情報に基づいて再付与する構成が安全です。
3. X-Forwarded-Prefixの扱いを確認する
アプリケーションをhttps://example.com/apiのようなサブパス配下で公開している場合、X-Forwarded-PrefixがURL生成に必要になることがあります。7.1では、このプレフィックス利用も個別に有効化する設計になっているため、サブパス公開を行っている環境は設定変更の影響を確認してください。
4. テストで外部URLを検証する
単体テストだけでなく、実際のプロキシを含む結合テストで次のケースを確認します。
- HTTPSアクセス時にHTTPSのリダイレクトが返るか
- 外部ホスト名を含むURLが正しく生成されるか
- サブパス配下でリンクやリダイレクトが壊れないか
- 不正なForwardedヘッダーを直接送信した場合に想定外の動作をしないか
- 複数プロキシを経由した場合に、どの値を採用するか
Spring Bootを利用している場合は、server.forward-headers-strategyなどの既存設定だけでなく、使用しているSpring Bootの7.1対応バージョンにおけるヘッダー形式の指定方法も確認が必要です。Framework単体のAPI変更と、Bootの自動設定変更は同時に適用されるとは限らないため、リリースノートと生成された設定を照合してください。
その他の移行ポイント
RestTemplate関連APIの非推奨化
RestTemplateおよび関連型が非推奨化されます。直ちに動作しなくなる変更ではありませんが、新規実装では後継のHTTPクライアントを選択し、既存コードも段階的な移行計画を立てるべきです。
同期的なHTTP通信であればRestClient、リアクティブな処理やストリーミングを重視する場合はWebClientを候補にできます。移行時には、タイムアウト、リトライ、エラー変換、トレース、接続プールといった運用上の設定が失われないかを確認してください。
Multipart処理の分離と刷新
Multipart対応がFormHttpMessageConverterから分離され、MultipartHttpMessageConverterが導入されます。ファイルアップロードを利用するAPIでは、次の点を重点的にテストしてください。
- multipartのContent-Typeとboundary
- 大容量ファイルのストリーミング
- パートごとのContent-Type
- 不正なリクエストや途中切断時のリソース解放
- MVC、WebFlux、テストクライアント間の挙動差
MultipartParserのエラー処理やリソースクローズも改善されているため、これまで例外処理が曖昧だった実装では、エラー時のレスポンスとログを見直す良い機会です。
静的リソースの安全性強化
MVCとWebFluxで、安全でない静的リソースの場所を拒否する変更が入ります。設定ミスによって意図しないファイルが公開されるリスクを抑える方向の変更ですが、独自のResourceResolverやファイルシステム上のカスタムパスを利用しているアプリケーションでは、起動時エラーや404の増加に注意が必要です。
特に、クラスパス外のディレクトリ、ユーザー入力を含むパス、シンボリックリンクを経由した公開設定を棚卸ししてください。
JSON LinesとHTTPメッセージ処理
application/jsonlがapplication/x-ndjsonと並んでサポートされます。ログ配信、AI推論結果、イベントストリーミングなどでJSON Linesを利用している場合、クライアントとサーバー間のContent-Typeの不一致を減らせます。一方、既存のクライアントが片方のMIMEタイプしか受け付けない可能性があるため、Content Negotiationのテストは必要です。
依存ライブラリの更新
Kotlin、Kotlin Coroutines、Jackson、Hibernate ORM、JUnit、Micrometer、Reactorなどが更新されます。特にMilestone版のReactorやMicrometerを含むため、Spring Frameworkだけを差し替えるのではなく、Spring Bootの対応バージョンと依存関係管理をセットで確認する必要があります。
Spring 7.1移行チェックリスト
- ForwardedとX-Forwarded-*のどちらを利用するか決定する
- プロキシでクライアント由来の転送ヘッダーを削除・上書きする
- MVCまたはWebFluxのコンストラクター設定を明示する
X-Forwarded-Prefixを利用する環境の設定を確認する- HTTPS判定、リダイレクト、外部URL生成を結合テストする
- RestTemplate利用箇所を洗い出し、後継APIへの移行計画を作る
- Multipartのアップロード・切断・大容量ファイルをテストする
- 静的リソースの公開パスとカスタムResolverを監査する
- JSON LinesのContent-Type互換性を確認する
- Spring Bootと関連ライブラリの対応バージョンを固定する
Spring Framework 7.1.0-M1は、まだ本番導入を急ぐ段階のリリースではありません。しかし、Forwardedヘッダーの変更は本番障害やセキュリティ問題に直結しやすい領域です。Milestone版の段階からプロキシ構成、URL生成、HTTPクライアント、ファイルアップロードを洗い出しておけば、正式版への移行時に設定を場当たり的に修正する必要がなくなります。今回の変更は、Springアプリケーションを「内部から見たHTTP」ではなく、「信頼境界を越えた後のHTTP」として正しく設計し直すためのシグナルと捉えるべきでしょう。
