为啥我从托管在 Firebase 上的 NextJs 应用程序仅针对 POST 请求收到“502 网关”错误?

Posted

技术标签:

【中文标题】为啥我从托管在 Firebase 上的 NextJs 应用程序仅针对 POST 请求收到“502 网关”错误?【英文标题】:Why do I get a "502 Gateway" error from NextJs app hosted on Firebase for POST requests only?为什么我从托管在 Firebase 上的 NextJs 应用程序仅针对 POST 请求收到“502 网关”错误? 【发布时间】:2021-01-06 04:07:48 【问题描述】:

我开始使用 NextJs 框架构建 API。我希望它托管在 Firebase (托管和功能) 上。只要我只发送 GET 请求,一切正常。当我发送 POST 请求时,我收到 “502 Bad Gateway” 错误。

复制非常简单。您只需下载并部署 NextJs 开发团队提供的示例即可。

在Firebase 控制台上创建一个新项目

安装“with Firebase hosting”示例

更改.firebaserc (line 3)文件中的项目名称

在文件夹"pages"

下创建一个文件夹"api"

在文件夹"api"下创建一个文件"hello.js"并添加如下sn-p

export default async (req, res) => 
  const 
    body,
    method
   = req;

  console.log("method :>> ", method);
  console.log("body :>> ", body);

  switch (method) 
  case "POST":
    res.status(200).end(`Method $method supported!`);
    break;
  default:
    res.setHeader("Allow", ["POST"]);
    res.status(405).end(`Method $method Not Allowed`);
  
;

部署应用程序

向“https://[project-name].web.app/api/hello”发送 GET 请求并查看它是否有效

向“https://[project-name].web.app/api/hello”发送 POST 请求,发现它不起作用

你有和我一样的错误吗?

我花了 2 天时间阅读文章、观看视频并尝试不同的配置。您甚至可以更新 firebaseFunctions 以添加 console.log 并查看 POST 请求被 Firebase Cloud Function 捕获,但 NextJs 服务器不会像 GET 请求那样将其传递给我们的 API。这超出了我的技能范围......

低于你应该有的输出。 POST 请求应以200 - Method POST is supported! 回答。

【问题讨论】:

我有另一个使用 ExpressJs 的项目,但我从未遇到过这个问题。 我倾向于认为这是由res.status(204).end(``Method $method supported!``); 引起的,而不是其他原因。请改用res.status(204).end(); @samthecodingman 如果您尝试一下,您会看到 Firebase Cloud Functions 上没有日志。这意味着该方法未被调用。我更新了 sn-p(感谢您的帮助!) 【参考方案1】:

追踪这件事真的很痛苦,但在我自己摸索了一段时间后,我发现 PUT 和 PATCH 请求也出现了同样的问题。这表明它与请求的正文有关。恼人的是,在发现这一点后,我偶然发现了Issue #7960 的线程,他们发现了同样的问题。

简单地说,请求的主体由https.onRequest()处理一次,然后nextjsHandle()尝试再次解析它。因为已经处理了主体,所以raw-body 模块(在nextjsHandle() 内)无限期地等待'data' 永远不会发生的事件。

目前还没有办法关闭https.onRequest()完成的body解析,所以必须在next.js端禁用。不幸的是,没有可以在next.config.js 中添加的用于正文解析的全局关闭开关,并且必须为每个 API 路由(pages/api 中的文件)完成(如果 @ 中建议的修复可能会改变) 987654322@已添加)。

要禁用给定路由的正文解析,请将以下内容添加到路由文件中

export const config = 
  api: 
    // disables call to body parsing module
    bodyParser: false,
  
;

但是,正如@rscotten 在Issue #7960 中提到的,您可能还希望在开发应用程序时使用next dev,因此您需要在使用next dev 时启用它,但在部署时禁用它。这可以使用

export const config = 
  api: 
    // disables call to body parsing module while deployed
    bodyParser: process.env.NODE_ENV !== 'production',
  
;

将这些更改应用于hello.js 会得到:

export default async (req, res) => 
  const 
    body,
    method
   = req;

  console.log("method :>> ", method);
  console.log("body :>> ", body);

  switch (method) 
  case "POST":
    res.status(200).end(`Method $method supported!`);
    break;
  default:
    res.setHeader("Allow", ["POST"]);
    res.status(405).end(`Method $method Not Allowed`);
  
;

export const config = 
  api: 
    // disable nextjs's body parser while deployed
    // (as body parsing is handled by `https.onRequest()`),
    // but enable it for local development using `next dev`
    bodyParser: process.env.NODE_ENV !== 'production',
  
;

【讨论】:

我看错了方向。我已经在 ExpressJs 应用程序中遇到了同样的问题,但我收到的错误很清楚,我可以很快解决它。当我看到你的回复时,我开始用 ExpressJs 替换 NextJs。非常感谢山姆的帮助! 还必须有 Firebase 托管配置问题。因为现在我在 Firebase Cloud Functions 上使用 Puppeteer 时出现“502 Bad Gateway”。 “goto”方法没有完成。在本地一切正常,在另一个项目中我可以毫无问题地使用 Puppeteer。不同之处在于我不会将所有请求重定向到 Next/Express 服务器,而只会重定向到“/api/**”下的请求。我正在调查它... 我错了,但不要删除我的评论,让我们保留 Express/Next 服务器网关问题后发生的事情的历史记录。我在通过服务器公开的 API 中使用 Puppeteer。我仍然收到502 - Bad Gateway 错误,因为在 Puppeteer 加载页面后它等待的时间太长了。我只是删除了“额外的”waitForNavigation 电话。在本地没有问题,但在 Firebase 上它阻止了我的脚本继续。

以上是关于为啥我从托管在 Firebase 上的 NextJs 应用程序仅针对 POST 请求收到“502 网关”错误?的主要内容,如果未能解决你的问题,请参考以下文章

将 .well-known/assetlinks.json 上传到 Mac 上的 Firebase 托管

Firebase 托管上的 Flutter 网站适用于域 1,但不适用于域 2

Firebase 托管单页应用程序上的深度路由问题

如何限制 Firebase 云功能仅接受来自 Firebase 托管网站的请求

从 Firebase 托管到 Firebase 功能的请求被 CORS 阻止

为啥我的 post 请求返回 405 错误? [复制]