Express调用Eve Online API后设置Cookie报错:res.cookie不是函数
我刚开始学习Express库,正在开发一款使用Eve Online API获取用户受限信息的应用。用户会被重定向到认证页面以获取access token和refresh token,所有步骤都正常,直到尝试从响应中提取refresh_token并设置Cookie时出现问题。
错误信息
(node:20600) UnhandledPromiseRejectionWarning: TypeError: res.cookie is not a function
我的代码
const url = 'https://login.eveonline.com/v2/oauth/token'; const options = { 'method':'POST', headers: { 'authorization':'Basic '+ process.env.ENV_PASS, 'Content-Type':'application/x-www-form-urlencoded', 'host':'login.eveonline.com' }, body:'' } function send_get_request(req, res){ options.body =`grant_type=authorization_code&code=${req.query.code}` fetch(url,options,{credentials:'include'}) .then(handle_stream) .then(handle_json) .then(set_cookie) .then(redirect_home) } function handle_stream(res){ return res.json() //handless data stream, returns responce } function handle_json(res){ return res.refresh_token } function set_cookie(res){ return res.cookie('refresh_token','hello') } function redirect_home(res){ res.redirect('http://localhost:3000/home') } router.get('/',send_get_request)
我尝试拆分.then()代码块,但res.cookie仍然不存在,也试过使用credentials,但没有效果。
问题原因
你完全混淆了Promise链中的参数:
send_get_request里的res是Express的响应对象,它才有cookie()和redirect()方法- 但在
.then()链中,每个函数的参数是上一个.then()返回的值:handle_stream的res是fetch请求返回的响应对象,不是Express的reshandle_json返回的是res.refresh_token字符串,所以set_cookie拿到的参数是这个字符串,不是Express的响应对象,自然没有cookie()方法
修复方案
需要把Express的res传递到后续的处理函数中,最简单的方式是在.then()里用箭头函数传递参数,或者直接内联逻辑避免参数混乱:
修改后的代码
const url = 'https://login.eveonline.com/v2/oauth/token'; const options = { method:'POST', headers: { 'authorization':'Basic '+ process.env.ENV_PASS, 'Content-Type':'application/x-www-form-urlencoded', 'host':'login.eveonline.com' }, body:'' } function send_get_request(req, res){ options.body =`grant_type=authorization_code&code=${req.query.code}` fetch(url, options) .then(fetchRes => fetchRes.json()) .then(jsonData => { // 使用Express的res对象设置Cookie res.cookie('refresh_token', jsonData.refresh_token, { httpOnly: true, // 推荐开启,防止XSS攻击 secure: process.env.NODE_ENV === 'production', // 生产环境需开启HTTPS maxAge: 7 * 24 * 60 * 60 * 1000 // 设置7天有效期示例 }); return res.redirect('http://localhost:3000/home'); }) .catch(err => { // 捕获请求错误,避免未处理的Promise拒绝警告 console.error('认证请求失败:', err); res.status(500).send('认证出错,请重试'); }); } router.get('/', send_get_request)
关键改动说明
- 直接在
.then()内联处理逻辑,彻底避免参数传递混淆 - 明确使用Express的
res对象调用cookie()和redirect()方法 - 添加
catch()捕获请求错误,解决UnhandledPromiseRejectionWarning问题 - 给Cookie添加安全配置(
httpOnly、secure),提升应用安全性
如果偏好保留拆分函数的写法,可以修改函数参数结构,主动传入Express的res:
function send_get_request(req, res){ options.body =`grant_type=authorization_code&code=${req.query.code}` fetch(url, options) .then(handle_stream) .then(jsonData => set_cookie(res, jsonData.refresh_token)) .then(() => redirect_home(res)) .catch(err => console.error('请求错误:', err)); } function handle_stream(fetchRes){ return fetchRes.json(); } function set_cookie(expressRes, refreshToken){ expressRes.cookie('refresh_token', refreshToken); } function redirect_home(expressRes){ expressRes.redirect('http://localhost:3000/home'); }
内容的提问来源于stack exchange,提问作者Rafael Franco
相关产品推荐
相关产品推荐

