我有一个QR码onRequest
谷歌云函数,运行在第二代。我正在使用qrcode package生成简单的QR码,就像你在这里看到的一样。
第二代GCF能够处理大量的呼叫。然而,虽然大多数QR码返回到调用程序,但许多QR码返回为黑色正方形,而不是QR码,然后在GCF日志中,我看到以下消息:
截断响应体。通常意味着请求超时或应用程序在响应完成之前退出。
正如你在下面的代码中所看到的,我有一个示例总是在运行,有足够的处理能力,并且应该没有超时问题来动态生成这些超级简单的QR码png。
在1,000个调用中,只有大约5%的结果是黑色方块和Truncated response
消息。
我想知道我是否有某种承诺的问题,而不是等待'ing适当?也想知道,是什么产生了这个截断消息?GCF跟踪没有给予更多细节。
注意:发送到QR码中编码的数据始终是相同的格式,即int。
GCF的qrCode.ts脚本
import { onRequest } from 'firebase-functions/v2/https'
import { logger } from 'firebase-functions/v2'
import QRCode from 'qrcode'
import express from 'express'
import cors from 'cors'
import { kDebug } from './lib/constants'
import { normalizedSku } from './lib/helperFunctions'
const app = express()
// Automatically allow cross-origin requests
app.use(cors({ origin: true }))
// Support json encoded bodies and url encoded bodies
app.use(express.urlencoded({ extended: true }))
// Save the qrcode to memory in GCF and return as a file
const filepath = '/tmp/qrcode.png'
/**
* Save the QR code to file.
* @param {string} qrCodePlainText The plain text that makes up QR code.
* @param {unknown} options The QR code package options.
* @return {boolean} Whether the QR code was saved to file.
*/
async function saveQrCodeToFile(qrCodePlainText: string, options: unknown): Promise<boolean> {
try {
await QRCode.toFile(filepath, qrCodePlainText, options)
return true
} catch (error) {
logger.error(error)
return false
}
}
/**
* QR Code image generator. The value in GET will be decoded and set as the plain text in the
* generated qr code, which is returned as a png.
*
* https://github.com/soldair/node-qrcode
*/
app.get('/qrCode/:data', async (req, res) => {
let qrCodeData = req.params.data
// Inches, e.g. a value of 1 will result in a 1"x1" qrcode. The max is 10.
const inchesParam = req.query.inches
const returnToDataUrl = req.query.returnToDataUrl === 'true'
const isSku = req.query.isSku === 'true'
try {
if (kDebug) {
logger.info('req.params', req.params)
logger.info('req.query', req.query)
}
if (!qrCodeData) {
throw Error('Missing QR Code data param')
}
if (!inchesParam) {
throw Error('Missing inches param')
}
// Will return NaN if not a number
const inches = parseFloat(inchesParam as string)
if (isNaN(inches)) {
throw Error(`${inchesParam} is not a number`)
}
if (kDebug) {
logger.info(`QR Code dimensions: ${inches}"x${inches}"`)
}
if (inches > 10) {
throw Error('Inches param cannot be greater than 10')
}
// If this is a sku then normalize the data
if (isSku) {
qrCodeData = normalizedSku(qrCodeData)
}
const options = {
margin: 2,
}
// Convert inches to pixels for digital devices. 1" = 96px
options['width'] = Math.round(inches * 96)
if (kDebug) {
logger.info(options)
}
const qrCodePlainText = decodeURIComponent(qrCodeData)
if (returnToDataUrl) {
res.send(await QRCode.toDataURL(qrCodePlainText))
return
} else {
if (!(await saveQrCodeToFile(qrCodePlainText, options))) {
throw Error(`QR code failed for ${qrCodeData}.`)
}
res.sendFile(filepath)
}
} catch (e) {
if (kDebug) {
logger.error(e)
}
res.status(400).send(e.toString())
}
})
exports.endpoint = onRequest(
{ timeoutSeconds: 60, region: ['us-east4'], memory: '2GiB', minInstances: 1 },
app,
)
1条答案
按热度按时间ecbunoof1#
toFile不返回promise。它使用了一个回调API,并且您没有指定回调,因此您的代码会继续尝试在完成写入之前发送文件。