NestJSでCloud Runのコンテナ自URLを正しく取得する方法
はじめに
NestJS を使って Cloud Run 上にデプロイされたアプリケーション内で、自サービスの URL を取得する際に、req.protocol が http になってしまうことがあります。これは、リバースプロキシを介したリクエストで、内部的に http で処理されるためです。
Cloud Run では、外部リクエストは HTTPS で送信されますが、コンテナ内部に届く際には HTTP として認識される場合があります。この問題を解決するためには、Express の trust proxy 設定を行い、X-Forwarded-Proto ヘッダーを信頼することで正しいプロトコル(https)を取得する必要があります。
この記事では、NestJS での trust proxy 設定の方法と、自URLを正しく取得するための実装方法について解説します。
NestJSでの解決方法
trust proxy の設定
NestJS では、Express を使ったアプリケーションであれば、app.set('trust proxy', true) を設定することで、リバースプロキシの背後にある場合でも、正しいプロトコルを認識できるようにできます。
main.ts の設定
まず、main.ts ファイルで、NestJS のアプリケーションに対して trust proxy 設定を追加します。
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();
この設定によって、リクエストの X-Forwarded-Proto ヘッダーが信頼され、正しいプロトコル(通常は 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() デコレーターを使用して Request オブジェクトを取得し、その中の protocol プロパティからプロトコル情報を確認します。これにより、リクエストがリバースプロキシを通過しても、正しいプロトコル (https) が取得できます。
まとめ
NestJS で Cloud Run のコンテナ内で自サービスの URL を取得する際、プロトコルが http になってしまう場合は、リバースプロキシを信頼するために trust proxy 設定を行う必要があります。これにより、req.protocol が正しく https を返し、正しい自URLを取得することができます。
Discussion