想定読者・必要な前提知識
- CORSエラーが出たけどヨクワカラン状態
- expressでの開発経験がある
- expressは使ったことないけどフレームワークに何となくの所感がある
そもそもCORSエラーとは?
Cross site origin resource sharingの略称
オリジンが違うところ同士で通信しようとすると生じるエラーです
オリジンについてはこちら
なぜ存在するか?
セキュリティ対策用です
以下の記事がわかりやすいのでこちらをご覧ください
どういう時に起こるのか?
ローカルで開発を進める際に
良く起こりますね
サーバ側にCORS用の設定がされていないAPIにサーバと別オリジンのクライアントでアクセスすると
基本的に生じます
CORSエラーの起こし方
fetchAPIを利用しオリジンの異なる通信を超すことで
CORSエラーを起こしてみます
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="main.js"></script>
</head>
<body>
</body>
</html>
main.js
// ローカルサーバーの3000番ポートにgetリクエストを送信する
const fetchReqToServer = async () => {
try {
const response = await fetch("http://localhost:3080")
const data = await response.text() // ローカルサーバーから返ってきたテキストデータ [Hello World]
console.log(data)
} catch (error) {
console.error("エラーが発生しました:", error)
}
}
fetchReqToServer()
server.js
const express = require('express')
const app = express()
// getリクエストを受け取る
// この場合はmain.jsのfetchReqToServer()が送信したリクエストを受け取る
app.get("/", (req, res) => {
console.log("GET /get リクエストを受信しました");
res.send("Hello World") // main.jsにHello Worldを返す
})
// 3000番ポートでサーバーを起動
app.listen(3080, () => {
console.log("Server is running on port 3000");
});
なおプロジェクトの全体構造は以下の通りです
これでindex.htmlをlive serverなどで起動し
ブラウザの開発者ツールからconsoleタブを見ると以下の様になっているかと思います。
cliant/:1 Access to fetch at 'http://localhost:3080/' from origin 'http://localhost:5500' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.Understand this error
main.js:4 GET http://localhost:3080/ net::ERR_FAILED 200 (OK)
fetchReqToServer @ main.js:4
(anonymous) @ main.js:12Understand this error
main.js:8 エラーが発生しました: TypeError: Failed to fetch
at fetchReqToServer (main.js:4:32)
at main.js:12:1
fetchReqToServer @ main.js:8
await in fetchReqToServer
(anonymous) @ main.js:12Understand this error
multi-tabs.js:4816 Injected CSS loaded successfully
※ポート部分は各々によって変わるかと思いますので
適宜ご自身の環境に合わせていただければと思います。
2つの方法で直していく
方法①
express.jsが用意してくれているCORSメソッドを利用する
以下の様にcorsメソッドをuse()でミドルウェアに登録します
ポート部分は各々の設定に合わせて書き換えてください
const express = require('express')
const cors = require('cors') // requireしましょう
const app = express()
app.use(cors(
{
origin: "http://localhost:5500" // ローカルの5500ポートからのアクセスを受け付けるように設定
}
))
// getリクエストを受け取る
// この場合はmain.jsのfetchReqToServer()が送信したリクエストを受け取る
app.get("/", (req, res) => {
console.log("GET /get リクエストを受信しました");
res.send("Hello World")
})
// 3000番ポートでサーバーを起動
app.listen(3080, () => {
console.log("Server is running on port 3000");
});
方法②
プリフライトリクエストで飛んでくるOPRIONメソッドを利用
プリフライトリクエストに関してはこちら
const express = require('express')
const app = express()
const allowCrossOriginRequestInPreFlight = function (req, res, next) {
res.header('Access-Control-Allow-Origin', '*') // 任意のオリジンからのリクエストを許可
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE') // 任意のメソッドを許可,*としているなら不要
if ('OPTIONS' === req.method) {
res.send(200)
} else {
next()
}
}
app.use(allowCrossOriginRequestInPreFlight)
// getリクエストを受け取る
// この場合はmain.jsのfetchReqToServer()が送信したリクエストを受け取る
app.get("/", (req, res) => {
console.log("GET /get リクエストを受信しました");
res.send("Hello World") // main.jsにHello Worldを返す
})
// 3000番ポートでサーバーを起動
app.listen(3080, () => {
console.log("Server is running on port 3000");
});