POSTメソッドを叩いたらエラーが出た
NestJS
で作成したAPI
をLambdaに乗せ
、API Gateway
でエンドポイントを作成した。
フロントエンドはNextJS
で作成し、Vercel
にデプロイした。
で、無事画面表示とGet
が成功し、得たいデータが表示された。
ただPOST API
を叩いた時
Access to fetch at 'https://xxxxxx.amazonaws.com/api/v1/login' from origin 'https://xxxxxxx.vercel.app' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
というエラーがでた。
CORSは有効にしている
上のエラーを読む限り、CORS
に関するエラーということがわかる。
ただNestJS
の方でCORS
は有効にしている。
該当のソースは下記の通り。
const app = await NestFactory.create(AppModule);
await app.init();
app.useGlobalPipes(new ValidationPipe());
app.useGlobalFilters(new HttpExceptionFilter());
// CORSの有効化
app.enableCors();
const expressApp = app.getHttpAdapter().getInstance();
return serverlessExpress({ app: expressApp });
Get
はできているし、CORS
もきっと有効に出来ているに違いない。
じゃあ、なんでPOST
はできないの?
沼に落ちた。
解決方法
ちなみに同じ状況に陥った人のために先に解決方法を載せておくと、下記のようにawait app.init();
の位置が肝だった。
const app = await NestFactory.create(AppModule);
app.enableCors()
app.useGlobalPipes(new ValidationPipe());
app.useGlobalFilters(new HttpExceptionFilter());
await app.init();
const expressApp = app.getHttpAdapter().getInstance();
return serverlessExpress({ app: expressApp });
理由はいまいちわからないので、ここには記載しない。
ここに至るまでの道のり(読むかは自己判断で)
上記の通りで解決するので後はただの蛇足。
ただ自分がどのように解決に至ったかをログとして残しておく。
見る価値があるかはわからない。
API GatewayでCORSを設定する
AWS
のほうでも同様にCORS
を設定する必要があるのか? という思いで設定した。
API Gateway > CORS
で設定にいき、下記の通り設定した。
Access-Control-Allow-Origin | * |
---|---|
Access-Control-Allow-Headers | content-type,authorization |
Access-Control-Allow-Methods | GET,POST,PUT,DELETE,OPTIONS |
がエラーが変わらないので、ReactからCognitoで認証認可されたAPI Gatewayを呼び出すを参考に下記の通り変更した。
Access-Control-Allow-Origin | https://vote-for-name.vercel.app |
---|---|
Access-Control-Allow-Headers | content-type,authorization |
Access-Control-Allow-Methods | * |
Access-Control-Max-Age | -1秒 |
Access-Control-Allow-Credentials | true |
に変更したが意味がなかった。
※ てかNestJSでCORSを設定しなくてもここで設定できる?(未確認)それならソースビルドしなくていいので負担が減りそう。いつか試してみたい。
## NestJS側でCORS有効化の書き方を変更してみる
const app = await NestFactory.create(AppModule);
await app.init();
app.useGlobalPipes(new ValidationPipe());
app.useGlobalFilters(new HttpExceptionFilter());
app.use((req: any, res: any, next: any) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.header('Access-Control-Allow-Methods', '*');
next();
});
const expressApp = app.getHttpAdapter().getInstance();
return serverlessExpress({ app: expressApp });
にしたみたけど変わらず、エラーが出続ける。
そもそも
app.use((req: any, res: any, next: any) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.header('Access-Control-Allow-Methods', '*');
next();
});
これを追加した時点で、
app.enableCors()
を削除してるけど、これも必要なんじゃないかということで復活してみる。
が、変わらず無理のまま。
エラーでpreflight
がどうこう言っているので、
if ('OPTIONS' == req.method) {
res.send(204);
}
else {
next();
}
CORS “It does not have HTTP ok status.”上記を追加してみた。
ができない。
同様に、上記サイトを参考にapp.options('*', cors())
を追加し見たが、そんな型存在しないともっと前の段階で怒られた。
Githubで他の人のソースを探る
どうやら順番が違うことに気が付いて無事解決。
諦めずに取り組んで良かった。