在Firebase可调用云函数中使用Puppeteer如何避免CORS错误
代码核心问题分析
- 混用了Firebase两种云函数的语法:
functions.https.onCall()是可调用云函数,专门对接Firebase客户端SDK,Firebase官方会自动处理CORS逻辑,不需要手动引入cors中间件。该接口的入参只有data和context,不存在req、res参数,你强行套cors(req, res, ...)的写法完全不符合可调用函数的规范,这是触发CORS报错的直接原因。 - Puppeteer的执行逻辑没有正确返回Promise,云函数会在异步逻辑执行完成前提前销毁实例,就算CORS问题修复也无法正常完成截图。
- 云函数是无图形界面的服务端环境,
headless: false配置完全无法运行,需要改为无头模式,同时要补充Puppeteer在容器环境运行必须的启动参数,否则会启动失败。 - 截图保存到
example.png没有意义,云函数的本地磁盘是临时的,执行结束后文件就会被销毁,如果需要返回截图,应该转成base64或者上传到云存储。
修正后的可调用函数代码
const functions = require('firebase-functions'); const puppeteer = require('puppeteer'); exports.takePic = functions.https.onCall(async (data, context) => { // 可调用函数不需要手动加CORS中间件,Firebase自动处理 const url = data.url; if (!url) { throw new functions.https.HttpsError('invalid-argument', '缺少url参数'); } let browser; try { browser = await puppeteer.launch({ args: [ '--no-sandbox', '--disable-setuid-sandbox', '--disable-web-security', '--disable-features=IsolateOrigins', '--disable-site-isolation-trials' ], headless: 'new', }); const page = await browser.newPage(); await page.goto(url, { waitUntil: 'networkidle2' }); // 截图转base64返回给前端,不要存在本地临时磁盘 const screenshotBase64 = await page.screenshot({ encoding: 'base64' }); await browser.close(); // 正常返回结果,可调用函数会自动处理响应头避免CORS return { success: true, image: `data:image/png;base64,${screenshotBase64}` }; } catch (err) { if (browser) await browser.close(); throw new functions.https.HttpsError('internal', '截图执行失败', err.message); } });
额外注意事项
- 如果你是用普通HTTP请求(不是Firebase客户端SDK)调用这个接口,应该把
onCall改成onRequest,再用你原来的cors中间件写法,两种函数的调用规范完全不同不要混用。 - Puppeteer依赖体积较大,部署时要注意云函数的内存配置,建议至少配置1GB内存避免实例崩溃。
内容的提问来源于stack exchange,提问作者MacD
相关产品推荐
相关产品推荐

