Nest.jsでCORSを許可する

いくつか方法があるので、それぞれ紹介する。
今回は、クライアントからのリクエストに対して以下のヘッダーが付加されることをゴールとする。

```
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
```

## CORS Middleware

Nest.jsには[Middleware](https://docs.nestjs.com/middleware)という機能があり、リクエスト/レスポンスオブジェクトを任意のタイミングで操作することができます。(ExpressのMiddlewareと同様のイメージ)

まずは、以下のように`NestMiddleware`を実装したMiddlewareを作成します。
ここでは、`CorsMiddleware`としました。

```ts:cors.middleware.ts
import { MiddlewareFunction, Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

@Injectable()
export class CorsMiddleware implements NestMiddleware {
  resolve(): MiddlewareFunction {
    return (req: Request, res: Response, next: NextFunction) => {
      res.header('Access-Control-Allow-Origin', '*');
      res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
      next();
    };
  }
}
```

次に、app.module.tsでMiddlewareを適用します。

```ts:app.module.ts
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { CorsMiddleware } from './cors.middleware';

@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer): MiddlewareConsumer | void {
    consumer.apply(CorsMiddleware).forRoutes('*');
  }
}
```

**注意**

`@Middleware`というDecoratorがありますが、これは現在Deprecatedになっているので、`@Injectable()`を使うようにします。

```
WARNING!!
The @Middleware() decorator is deprecated and will be removed within next major release. Use @Injectable() instead.
```

## app.enableCors()

おそらくこれが一番手軽な方法。
アプリケーションのブートストラップ時に`app.enableCors()`を使ってCORSオプションを渡す。

```ts:main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  app.enableCors({
    origin: '*',
    allowedHeaders: 'Origin, X-Requested-With, Content-Type, Accept',
  });

  await app.listen(3000);
}
bootstrap();
```

`enableCors()`に渡すオプションは次のように定義されているので、上記のoriginとallow headerの他にも細かく設定が可能。

```ts
export interface CorsOptions {
    origin?: boolean | string | RegExp | (string | RegExp)[] | CustomOrigin;
    methods?: string | string[];
    allowedHeaders?: string | string[];
    exposedHeaders?: string | string[];
    credentials?: boolean;
    maxAge?: number;
    preflightContinue?: boolean;
    optionsSuccessStatus?: number;
}
```

## app.use()

Nest.jsのHTTP HandlerはExpressのラッパーなので、Expressのインターフェースを間接的に呼び出せる。
次のように、ExpressでMiddlewareを使うときと同様にCORSの有効化ができる。

```ts:main.ts
import { NestFactory } from '@nestjs/core';
import { Request, Response, NextFunction } from 'express';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  app.use((req: Request, res: Response, next: NextFunction) => {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
    next();
  });

  await app.listen(3000);
}
bootstrap();
```

## どれを使えばよいか

ひとまず開発中にCORSを許可したい場合などは、`app.enableCors()`が一番手軽で良さそう。
よりアプリケーションに近いレイヤーで、CORS関連以外のヘッダー操作も同時に行いたいといった場合には、Middleware化しておいたほうがメンテナンスもしやすくなり、良さそうです。


## 参考

https://docs.nestjs.com/middleware
https://qiita.com/tomoya_ozawa/items/feca4ffc6217d585b037
https://www.thecodecampus.de/blog/creating-cors-middleware-nest-js/