【发布时间】:2021-07-29 04:04:34
【问题描述】:
我正在使用谷歌云功能从 Firestore 获取令牌,检查它是否仍然处于活动状态,如果是则返回访问令牌。其他:
- 从 secretmanager 获取刷新令牌
- 刷新
- 在 Secret Manager 中更新刷新令牌
- 在 Firebase 中更新访问令牌
现在我有时会收到此错误...此函数至少每 15 分钟从不同的云函数调用一次。错误每天发生 5 次。我看过this 的帖子,但无法将其转换为我的代码。
错误:
FetchError: request to https://europe-west1-project.cloudfunctions.net/getToken failed, reason: socket hang up
at ClientRequest.<anonymous> (/workspace/node_modules/node-fetch/lib/index.js:1461:11)
at ClientRequest.emit (events.js:315:20)
at ClientRequest.EventEmitter.emit (domain.js:467:12)
at TLSSocket.socketOnEnd (_http_client.js:493:9)
at TLSSocket.emit (events.js:327:22)
at TLSSocket.EventEmitter.emit (domain.js:529:15)
at endReadableNT (internal/streams/readable.js:1327:12)
at processTicksAndRejections (internal/process/task_queues.js:80:21)
代码:
const { SecretManagerServiceClient } = require("@google-cloud/secret-manager");
const client = new SecretManagerServiceClient();
const name = `projects/${process.env["PROJECT"]}/secrets/TOKEN/versions/latest`;
const axios = require("axios");
const milliseconds = new Date().getTime()
const now = Math.round(milliseconds / 1000);
const { Firestore } = require("@google-cloud/firestore");
const firestore = new Firestore();
const tokens = firestore.collection("tokens");
module.exports = async function getToken() {
let responseData;
await tokens.where("system", "==", "x").limit(1).get()
.then((res) => {
res.forEach((snap) => {
responseData = snap.data();
});
})
.catch((err) => {
console.error(JSON.stringify(err));
});
console.log(`custom_log: now = ${now}`)
console.log(JSON.stringify(responseData))
if (now - responseData.timestamp < 250) {
console.log(`custom_log: Returning access token from Firebase`)
return responseData.access_token;
} else {
console.log(`custom_log: Return new access token`)
return await refreshToken();
}
};
async function refreshToken() {
const [version] = await client.accessSecretVersion({ name: name });
const secret = version.payload.data.toString();
const config = {
method: "post",
url: "https://login.webpage.com/token?grant_type=client_credentials",
headers: {
Authorization: `Basic ${secret}`,
},
};
return axios(config)
.then((response) => {
updateAccesToken(response.data.access_token)
return response.data.access_token;
})
.catch((error) => {
console.error(`custom_error: Error refresh token: ${error.message}`);
});
}
async function updateAccesToken(token) {
await tokens.doc('token').update({
timestamp: now,
access_token: token,
dateTime: new Date(milliseconds).toISOString()
})
console.log('custom_log: access_token updated in Firestore')
}
【问题讨论】:
-
对于 HTTP 触发的云函数 require the response to be sent,否则您应该确保返回正确的 Promise 以终止函数,您的
return responseData.access_token;是否被正确调用? (这似乎不是一个有效的承诺)。我无法调试它,因为您对多个服务的多次调用可能会失败并返回错误的响应,我建议重构您的代码以返回正确的值(预计会有 Promise,而不仅仅是将其记录到控制台)
标签: node.js google-cloud-firestore google-cloud-functions