路由器处理程序返回一个对象数组,但客户端没有在 json 中获取它们,尽管响应为 200 状态

Posted

技术标签:

【中文标题】路由器处理程序返回一个对象数组,但客户端没有在 json 中获取它们,尽管响应为 200 状态【英文标题】:router handler returns an array of object but client doesn't get them in json though response with 200 status 【发布时间】:2021-09-30 01:20:41 【问题描述】:

我正在使用 Typescript 实现一个 express.js 项目。

我定义了一个enum 和一个interface

export enum ProductType 
    FOOD = 'food',
    CLOTH = 'cloth',
    TOOL = 'tool'


export interface MyProduct 
    type: ProductType;
    info: 
        price: number;
        date: Date;
    ;

我的一个路由器处理程序需要将MyProduct 的数组返回给客户端。我试过这个:

const productArr: MyProduct[] = // call another service returns an array of MyProduct
app.get('/products', (req, res) => 
    res.status(200).send(products: productArr);
);

我使用 Postman 测试了这个端点,它以状态 200 响应,但使用默认 html 页面而不是 JSON 中的对象数组。

我错过了什么?是不是因为express.js无法自动解析enuminterface为json对象??

附:我已经设置了 json 解析器,所以不是这样,其他端点可以正常使用 json 响应:

const app = express();
app.use(express.json());
...

【问题讨论】:

我认为你应该使用json而不是send 您在此处发布的代码应该可以正常工作,至少在最新的 expressjs 中是这样。您获得默认页面的事实可能表明此特定路线存在问题。也可能是中间件的一些无意交互。你有吗? @AhmetŞimşek ,send 不是原因,因为我的其他端点也使用send 没有这样的问题。 这个问题肯定与 Typescript 无关。出于调试目的,只需注释掉处理程序中的所有内容,添加一个简单的 console.log() 并检查是否正在调用端点。在我看来,路线有问题(中间件或路线重叠) 你确定productArr 是一个数组吗?因为如果某些服务返回这个值 - 它可能是未解决的承诺 【参考方案1】:

由于缺少完整的响应标头和服务器环境假设您使用的是带有反向代理的 AWS 服务。因此,这里列出的可能性可能很少需要考虑:

如果路由器处理程序返回一个对象数组,但客户端没有在 json 中获取它们,尽管响应为 200 状态,那么可能有一个 反向代理充当后端服务器,为未知的状态代码提供默认内容 200来自客户端的路由。因此,在这种情况下,您需要在反向代理服务器中将新路由列入白名单,假设您使用 AWS Amplify 进行 API 重写和重定向,那么您需要在 AWS amplify settings 中将此路由列入白名单,或者否则它将提供默认内容,就像在当前场景中发生的那样。

如果问题仍然存在,那么:

确保您的服务器上有正确的 CORS 规范。

确保productArr 是服务返回的数组,因为如果某些服务返回此值 - 它可能是未解决的承诺。因此,适当的测试用例将在此处为您提供帮助或出于调试目的在您的环境中设置 DEBUG=* 并确保它应按预期返回值。

检查使请求短路的另一个路由:当 Express 路由发送对象时您看到的是 HTML 页面这一事实可能表明您的请求与不同的路由匹配。寻找包罗万象的路由,例如出现在您的路由上方的非中间件 app.use() 或通配符路由。

【讨论】:

【参考方案2】:

如 cmets 中所述,您的代码应该可以工作。我将列出一些可用于尝试找出问题的步骤。

显示调试信息

在您的环境中设置DEBUG=*DEBUG 是一个环境变量,用于控制许多 Node 模块的日志记录。您将能够通过 Express 看到请求的流程。如果信息太多,您可以像这样限制输出:DEBUG=*,-babel,-babel:*,-nodemon,-nodemon:*,-router:layer,-follow-redirects,-send(使用逗号分隔的列表并在您要排除的任何模块前面放置一个-

这应该可以帮助您通过各种路由器和路由跟踪请求的生命周期。你现在可以...

检查另一个正在短路请求的路由

当 Express 路由发送对象时,您看到的是 HTML 页面这一事实可能表明您的请求正在匹配不同的路由。寻找包罗万象的路由,例如非中间件 app.use() 或出现在您的路由上方的通配符路由。

其他建议

不要显式设置状态

添加.status(200) 代码较多且不必要。

使用res.json()

使用.json() 而不是.send()。 If 将始终添加Content-Type: application/json 标头,而.send() 在无法确定内容类型时不会添加(例如.send(null).send('hello') 不会将Content Type 标头设置为application/json,这可能会混淆客户端)。

【讨论】:

以上是关于路由器处理程序返回一个对象数组,但客户端没有在 json 中获取它们,尽管响应为 200 状态的主要内容,如果未能解决你的问题,请参考以下文章

#2 中间件, 路由,router,https

Cjson 处理返回的对象数组

使用 useQuery 进行批处理反应钩子返回未定义

频繁的GET请求停止实际处理HTTP处理程序/离开返回相同的值

jquery:为啥选择器返回我一个数组,但属性没有?

猫鼬不将对象插入数组