リクエスト先サーバー
パス | 役割 |
---|
/ | HTMLを配信するエンドポイント |
/api-full-cors | CORSとCORS Preflight Request に対応したエンドポイント |
/api-simple-cors | CORSの「単純なリクエスト」のみ対応し、CORS Preflight Request に非対応のエンドポイント |
/api-no-cors | CORS非対応のエンドポイント |
検証に使用したexpressサーバーのソースコード
クリックして展開
import express from "express";
import fs from "fs";
import https from "https";
import path from "path";
const app = express();
/**
* パス: "/"
* HTMLを配信するエンドポイント
*/
app.get("/", (req, res) => {
res.send("<html><body><h1>hello world</h1></body></html>");
});
/**
* パス: "/api-cors"
* CORSとCORS Preflight Request に対応したエンドポイント
*/
app.post("/api-full-cors", (req, res, next) => {
res.header("Access-Control-Allow-Origin", req.headers.origin);
res.json({ result: "ok" });
res.send();
});
app.options("/api-full-cors", (req, res) => {
res.header("Access-Control-Allow-Origin", req.headers.origin);
res.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
res.header("Access-Control-Allow-Headers", "Content-Type, Authorization");
res.send();
});
/**
* パス: "/api-simple-cors"
* CORSの「単純なリクエスト」のみ対応し、CORS Preflight Request に非対応のエンドポイント
*/
app.post("/api-simple-cors", (req, res, next) => {
res.header("Access-Control-Allow-Origin", req.headers.origin);
res.json({ result: "ok" });
res.send();
});
/**
* パス: "/api-no-cors"
* CORS非対応のエンドポイント
*/
app.post("/api-no-cors", (req, res, next) => {
res.json({ result: "ok" });
res.send();
});
// HTTPSサーバーの起動
const options = {
key: fs.readFileSync(path.join(__dirname, "..", "key.pem")),
cert: fs.readFileSync(path.join(__dirname, "..", "cert.pem")),
};
https.createServer(options, app).listen(3000, () => {
console.log("HTTPS Server running on port 3000");
});
// HTTPサーバーの起動
app.listen(3001, () => {
console.log("HTTP Server running on port 3001");
});
// HTTPサーバーの起動(2)
app.listen(3002, () => {
console.log("HTTP Server running on port 3002");
});
(補足)
expressでは、実装していないOPTIONSリクエストに対してもレスポンスを自動的に返却してしまう。ただし今回の場合、自動的に実装されるレスポンスに関してはAccess-Control-Allow-
ヘッダーが含まれないのでこのまま進める。
$ curl 'http://localhost:3001/api-simple-cors' -X 'OPTIONS' --head
HTTP/1.1 200 OK
X-Powered-By: Express
Allow: POST
Content-Type: text/html; charset=utf-8
Content-Length: 4
ETag: W/"4-Yf+Bwwqjx254r+pisuO9HfpJ6FQ"
Date: Sun, 21 Jul 2024 08:21:08 GMT
Connection: keep-alive
Keep-Alive: timeout=5
ケース 1
リクエスト条件
スキーマ | SSL証明書 | オリジン | リクエストの内容 |
---|
HTTP | n/a (HTTPのため未使用) | 同じ | 単純 |
結果
http://localhost:3001/ にアクセス後、Consoleで実行して確認する
api-full-cors | api-simple-cors | api-no-cors |
---|
OK | OK | OK |
var res = await fetch("http://localhost:3001/api-full-cors", {headers: {"Content-Type": "text/plain"}, body: "abc", method: "POST"})
console.log(res.ok) // true
var res = await fetch("http://localhost:3001/api-simple-cors", {headers: {"Content-Type": "text/plain"}, body: "abc", method: "POST"})
console.log(res.ok) // true
var res = await fetch("http://localhost:3001/api-no-cors", {headers: {"Content-Type": "text/plain"}, body: "abc", method: "POST"})
console.log(res.ok) // true
ケース 2
リクエスト条件
スキーマ | SSL証明書 | オリジン | リクエストの内容 |
---|
HTTP | n/a (HTTPのため未使用) | 同じ | 単純でない |
結果
http://localhost:3001/ にアクセス後、Consoleで実行して確認する
api-full-cors | api-simple-cors | api-no-cors |
---|
OK | OK | OK |
var res = await fetch("http://localhost:3001/api-full-cors", {headers: {"Content-Type": "application/json"}, body: JSON.stringify({data: "abc"}), method: "POST"})
console.log(res.ok) // true
var res = await fetch("http://localhost:3001/api-simple-cors", {headers: {"Content-Type": "application/json"}, body: JSON.stringify({data: "abc"}), method: "POST"})
console.log(res.ok) // true
var res = await fetch("http://localhost:3001/api-no-cors", {headers: {"Content-Type": "application/json"}, body: JSON.stringify({data: "abc"}), method: "POST"})
console.log(res.ok) // true
ケース 3
リクエスト条件
スキーマ | SSL証明書 | オリジン | リクエストの内容 |
---|
HTTP | n/a (HTTPのため未使用) | 異なる | 単純 |
結果
http://localhost:3001/ にアクセス後、Consoleで実行して確認する
api-full-cors | api-simple-cors | api-no-cors |
---|
OK | OK | NG |
var res = await fetch("http://localhost:3002/api-full-cors", {headers: {"Content-Type": "text/plain"}, body: "abc", method: "POST"})
console.log(res.ok) // true
var res = await fetch("http://localhost:3002/api-simple-cors", {headers: {"Content-Type": "text/plain"}, body: "abc", method: "POST"})
console.log(res.ok) // true
var res = await fetch("http://localhost:3002/api-no-cors", {headers: {"Content-Type": "text/plain"}, body: "abc", method: "POST"})
console.log(res.ok) // CORSエラー
ケース 4
リクエスト条件
スキーマ | SSL証明書 | オリジン | リクエストの内容 |
---|
HTTP | n/a (HTTPのため未使用) | 異なる | 単純でない |
結果
http://localhost:3001/ にアクセス後、Consoleで実行して確認する
api-full-cors | api-simple-cors | api-no-cors |
---|
OK | NG | NG |
var res = await fetch("http://localhost:3002/api-full-cors", {headers: {"Content-Type": "application/json"}, body: JSON.stringify({data: "abc"}), method: "POST"})
console.log(res.ok) // true
var res = await fetch("http://localhost:3002/api-simple-cors", {headers: {"Content-Type": "application/json"}, body: JSON.stringify({data: "abc"}), method: "POST"})
console.log(res.ok) // CORSエラー
var res = await fetch("http://localhost:3002/api-no-cors", {headers: {"Content-Type": "application/json"}, body: JSON.stringify({data: "abc"}), method: "POST"})
console.log(res.ok) // CORSエラー
ケース 5
リクエスト条件
スキーマ | SSL証明書 | オリジン | リクエストの内容 |
---|
HTTPS | 異常 (オレオレ証明書な場合) | 同じ | 単純 |
結果
https://localhost:3000 にアクセスし、証明書エラーをAcceptしてからConsoleで実行して確認する。
api-full-cors | api-simple-cors | api-no-cors |
---|
OK | OK | OK |
var res = await fetch("https://localhost:3000/api-full-cors", {headers: {"Content-Type": "text/plain"}, body: "abc", method: "POST"})
console.log(res.ok) // true
var res = await fetch("https://localhost:3000/api-simple-cors", {headers: {"Content-Type": "text/plain"}, body: "abc", method: "POST"})
console.log(res.ok) // true
var res = await fetch("https://localhost:3000/api-no-cors", {headers: {"Content-Type": "text/plain"}, body: "abc", method: "POST"})
console.log(res.ok) // true
ケース 6
リクエスト条件
スキーマ | SSL証明書 | オリジン | リクエストの内容 |
---|
HTTPS | 異常 (オレオレ証明書な場合) | 同じ | 単純でない |
結果
https://localhost:3000 にアクセスし、証明書エラーをAcceptしてからConsoleで実行して確認する
api-full-cors | api-simple-cors | api-no-cors |
---|
OK | OK | OK |
var res = await fetch("https://localhost:3000/api-full-cors", {headers: {"Content-Type": "application/json"}, body: JSON.stringify({data: "abc"}), method: "POST"})
console.log(res.ok) // true
var res = await fetch("https://localhost:3000/api-simple-cors", {headers: {"Content-Type": "application/json"}, body: JSON.stringify({data: "abc"}), method: "POST"})
console.log(res.ok) // true
var res = await fetch("https://localhost:3000/api-no-cors", {headers: {"Content-Type": "application/json"}, body: JSON.stringify({data: "abc"}), method: "POST"})
console.log(res.ok) // true
ケース 7
リクエスト条件
スキーマ | SSL証明書 | オリジン | リクエストの内容 |
---|
HTTPS | 異常 (オレオレ証明書な場合) | 異なる | 単純 |
結果
一度 https://localhost:3000 にアクセスし、証明書エラーをAcceptする。
その後、 https://example.com にアクセスし、そのConsoleで実行して確認する
api-full-cors | api-simple-cors | api-no-cors |
---|
OK | OK | NG |
var res = await fetch("https://localhost:3000/api-full-cors", {headers: {"Content-Type": "text/plain"}, body: "abc", method: "POST"})
console.log(res.ok) // true
var res = await fetch("https://localhost:3000/api-simple-cors", {headers: {"Content-Type": "text/plain"}, body: "abc", method: "POST"})
console.log(res.ok) // true
var res = await fetch("https://localhost:3000/api-no-cors", {headers: {"Content-Type": "text/plain"}, body: "abc", method: "POST"})
console.log(res.ok) // CORSエラー
ケース 8
リクエスト条件
スキーマ | SSL証明書 | オリジン | リクエストの内容 |
---|
HTTPS | 異常 (オレオレ証明書な場合) | 異なる | 単純でない |
結果
一度 https://localhost:3000 にアクセスし、証明書エラーをAcceptする。
その後、 https://example.com にアクセスし、そのConsoleで実行して確認する
api-full-cors | api-simple-cors | api-no-cors |
---|
OK | NG | NG |
var res = await fetch("https://localhost:3000/api-full-cors", {headers: {"Content-Type": "application/json"}, body: JSON.stringify({data: "abc"}), method: "POST"})
console.log(res.ok) // true
var res = await fetch("https://localhost:3000/api-simple-cors", {headers: {"Content-Type": "application/json"}, body: JSON.stringify({data: "abc"}), method: "POST"})
console.log(res.ok) // CORSエラー
var res = await fetch("https://localhost:3000/api-no-cors", {headers: {"Content-Type": "application/json"}, body: JSON.stringify({data: "abc"}), method: "POST"})
console.log(res.ok) // CORSエラー
ケース 9
リクエスト条件
スキーマ | SSL証明書 | オリジン | リクエストの内容 |
---|
HTTPS | 正常 | 同じ | 単純 |
結果
ngrok等を使って正しく署名された URL (例: https://sample.test) にアクセスしてからConsoleで実行して確認する
api-full-cors | api-simple-cors | api-no-cors |
---|
OK | OK | OK |
var res = await fetch("https://sample.test/api-full-cors", {headers: {"Content-Type": "text/plain"}, body: "abc", method: "POST"})
console.log(res.ok) // true
var res = await fetch("https://sample.test/api-simple-cors", {headers: {"Content-Type": "text/plain"}, body: "abc", method: "POST"})
console.log(res.ok) // true
var res = await fetch("https://sample.test/api-no-cors", {headers: {"Content-Type": "text/plain"}, body: "abc", method: "POST"})
console.log(res.ok) // true
ケース 10
リクエスト条件
スキーマ | SSL証明書 | オリジン | リクエストの内容 |
---|
HTTPS | 正常 | 同じ | 単純でない |
結果
ngrok等を使って正しく署名された https://[URL] にアクセスしてからConsoleで実行して確認する
api-full-cors | api-simple-cors | api-no-cors |
---|
OK | OK | OK |
var res = await fetch("https://sample.test/api-full-cors", {headers: {"Content-Type": "application/json"}, body: JSON.stringify({data: "abc"}), method: "POST"})
console.log(res.ok) // true
var res = await fetch("https://sample.test/api-simple-cors", {headers: {"Content-Type": "application/json"}, body: JSON.stringify({data: "abc"}), method: "POST"})
console.log(res.ok) // true
var res = await fetch("https://sample.test/api-no-cors", {headers: {"Content-Type": "application/json"}, body: JSON.stringify({data: "abc"}), method: "POST"})
console.log(res.ok) // true
ケース 11
リクエスト条件
スキーマ | SSL証明書 | オリジン | リクエストの内容 |
---|
HTTPS | 正常 | 異なる | 単純 |
結果
https://example.com にアクセスしてからConsoleで実行して確認する
api-full-cors | api-simple-cors | api-no-cors |
---|
OK | OK | NG |
var res = await fetch("https://sample.test/api-full-cors", {headers: {"Content-Type": "text/plain"}, body: "abc", method: "POST"})
console.log(res.ok) // true
var res = await fetch("https://sample.test/api-simple-cors", {headers: {"Content-Type": "text/plain"}, body: "abc", method: "POST"})
console.log(res.ok) // true
var res = await fetch("https://sample.test/api-no-cors", {headers: {"Content-Type": "text/plain"}, body: "abc", method: "POST"})
console.log(res.ok) // CORSエラー
ケース 12
リクエスト条件
スキーマ | SSL証明書 | オリジン | リクエストの内容 |
---|
HTTPS | 正常 | 異なる | 単純でない |
結果
https://example.com にアクセスしてからConsoleで実行して確認する
api-full-cors | api-simple-cors | api-no-cors |
---|
OK | NG | NG |
var res = await fetch("https://sample.test/api-full-cors", {headers: {"Content-Type": "application/json"}, body: JSON.stringify({data: "abc"}), method: "POST"})
console.log(res.ok) // true
var res = await fetch("https://sample.test/api-simple-cors", {headers: {"Content-Type": "application/json"}, body: JSON.stringify({data: "abc"}), method: "POST"})
console.log(res.ok) // CORSエラー
var res = await fetch("https://sample.test/api-no-cors", {headers: {"Content-Type": "application/json"}, body: JSON.stringify({data: "abc"}), method: "POST"})
console.log(res.ok) // CORSエラー