为啥我从托管在 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 托管网站的请求