1188 字
6 分鐘
解決 CORS Preflight 404 錯誤
CORS Preflight 404 錯誤解析
在前端開發中,你可能會遇到以下錯誤訊息:
Failed to load resource: Preflight response is not successful. Status code: 404
這個錯誤表示你的跨來源資源共享(CORS)請求中,瀏覽器自動發起的預檢(Preflight)請求失敗了,伺服器回應了 HTTP 404 狀態碼。這是一個常見但經常被誤解的問題,本文將詳細解釋其原因和解決方法。
什麼是 Preflight 請求?
當瀏覽器需要進行「非簡單請求」的跨域操作時,會先發送一個 OPTIONS 方法的「預檢請求」(Preflight Request)到伺服器,以確認伺服器是否允許實際的請求。這是 CORS 機制的一部分,目的是保護伺服器不受未經授權的跨域請求影響。
以下情況會觸發預檢請求:
- 使用 GET、HEAD、POST 以外的 HTTP 方法(如 PUT、DELETE)
- 設置了特定的自定義請求標頭(如
Authorization
、X-API-Key
等) - 使用
Content-Type
為application/json
等非簡單內容類型 - 使用了
credentials: 'include'
或withCredentials: true
設置
404 錯誤的原因
當預檢請求收到 404 回應時,表示:
- 伺服器未處理 OPTIONS 請求:伺服器可能沒有配置來回應 OPTIONS 方法,或者未在請求的路徑上正確處理該方法。
- URL 路徑錯誤:請求的 URL 可能不存在或拼寫錯誤,導致伺服器找不到對應的資源。
- 伺服器配置問題:伺服器可能缺少處理 CORS 的中間件或配置。
- 路由處理不正確:後端框架可能未正確設置處理 OPTIONS 請求的路由。
解決方案
1. 前端解決方案
簡化請求(如果可能)
如果可以,將請求簡化為「簡單請求」以避免預檢:
- 使用 GET、HEAD 或 POST 方法
- 移除自定義標頭
- 使用
application/x-www-form-urlencoded
、multipart/form-data
或text/plain
作為 Content-Type
// 替代
fetch('https://api.example.com/data', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
key: 'value'
})
})
開發環境使用代理
在開發環境中設置代理伺服器可以繞過 CORS 限制:
// vite.config.js
export default {
server: {
proxy: {
'/api': {
target: 'https://api.example.com',
changeOrigin: true,
},
}
}
}
使用 CORS 代理工具
對於測試或開發,可以使用如 Proxyman 等工具修改 API 回應標頭:
async function onResponse(context, url, request, response) {
// 為所有回應添加 CORS 標頭
response.headers["Access-Control-Allow-Origin"] = request.headers.Origin
response.headers["Access-Control-Allow-Credentials"] = "true"
response.headers["Access-Control-Allow-Methods"] = "GET, POST, PUT, DELETE, OPTIONS"
response.headers["Access-Control-Allow-Headers"] = "Content-Type, Authorization"
return response;
}
2. 後端解決方案
Express.js
const express = require('express');
const app = express();
// CORS 中間件
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'https://your-frontend-domain.com');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.header('Access-Control-Allow-Credentials', 'true');
// 處理 OPTIONS 請求
if (req.method === 'OPTIONS') {
return res.sendStatus(200);
}
next();
});
// 或使用 cors 套件
const cors = require('cors');
app.use(cors({
origin: 'https://your-frontend-domain.com',
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true
}));
其他後端框架
根據你使用的後端框架,確保:
- 正確配置 CORS 標頭
- 顯式處理 OPTIONS 請求
- 在所有 API 路由上允許 OPTIONS 方法
最佳實踐
- 明確配置 CORS:不要使用
Access-Control-Allow-Origin: *
當你需要攜帶憑證(cookies)時 - 檢查請求 URL:確保 URL 正確,並且後端確實有對應的路由
- 查看網路請求:使用瀏覽器開發者工具中的網路面板來查看具體的預檢請求細節
- 測試簡化的請求:嘗試簡化請求,看錯誤是否與特定請求設置有關
- 後端日誌:檢查伺服器日誌以確認是否收到了 OPTIONS 請求
常見錯誤排除
情境一:使用 Axios 發送 PUT 請求時出現 404
axios.put('https://api.example.com/resource', data, {
withCredentials: true
})
問題:這會觸發預檢請求,但後端可能未處理 OPTIONS 方法。
解決方案:確保後端路由處理 OPTIONS 請求。
情境二:在 React 專案中使用 fetch API 發送 JSON 資料
fetch('https://api.example.com/data', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
問題:Content-Type 為 application/json 會觸發預檢請求。
解決方案:後端需設置正確的 CORS 標頭。
總結
CORS Preflight 404 錯誤通常是由於伺服器未正確處理 OPTIONS 請求導致的。解決方法包括:
- 確保後端正確處理 OPTIONS 請求
- 設置適當的 CORS 標頭
- 在開發環境中使用代理服務器
- 簡化請求(如果可能)
透過理解 CORS 機制和預檢請求的運作原理,你將能夠更有效地診斷和解決這類問題,讓你的前端應用能夠順利與其他來源的資源進行互動。
參考資源
- MDN Web Docs: CORS - Mozilla 開發者網路上關於跨來源資源共享的完整指南
- CORS 完全手冊(一):為什麼會發生 CORS 錯誤? - Huli 的詳細 CORS 指南
希望這篇文章對你有所幫助!如果你有進一步的問題或需要更深入的解釋,歡迎在下方留言。
解決 CORS Preflight 404 錯誤
https://laplusda.com/posts/cors-preflight-404-error/