错误:这是由Node.js中的错误或Node.js内部使用不正确引起的



我正在为我的服务创建身份验证机制。有一段时间我对饼干有意见。你可以在这里找到更多,所以我解决了这个问题。

问题是我试图通过两个请求发送cookie。我的Next.js前端将请求发送到其内部API,然后内部API将此请求发送到后端。

这个问题的解决方案非常简单,我必须做的就是在后端设置cookie并在头文件中返回。以下是流动的样子。

这就是它的样子,Next.js前端中的端点。除了响应中的数据外,它接收设置cookie的标头(来自后端的响应(,并将其发送到响应的标头中,该标头将在前端发送,设置cookie:

import { NextApiRequest, NextApiResponse } from "next";
import { AxiosError } from "axios";
import { api } from "../../../api";
export default async (
req: NextApiRequest,
res: NextApiResponse
) => {
try {
const { data, headers } = await api.post('/user/sign-in', req.body)
if (headers["set-cookie"]) {
res.setHeader("Set-Cookie", headers["set-cookie"]);
}
return res.json(data)
} catch (error) {
return res
.status((error as AxiosError).response?.status as number)
.json((error as AxiosError).response?.data);
}
}

后端端点:

import { Response as Res } from 'express';
import * as dayjs from 'dayjs';
...
async signIn(@Body() signInUserDto: SignInUserDto, @Response() res: Res) {
const { _at, _rt } = await this.userService.signIn(signInUserDto);
res.cookie('_rt', _rt, {
httpOnly: true,
expires: dayjs().add(7, 'days').toDate()
});
return res.send(_at);
}

问题是,由于expressResponse类,我一直收到警告:

Error: This is caused by either a bug in Node.js or incorrect usage of Node.js internals.
Please open an issue with this stack trace at https://github.com/nodejs/node/issues
at new NodeError (node:internal/errors:371:5)
at assert (node:internal/assert:14:11)
at ServerResponse.detachSocket (node:_http_server:249:3)
at resOnFinish (node:_http_server:819:7)
at ServerResponse.emit (node:events:390:28)
at onFinish (node:_http_outgoing:830:10)
at callback (node:internal/streams/writable:552:21)
at afterWrite (node:internal/streams/writable:497:5)
at afterWriteTick (node:internal/streams/writable:484:10)
at processTicksAndRejections (node:internal/process/task_queues:82:21)

这肯定是因为这个signIn函数的样子,因为我试图像这样返回return this.userService.signIn(signInUserDto),它成功了,但在这种情况下我不能cookie。

所以,我的问题是——这个错误是什么?我可以忽略它吗?如果没有,我该如何修复?

提前感谢!

TL;DR

最后,我修复了这个错误,首先,正如我所说,我通过了2个API,从后端到前端API,然后,这个前端API将这个请求发送到实际的前端。

所以,我所做的只是返回两个令牌——刷新和访问——作为主体。

@ApiOperation({ summary: 'Resource for sign in user.' })
@ApiResponse({ status: 200, type: TokensDto })
@Post('/sign-in')
async signIn(@Body() signInUserDto: SignInUserDto) {
return this.userService.signIn(signInUserDto);
}

然后,在前端,我安装了cookie@types/cookie,在这个前端端点中,在头文件中,我只是从主体负载中序列化了这个刷新令牌,并将其删除

import { NextApiRequest, NextApiResponse } from "next";
import { AxiosError } from "axios";
import { api } from "../../../api";
import { serialize } from 'cookie';
export default async (
req: NextApiRequest,
res: NextApiResponse
) => {
try {
const { data } = await api.post('/user/sign-in', req.body)
res.setHeader('Set-Cookie', serialize(
'_rt',
data._rt,
{ path: '/', httpOnly: true })
);
delete data._rt
return res.json(data)
} catch (error) {
return res
.status((error as AxiosError).response?.status as number)
.json((error as AxiosError).response?.data);
}
}

它工作得很好,因为Express响应类的响应,我再也没有Node.js错误了,而且我可以设置cookie。

编辑

我通过使用fastify以更好的方式改进了这段代码,并且在整个管道中,cookie设置在头中。首先,在后端安装@fastify/cookie@nestjs/platform-fastify。然后,将其添加到文件中,在文件中启动Nest.js应用程序:

import {
FastifyAdapter,
NestFastifyApplication
} from '@nestjs/platform-fastify';
import { fastifyCookie } from '@fastify/cookie';
async function bootstrap() {
const PORT = process.env.PORT || 3002;
const app = await NestFactory.create<NestFastifyApplication>(
AppModule,
new FastifyAdapter()
);
await app.register(fastifyCookie, {
secret: 'my-secret'
});

这将允许您使用fastify中的FastifyReply这将消除此Node.js错误作为响应类:

import { FastifyReply } from 'fastify';
@ApiTags('User')
@Controller('user')
export class UserController {
constructor(private userService: UserService) {}
@Post('/sign-in')
async signIn(
@Body() signInUserDto: SignInUserDto,
@Res({ passthrough: true }) res: FastifyReply
) {
const { _at, _rt } = await this.userService.signIn(signInUserDto);
res.setCookie('_rt', _rt);
return res.send(_at);
}
...

最后一步,在前端端点上,使用cookie解析此cookie并将其发送到前端。

const { data, headers } = await api.post('/user/sign-in', req.body)
if (headers["set-cookie"]) {
const refreshToken = headers["set-cookie"][0].split('=')[1];
res.setHeader('Set-Cookie', serialize(
'_rt', refreshToken, { path: '/', httpOnly: true })
);
}
return res.json(data)

这是我发现的最好的方法,因为它允许您通过所有管道而不是主体在头中发送cookie,然后删除它,这个解决方案消除了这个奇怪的Node.js错误。

最新更新