[英]How to send data using fetch and POST request with credentials included?
我想使用 fetch 從端口 3000 上的 React 前端向 3005 上的 node.js 服務器發送一些 JSON 數據。我在服務器上配置了 cors,但每次嘗試使用 cookie 發送請求時,Chrome 都會拋出錯誤:
CORS 策略已阻止從來源“ http: //localhost:3005/user-connected”訪問“ http://localhost:3005/user-connected ”:對預檢請求的響應未通過訪問控制檢查:值當請求的憑據模式為“include”時,響應中的“Access-Control-Allow-Origin”標頭不能是通配符“*”。
跳過來自服務器代碼的所有 console.log。
當我在獲取代碼中刪除標頭時
“內容類型”、“應用程序/json”
我收到 cookie,但沒有數據。 包含此標頭但沒有憑據:“include”,我可以獲得我的數據,但我永遠不會同時獲得兩者。
這是我的獲取代碼:
fetch("http://localhost:3005/user-connected", {
mode: "cors",
method: "post",
headers: [
["Content-Type", "application/json"],
],
credentials: "include",
body: JSON.stringify({data: "123"})
})
.then(data => data.json())
.then((data) => {
console.log(`Response: ${JSON.stringify(data)}`);
}).catch(err => {
console.log(`Error: ${err}`)
});
Node.js cors 配置:
app.use(cors({credentials: true}));
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type', 'Access-Control-Allow-Origin', 'Origin');
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
還有我的發帖路線:
let cookiesData = (req, res) => {
console.log(`Cookie user-connected: ${req.cookies.io}`)
console.log(`Received data: ${JSON.stringify(req.body)}`);
res.send({ status: "OK" });
}
router.post("/user-connected", cors({origin: 'http://localhost:3000'}), cookiesData);
甚至可以做我想做的事嗎? 或者我錯過了一些重要的配置?
您需要在 post 方法的獲取請求中傳遞這樣的標頭:
{
credentials: 'include',
mode: 'cors',
method: 'POST',
headers: { 'Content-Type': 'application/json' },
}
您必須確保已授予訪問權限 allow origin for localhost:3000
嘗試使用標頭作為對象:
headers: {
"Content-Type": "application/json",
},
文檔Fetch Reference - Headers顯示帶有對象而非數組的示例
每當前端和后端之間的連接過程中發生錯誤時,通常最好將問題分離到這些端,所以首先讓我們完全忽略前端。 相反,我們可以使用 curl 或Postman查詢后端,通過它們您可以深入了解服務器實際返回的內容。
現在在您的情況下,CORS 飛行前請求是最重要的請求,並且可以通過向特定服務器路徑發送 OPTIONS 請求來檢查它是否正確設置。
然后您會發現, 不能同時使用通配符和憑據。
現在,如果您更改路由本身的cors({... })
選項,您會發現這不會影響返回的實際 OPTIONS 標頭。 也就是說,因為第一個cors()
將終止所有 OPTION 請求並使用 uts 配置進行應答,所有進一步cors()
中間件都不會改變任何東西。
因此,您應該添加一個全局 cors 處理程序:
app.use(cors({origin: 'http://localhost:3000', credentials: true }));
// don't use cors() again!
或者(這可能更好,因為它允許細粒度的訪問控制)將 cors 設置單獨添加到每個路由:
app.use("/route", cors({origin: 'http://localhost:3000'}));
app.get("/route", (req, res) => { /*...*/ });
您也可以將其添加到路由器,以便 cors 策略僅影響特定路徑。
添加 Content-Type 將在發送實際請求之前首先觸發預檢請求。 預檢請求方法是選項。 OPTIONS 不在請求標頭中包含 cookie(至少對於 Chrome 和 Firefox)。
錯誤可能是因為這段代碼:
console.log(`Cookie user-connected: ${req.cookies.io}`)
req.cookies 在預檢請求期間為 null,當您嘗試獲取 req.cookies.io 時會拋出錯誤。 預檢請求要求服務器返回 200(請參閱https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Preflighted_requests )。 您的代碼有錯誤可能會拋出 500,從而向您顯示可怕的 CORS 錯誤消息。
您必須首先處理預檢請求。
在服務器端,嘗試處理 CORS 代碼中的 OPTIONS 方法以在 next() 之前返回 200:
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type', 'Access-Control-Allow-Origin', 'Origin');
res.setHeader('Access-Control-Allow-Credentials', true);
if (req.method === 'OPTIONS') {
res.sendStatus(200);
return;
}
next();
});
這將阻止 next() 在預檢請求期間執行任何代碼,並告訴客戶端可以發送實際請求。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.