下面是一个Webshop服务器的精简部分,有两个API:./login用于登录,./products用于展示产品.只有在成功登录后才能显示产品.

我使用的是带有Node.js的TypeScrip和启用了会话管理的Express.下面的代码还try 通过向API发送fetch()个请求来测试服务器.注意:我从within个Node.js发送了fetch()个请求,而不是从浏览器.下面的代码生成以下输出:

Login session ID: um2RykooJCer7Oy7YmJQs7s9ge3mZWL1
Products session ID: uAk03ochUM56rzJjPvbiRnFuPG8CUqTB
Products response: Error: Not logged in

可以看出,会话ID是不同的,这就是它无法显示产品的原因.当我让代码保持运行并在浏览器中手动键入API调用时:

http://localhost:3000/login
http://localhost:3000/products

然后代码就可以正常工作了,浏览器显示"Login OK",然后显示"Apple, Orange, Pear",两者都具有相同的会话ID.

所以问题是:如何让服务器测试在Node.js中正确地使用fetch(),就像从浏览器调用时一样?是否有一些选项可以给fetch()个请求或Express?我还没有找到.

附加问题:它也可以与NPM包的 node 获取一起工作吗?我使用它是因为Node.js的内置fetch()在其他地方给出了错误.

PS我使用的是最新版本的Node.js(v21.5)、Express、Express-Session和Node-Fetch.

import Express from "express";
import Session from "express-session";
// Uncomment this to use the node-fetch module, but gives the same result:
// import fetch from "node-fetch";

declare module 'express-session' {
    interface SessionData
    {
        loggedIn: boolean;
    }
}

class App
{
    express = Express();

    start()
    {
        let session = Session( { secret: "my-secret", /* options? */ } );
        this.express.use( session );
        this.express.get( "/login", ( request, response ) => this.onLoginRequest( request, response ) );
        this.express.get( "/products", ( request, response ) => this.onProductsRequest( request, response ) );
        this.express.listen( 3000, () => this.requestLogin() );
    }

    // =================================== Login

    requestLogin()
    {
        fetch( 'http://localhost:3000/login', { /* options? */ } )
            .then( result => this.showProducts() );
    }

    onLoginRequest( request: Express.Request, response: Express.Response )
    {
        console.log( "Login session ID: " + request.session.id );
        request.session.loggedIn = true;
        response.send( "Login OK" );
    }

    // =================================== Products

    showProducts()
    {
        fetch( 'http://localhost:3000/products', { /* options? */ } )
            .then( result => this.onProducts( result ) );
    }

    onProductsRequest( request: Express.Request, response: Express.Response )
    {
        console.log( "Products session ID: " + request.session.id );
        if( !request.session.loggedIn )
            response.send( "Error: Not logged in" );
        else
            response.send( "Apple, Orange, Pear" );
    }

    onProducts( result: any )
    {
        result.text()
            .then( ( text: string ) => console.log( "Products response: " + text ) );
    }
}

( new App() ).start();

推荐答案

在浏览器中,将此选项添加到您的fetch()呼叫:

{ withCredentials: true }

否则,fetch()可能不会随请求一起发送Cookie.如果没有Cookie,就不会连接到现有会话,因此Express会在每个新请求上创建一个新的空会话.

如果您使用的是node-fetch()服务器端,那么您将需要某种类型的cookie jar来收集和保留从一个请求到下一个请求的cookie.与浏览器不同,NodeJS不会为您收集和跟踪cookie.对于node-fetch代码,有一个module node-fetch-cookies可以做到这一点.您还可以手动收集响应返回的Cookie,然后在下一个请求中发送回该Cookie(与浏览器相同).

Javascript相关问答推荐

React Native平面列表自动滚动

我试图实现用户验证的reduxstore 和操作中出了什么问题?

将状态向下传递给映射的子元素

colored颜色 检测JS,平均图像 colored颜色 检测JS

MathJax可以导入本地HTML文档使用的JS文件吗?

如何用拉威尔惯性Vue依赖下拉?

IF语句的计算结果与实际情况相反

如何在不影响隐式类型的情况下将类型分配给对象?

未加载css colored颜色 ,无法将div设置为可见和不可见

VSCode中出现随机行

将异步回调转换为异步生成器模式

如何 for each 输入动态设置输入变更值

Next.js中的服务器端组件列表筛选

JS Animate()方法未按预期工作

我想使用GAS和HTML将从Electron 表格中获得的信息插入到文本字段的初始值中

如何根据输入数量正确显示alert ?

调用特定数组索引时,为什么类型脚本不判断未定义

为什么当雪碧的S在另一个函数中时,Phaser不能加载它?

使用Perl Selify::Remote::Driver执行Java脚本时出错

检测带有委托的元素内部的点击,以及元素何时按其类名被选中