🔧

[Next.js] API リクエストの CORS エラーを回避する

2022/10/27に公開約2,200字

こんにちは、よしお (@yoshio__25) です。

Webフロントエンジニアは皆さん、下のエラーを一度は目にしたことがあるのではないでしょうか。

Access to fetch at '' from origin '' has been blocked by CORS policy

CORSとは

MDN に以下のように記述されています。

https://developer.mozilla.org/ja/docs/Web/HTTP/CORS

オリジン間リソース共有 (Cross-Origin Resource Sharing, CORS) は、追加の HTTP ヘッダーを使用して、あるオリジンで動作しているウェブアプリケーションに、異なるオリジンにある選択されたリソースへのアクセス権を与えるようブラウザーに指示するための仕組みです。

つまり上のエラーメッセージは、異なるオリジンへのアクセスをしようとしたときに、セキュリティ上の理由からそのポリシーに反しているため、リクエストをブロックした旨を伝えています。

このポリシーはもちろん製品の開発時にも適用されます。
つまり開発用の localhost サーバーを立てて、そこから開発用の API サーバーにアクセスしたときも、上記エラーは発生するということです。

回避方法

API サーバーでの回避方法

このエラーの回避にはいくつか方法があります。
例えば API サーバーに Express を利用しているのであれば cors パッケージが利用できます。

var express = require('express');
var cors = require('cors');
var app = express();

app.use(cors());

ただしこれでは API サーバーへの改修も必要ですし、 Express 以外が利用されている場合には別の対策を考える必要があります。

Next.js での回避方法

Webフロントに Next.js を利用しているのであれば、それにぴったり合う機能が用意されています。

https://nextjs.org/docs/api-reference/next.config.js/rewrites

Rewrites は、あるリクエストを別のパスにマッピングする機能になります。

next.config.js
module.exports = {
  async rewrites() {
    return [
      {
        source: '/about',
        destination: '/',
      },
    ];
  },
};

しかもこの機能はマッピング先を Next.js 内のルーティングだけでなく、外部の URL に対しても行うことができます。

https://nextjs.org/docs/api-reference/next.config.js/rewrites#rewriting-to-an-external-url

next.config.js
module.exports = {
  async rewrites() {
    return [
      {
        source: '/blog',
        destination: 'https://example.com/blog',
      },
    ];
  },
};

これを利用することで、例えば localhost での開発時にも、開発用の API サーバーへ直接リクエストを行うことが簡単にできます。

next.config.js
const rewrites = process.env.NODE_ENV === 'development' ? [
  {
    source: '/api/:path*',
    destination: 'https://dev.api.example.com/:path*',
  },
] : [];

module.exports = {
  async rewrites() {
    return rewrites;
  },
};
fetch('http://localhost:3000/api/user')
// -> https://dev.api.example.com/user

まとめ

Webフロントエンドの開発時によく目にする CORS エラーですが、 Next.js を利用していれば Rewrites 機能を利用することで簡単に対処することができます。

Discussion

ログインするとコメントできます