この記事は NestJS Advent Calendar 2019 11日目の記事です。前日は @euxn23 さんによる「NestJS 循環参照」の予定でしたが、都合により遅れるとのことです。かくいう私も担当の日付を勘違いしていて、1日遅れの投稿となってしまったことをお詫び申し上げます。
本日は NestJS においてレスポンスのヘッダーを変える方法について紹介します。
Content-Type を変更する
特定のエンドポイントだけ返すコンテンツの種類が異なり、特定の Content-Type を設定したいなどのシチュエーションは往々にしてあると思います。
今回は例として、NewsController というコントローラ以下の feed という関数の担当するエンドポイントに対して、RSS フィードの Content-Type である application/rss+xml; charset=UTF-8
を設定する方法を例に解説したいと思います。
これの要件に対し、NestJS では2通りの解決方法があります。
@Header
デコレータを用いる方法
NestJS では、コントローラ内のエンドポイントに対して @Get
, @Post
と同様に @Header
というデコレータを用いることによってヘッダーの特定プロパティの返り値を上書きすることができます。
以下の例ではエンドポイントが返すレスポンスのヘッダーが常に application/rss+xml; charset=UTF-8
になります。
import { Controller, Get, Header } from '@nestjs/common';
@Controller('news')
export class NewsController {
@Get('/feed')
@Header('content-type', 'application/rss+xml; charset=UTF-8')
feed(): string {
return feedContent;
}
}
ただしこの方法を用いると、関数内でエラーが発生しエラーレスポンスが json で返されたときも指定した Content-Type で上書きされてしまいます。
Response オブジェクトに設定する方法
こちらは関数の引数として Response オブジェクトを受け取り、それに直接 Content-Type を設定する方法です。Express などを既に使ったことがある方にはおなじみの方法ではないでしょうか。
以下の例ではエンドポイントが返すレスポンスのヘッダーが生成処理の成功時のみ application/rss+xml; charset=UTF-8
になります。
import {
Controller,
Get,
Res,
HttpException,
HttpStatus,
} from '@nestjs/common';
import { Response } from 'express';
@Controller('news')
export class NewsController {
@Get('/feed')
async feed(@Res() res: Response) {
try {
// RSS フィードを生成する関数が存在すると仮定
const generatedFeed = await feedGenerator.generate();
res.set({
'content-type': 'application/rss+xml; charset=UTF-8',
});
res.send(generatedFeed);
} catch (error) {
throw new HttpException(
'Internal server error',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
}
ただ、上記コードを見てもらえばわかるように、NestJS では引数として受け取った部分をハンドリングしてやる必要があります。
今回は Response オブジェクトをヘッダーの設定のために呼び出しているので、そのオブジェクトに対してレスポンスを設定する部分まで面倒を見る必要があります。
デコレータで設定したときのように return でレスポンス内容を返してもタイムアウトしてしまう点に注意が必要です。
おわりに
本日の記事では、NestJS においてレスポンスヘッダーを書き換える方法を、設定したシチュエーションに合わせて2通りの手法で紹介しました。
明日の担当は @euxn23 さんです。