You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的res
    • handle_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)

关键改动说明

  1. 直接在.then()内联处理逻辑,彻底避免参数传递混淆
  2. 明确使用Express的res对象调用cookie()和redirect()方法
  3. 添加catch()捕获请求错误,解决UnhandledPromiseRejectionWarning问题
  4. 给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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 11:31:02