You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Firebase云函数调用时因目标URL协议错误引发CORS问题的捕获与处理求助

Firebase云函数调用时因目标URL协议错误引发CORS问题的捕获与处理求助

我最近碰到了一个棘手的问题:当用户传入的目标URL本该使用http协议却误写成https时,我的Firebase云函数在调用fetch、extract(来自@extractus/oembed-extractor)和getLinkPreview(来自link-preview-js)这几个方法时,会触发CORS错误。更麻烦的是,这个错误既没在服务端的try/catch里被捕获,客户端的异常处理也抓不到它。

我的Firebase云函数代码(服务端)

export const getPreviewData = onCall(async (request) => {

  if (!request.auth) return {
    sucess:false,
    message:'request not authorized'
  }

  const { url } = request.data;

  let err, status;
  try {
    const response = await fetch(url);
    status = await response.status;

  } catch (e) {
      const error:Error = e as Error
      err = error.message;
  }
...
  const oEmbedData = extract(url)
...
  const OGData = getLinkPreview(url)
...
}

客户端控制台的CORS错误信息

Access to fetch at 'https://us-central1-workboxes-dev.cloudfunctions.net/getPreviewData' from origin 'https://workboxes-dev.web.app' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

客户端调用云函数的代码

const functions = getFunctions()
const fetchPreviewData = httpsCallable(functions, 'getPreviewData')

try {
    const previewData = await fetchPreviewData({url})
    console.log('previewData', previewData)
} catch(error) {
    console.log('error fetching weblink data',error.message)
}

正常情况下,只要URL协议正确,整个流程都能顺畅运行。但这是面向用户的界面,我必须能捕获到这种协议错误,这样才能自动把错误的https替换成正确的http来解决问题。

我最终的解决方法

后来我想到,先用fetch对传入的URL做一层校验过滤,把有协议问题的URL处理好之后,再安全地调用另外两个方法。具体代码如下:

const { url, eooptions, ogoptions } = request.data;

  let err = 'no error', response, ok = false, status,
    selectedURL = url, modifiedprotocol

  // 先校验传入的URL
  try {
    response = await fetch(selectedURL);
    status = response.status;
    ok = response.ok
  } catch (e) {
    const error:Error = e as Error
    err = error.message;
    const urlData = new URL(selectedURL);
    if (urlData.protocol == 'https:') {
      err = 'no error'
      selectedURL = 'http://' + urlData.hostname + urlData.pathname
      modifiedprotocol = 'http:'
      try {
        response = await fetch(selectedURL);
        status = response.status;
        ok = response.ok;
      } catch (e) {
        const error:Error = e as Error
        err = error.message;
      }
    }
  }

  if (!ok) {
    return {
      status,
      ok,
      err,
      selectedURL
    }
  }

// 现在可以安全地调用extract和getLinkPreview了
...

备注:内容来源于stack exchange,提问作者HenrikBechmann

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 18:59:30