Firebase Cloud功能在收到204响应代码后挂起



我正在编写一个云函数来启动或停止我正在使用的游戏面板的服务器。除了当请求完成时,它从未触发导致Firebase挂起的"数据"、"结束"或"关闭"事件之外,其他一切都正常工作。其他人以前遇到过这种情况吗?我在谷歌上搜索了"收到204响应后节点http挂起",但没有发现任何相关内容。

import * as functions from "firebase-functions";
import * as http from "https";
import * as qs from "querystring";
export const commandServer = functions.https.onRequest((request, response) => {
if (request.body.command !== "start" && request.body.command !== "stop") {
response.status(400).send("Error, missing information.");
}
console.log(request.body.origin);
const apiKey = "<apiKey>";
const panelServerId = "<panelId>";
const data = qs.stringify({
signal: request.body.command === "start" ? "start" : "stop",
});
const options = {
protocol: "https:",
hostname: "<server url>",
port: 443,
path: `/api/client/servers/${panelServerId}/power?`,
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Content-Length": data.length,
Authorization: `Bearer ${apiKey}`,
},
};
const req = http.request(options, (res) => {
console.log(`statusCode: ${res.statusCode}`);
res.on("data", () => {
response.status(200).send(`Successfuly sent ${data} command`);
});
});
req.on("error", (error) => {
console.log("error: ", error);
response.status(500).send("Oops, something went wrong!");
});
req.write(data);
req.end();
});

我认为应该使用一个返回Promises的库,而不是https库,比如axios(另请参阅samthecodingman在评论中提到的其他选项(。

以下修改,使用axios,应该可以做到这一点(未经测试(:

import * as functions from "firebase-functions";
import * as axios from "axios";
import * as qs from "querystring";

export const commandServer = functions.https.onRequest((request, response) => {
if (request.body.command !== "start" && request.body.command !== "stop") {
response.status(400).send("Error, missing information.");
}
console.log(request.body.origin);
const apiKey = "<apiKey>";
const panelServerId = "<panelId>";
const data = qs.stringify({
signal: request.body.command === "start" ? "start" : "stop",
});
const options = {
url: "<server url>",   //Assign the absolute url with protocol, host, port, path, etc... See the doc https://github.com/axios/axios#request-config
method: "post",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Content-Length": data.length,
Authorization: `Bearer ${apiKey}`,
},
};
axios.request(options)
.then(res => {
console.log(`statusCode: ${res.statusCode}`);
response.status(200).send(`Successfuly sent ${data} command`);
})
.catch(err => {
console.log("error: ", error);
response.status(500).send("Oops, something went wrong!");        
})
});

204 No Content响应没有任何内容,因此不会激发任何"data"事件。相反,您应该监听"end"事件。

此外,当返回的数据流式传输时,可能会触发多个"data"事件。每个流式传输的数据块在使用之前都应该与其他块组合,例如将每个块附加到字符串、文件或通过数据管道。

以下是一个基于http.get(...)文档的更正示例:

const req = http.request(options, (res) => {
console.log(`statusCode: ${res.statusCode}`);
res.setEncoding('utf8');
let rawData = '';
res.on('data', (chunk) => { rawData += chunk; });
res.on('end', () => {
if (!res.complete) {
// connection lost before complete response was received
response.status(500).send('The connection to the server was terminated while the command was still being sent.');
return;
}
if (res.statusCode < 200 || res.statusCode >= 300) {
// unexpected status code
response.status(500).send('Server responded unexpectedly.');
return;
}
if (rawData === '') {
// no body recieved
response.status(200).send(`Successfuly sent ${data} command and got a ${res.statusCode} response without a body`);
return;
}
// try to parse body as JSON
try {
const parsedData = JSON.parse(rawData);
console.log(`Server gave a ${res.statusCode} response. JSON body: `, parsedData);
response.status(200).send(`Successfuly sent ${data} command and got a ${res.statusCode} response with data: ${JSON.stringify(parsedData)}`);
} catch (error) {
// JSON parse error
console.error(`Failed to parse response body as JSON`, { statusCode: res.statusCode, error, rawData });
response.status(500).send(`Successfuly sent ${data} command and got a ${res.statusCode} response, but the response body could not be parsed as JSON.`);
}
});
});

但正如@Renaud在他们的回答中所提供的那样,使用第三方请求库为您处理细节通常更简单。建议选择一个围绕Promises构建的库,因为这些库在云函数中运行良好。避免使用基本httphttps库的另一个原因是,在查看代码时,处理称为req/requestres/response的多个对象可能会导致混乱。

相关内容

  • 没有找到相关文章

最新更新