NestJSでCloud Runのコンテナ自URLを正しく取得する方法
はじめに
Cloud Run にデプロイした NestJS アプリケーションで自サービスの URL を組み立てると、req.protocol が http を返すことがあります。Cloud Run はクライアントからの HTTPS リクエストを手前のプロキシで受け、コンテナへは HTTP で転送するためです。
クライアントが使った元のプロトコルは、プロキシが付与する X-Forwarded-Proto ヘッダーに残っています。Express の trust proxy を有効にすると、Express はこのヘッダーを信頼し、req.protocol に https を返すようになります。
この記事では、NestJS で trust proxy を設定する方法と、自サービスの URL を正しく取得する実装を説明します。
NestJS での解決方法
trust proxy の設定
Express をベースにした NestJS アプリケーションでは、app.set('trust proxy', true) を設定すると、リバースプロキシの背後でも正しいプロトコルを取得できます。この設定は、main.ts でアプリケーションを生成した直後に追加します。
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { NestExpressApplication } from '@nestjs/platform-express';
async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
// Express の trust proxy 設定
app.set('trust proxy', true);
await app.listen(process.env.PORT || 8080);
}
bootstrap();
この設定により、Express は X-Forwarded-Proto ヘッダーの値を req.protocol に反映します。クライアントが HTTPS でアクセスした場合、req.protocol は https になります。
コントローラーでの自サービス URL の取得
次のコントローラーは、req.protocol から取得したプロトコルを使って自サービスの URL を組み立てます。
import { Controller, Get, Req } from '@nestjs/common';
import { Request } from 'express';
@Controller()
export class AppController {
@Get()
getHello(@Req() req: Request): string {
const protocol = req.protocol; // 正しいプロトコル(通常は 'https')
const host = req.hostname;
const port = process.env.PORT || 8080;
const selfUrl = `${protocol}://${host}:${port}`;
return `自URL: ${selfUrl}`;
}
}
@Req() デコレーターで Express の Request オブジェクトを受け取り、その protocol プロパティからプロトコルを読み取ります。trust proxy を設定していれば、リクエストがリバースプロキシを経由していても https を取得できます。
まとめ
Cloud Run 上の NestJS アプリケーションで自サービスの URL のプロトコルが http になる場合は、trust proxy を設定して、プロキシが付与する X-Forwarded-Proto ヘッダーを Express に信頼させます。これで req.protocol が https を返し、自サービスの URL を正しく組み立てられます。
Discussion