简体   繁体   English

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

[英]Error: This is caused by either a bug in Node.js or incorrect usage of Node.js internals

I was creating authentication mechanism for my service.我正在为我的服务创建身份验证机制。 And at some moment I had problem with cookies.在某个时刻,我遇到了 cookies 的问题。 More you can find here , so I solved this.更多你可以在这里找到,所以我解决了这个问题。

The problem was that I was trying to send cookie through 2 requests.问题是我试图通过 2 个请求发送 cookie。 My Next.js front-end sends request to its internal API, and only then, internal API sends this request to back-end.我的Next.js前端向其内部 API 发送请求,然后,内部 API 才将此请求发送到后端。

The solution of this problem was very easy, what I had to do - is to set cookie on back-end and return it in headers.这个问题的解决方案很简单,我要做的就是在后端设置 cookie 并在 headers 中返回它。 Here is how flow looks, like.这是流程的外观。

This is how it looks like, endpoint in Next.js front-end.这就是它的样子, Next.js前端的端点。 Except of data in response, it receives header, where cookie is set (response from back-end) and send it in header of response, that will be send on front-end, where cookie will be set:除了响应中的数据,它接收 header,其中设置了 cookie(来自后端的响应)并在响应的 header 中发送,该响应将在前端发送,其中将设置 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);
  }
}

And endpoint on back-end:和后端端点:

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);
}

And here is the problem, because of this Response class of express I keep getting this warning:这就是问题所在,因为express的这个Response class 我不断收到这个警告:

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)

It is definitely because of how this signIn function looks like, because I was trying to return just like this - return this.userService.signIn(signInUserDto) - and it worked, but I can't cookie in this case.这绝对是因为这个signIn function 的样子,因为我试图像这样返回 - return this.userService.signIn(signInUserDto) - 它有效,但在这种情况下我不能 cookie。

So, my question is - what is this error?所以,我的问题是 - 这个错误是什么? Can I just ignore it?我可以忽略它吗? If not, then how can I fix it?如果没有,那我该如何解决?

Thanks in advance!提前致谢!

TL;DR TL;博士

Finally, I was able to fix this error, first of all, as I said, my goes through 2 API's, from back-end to front-end API, and only then, this front-end API sends this request to actual front-end.最后,我能够修复这个错误,首先,正如我所说,我经历了 2 个 API,从后端到前端 API,然后这个前端 API 才会将此请求发送到实际前端结尾。

So, what I did, is just returned 2 tokens - refresh and access - as body.所以,我所做的只是返回了 2 个令牌 - 刷新和访问 - 作为正文。

@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);
}

Then, on front-end, I installed cookie and @types/cookie and in this front-end endpoint, in headers, I just serialized this refresh token from body payload, and removed from it.然后,在前端,我安装了cookie@types/cookie ,在这个前端端点的 headers 中,我只是从 body 有效负载中序列化了这个刷新令牌,并从中删除。

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);
  }
}

And it works perfectly fine, I don't have this Node.js error any more because of response with Express response class, and I'm able to set cookie.它工作得很好,我不再有这个Node.js错误,因为Express响应 class 的响应,我可以设置 cookie。

EDIT编辑

I have improved this code in even better way by using fastify and in the whole pipeline cookie is set in header.我通过使用fastify以更好的方式改进了这段代码,并且在整个管道中 cookie 设置在 header 中。 First of all, on back-end install @fastify/cookie and @nestjs/platform-fastify .首先,在后端安装@fastify/cookie@nestjs/platform-fastify Then, add this in file, where you start you Nest.js app:然后,将其添加到文件中,您将在其中启动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'
  });

This will allow you to use FastifyReply from fastify , this will eliminate this Node.js error as response class:这将允许您使用来自FastifyReplyfastify这将消除此Node.js错误作为响应 class:

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);
  }
...

And the last step, on front-end endpoint, using cookie , parse this cookie and send it to front.最后一步,在前端端点上,使用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)

And this is the best way, that I've found, because it allows you to send cookie in header though all pipeline, not in body and then delete it, and this solution eliminates this strange Node.js error.这是我发现的最好方法,因为它允许您通过所有管道发送 header 中的 cookie,而不是在正文中然后删除它,并且此解决方案消除了这个奇怪Node.js错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM