🔗

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を取得することができます。

出典

Studio Tech Blog

Discussion