【问题标题】:Only HTTP(S) protocols are supported Firebase Functions仅支持 HTTP(S) 协议 Firebase 函数
【发布时间】:2021-12-04 13:51:12
【问题描述】:

我已经复制了所有代码,包括来自 Resize Image Firebase Functions Extension 的依赖项。我在 Firebase 模拟器中运行它,需要对其进行调整以满足我的需求。但是,就目前而言,我将其设置为几乎与扩展程序的源代码完全相同。

分机网址:https://firebase.google.com/products/extensions/storage-resize-images

我的本地设置:
节点:v14.17.5
npm:7.23.0
火力基地:9.20.0

firebase 管理员:^9.11.1
firebase-functions": ^3.15.6
mkdirp: ^1.0.4
uuid:^8.3.2

扩展的依赖
firebase 管理员:^8.0.0
firebase 功能:^3.13.2
mkdirp: ^1.0.4
尖锐:0.23.4
uuidv4: ^6.1.0

这是调整图像大小的代码
请注意这一行:await remoteFile.download({ destination: originalFile }); // <- Offending line of code...,因为那是它失败的那一行。

const resizeImage = async (object): Promise<ResizedImageResult[]> => {
  logs.start();
  const { contentType } = object; // This is the image MIME type

  const tmpFilePath = path.resolve('/', path.dirname(object.name)); // Absolute path to dirname

  if (!contentType) {
    logs.noContentType();
    return;
  }

  if (!contentType.startsWith('image/')) {
    logs.contentTypeInvalid(contentType);
    return;
  }

  if (object.contentEncoding === 'gzip') {
    logs.gzipContentEncoding();
    return;
  }

  if (!supportedContentTypes.includes(contentType)) {
    logs.unsupportedType(supportedContentTypes, contentType);
    return;
  }

  if (config.includePathList && !startsWithArray(config.includePathList, tmpFilePath)) {
    logs.imageOutsideOfPaths(config.includePathList, tmpFilePath);
    return;
  }

  if (config.excludePathList && startsWithArray(config.excludePathList, tmpFilePath)) {
    logs.imageInsideOfExcludedPaths(config.excludePathList, tmpFilePath);
    return;
  }

  if (object.metadata && object.metadata.resizedImage === 'true') {
    logs.imageAlreadyResized();
    return;
  }

  const bucket = admin.storage().bucket(object.bucket);
  const filePath = object.name; // File path in the bucket.
  const fileDir = path.dirname(filePath);
  const fileExtension = path.extname(filePath);
  const fileNameWithoutExtension = extractFileNameWithoutExtension(filePath, fileExtension);
  const objectMetadata = object;

  let originalFile;
  let remoteFile: File;
  try {
    originalFile = path.join(os.tmpdir(), filePath);
    const tempLocalDir = path.dirname(originalFile);

    // Create the temp directory where the storage file will be downloaded.
    logs.tempDirectoryCreating(tempLocalDir);
    await mkdirp(tempLocalDir);
    logs.tempDirectoryCreated(tempLocalDir);

    // Download file from bucket.
    remoteFile = bucket.file(filePath);
    logs.imageDownloading(filePath);
    logs.imageDownloading(originalFile);
    await remoteFile.download({ destination: originalFile }); // <- Offending line of code...
    logs.imageDownloaded(filePath, originalFile);

    // Get a unique list of image types
    const imageTypes = new Set(config.imageTypes);

    // Convert to a set to remove any duplicate sizes
    const imageSizes = new Set(config.imageSizes);

    const tasks: Promise<ResizedImageResult>[] = [];

    imageTypes.forEach((format) => {
      imageSizes.forEach((size) => {
        tasks.push(
          modifyImage({
            bucket,
            originalFile,
            fileDir,
            fileNameWithoutExtension,
            fileExtension,
            contentType,
            size,
            objectMetadata: objectMetadata,
            format,
          }),
        );
      });
    });

    const results = await Promise.all(tasks);

    const failed = results.some((result) => result.success === false);
    if (failed) {
      logs.failed();
      return;
    } else {
      if (config.deleteOriginalFile === deleteImage.onSuccess) {
        if (remoteFile) {
          try {
            logs.remoteFileDeleting(filePath);
            await remoteFile.delete();
            logs.remoteFileDeleted(filePath);
          } catch (err) {
            logs.info('Catch 1');
            logs.errorDeleting(err);
          }
        }
      }
      logs.complete();
    }
  } catch (err) {
    logs.info('Catch 2');
    logs.error(err);
  } finally {
    if (originalFile) {
      logs.tempOriginalFileDeleting(filePath);
      fs.unlinkSync(originalFile);
      logs.tempOriginalFileDeleted(filePath);
    }
    if (config.deleteOriginalFile === deleteImage.always) {
      // Delete the original file
      if (remoteFile) {
        try {
          logs.remoteFileDeleting(filePath);
          await remoteFile.delete();
          logs.remoteFileDeleted(filePath);
        } catch (err) {
          logs.errorDeleting(err);
        }
      }
    }
  }
};

预期行为

当执行await remoteFile.download({ destination: originalFile }); 时,它应该下载原始文件。此代码与扩展代码完全相同。

实际行为

以下错误被注销:

{
  "severity":"ERROR","message":"Error when resizing image TypeError: Only HTTP(S) protocols are supported
    at getNodeRequestOptions (.../node_modules/teeny-request/node_modules/node-fetch/lib/index.js:1309:9)
    at .../node_modules/teeny-request/node_modules/node-fetch/lib/index.js:1410:19
    at new Promise (<anonymous>)
    at Function.fetch [as default] (.../node_modules/teeny-request/node_modules/node-fetch/lib/index.js:1407:9)
    at teenyRequest (.../node_modules/teeny-request/build/src/index.js:184:29)
    at Object.request (.../node_modules/teeny-request/build/src/index.js:241:20)
    at Timeout.makeRequest [as _onTimeout] (.../node_modules/retry-request/index.js:139:28)
    at listOnTimeout (internal/timers.js:557:17)
    at processTimers (internal/timers.js:500:7)"
}

有人遇到过这个问题吗?我无法返回到早期版本的 Firebase,因为存在重大更改。

【问题讨论】:

  • Remember 以简明扼要的摘要为您的帖子命名。
  • 我创建了一个测试用例。错误是不同的,但它在同一个地方中断:github.com/vdiaz1130/fb-resize-image-locally 请务必将您的项目添加到 .firebaserc 文件中。
  • 我和我的同事对此进行了测试,您在 GitHub 上发布的代码在部署时似乎运行良好。这是logs。再次检查您的设置,并确保您的依赖项与您的问题中所述的相匹配。
  • @RobertG 感谢您的测试。是的,我知道它在部署时有效。我希望让这个在模拟器中本地工作,因为我需要进行一些更改以满足我的需要。没有必要使用匹配的 dep 1. 因为它在部署时可以工作 2. 因为 Firebase v8 与 v9 发生了重大变化,而我正在使用 v9。
  • 由于这是您升级后模拟器内部的问题,建议您通过Firebase Tools Issue link提交您的问题。

标签: node.js firebase google-cloud-functions google-cloud-storage


【解决方案1】:

对于遇到此问题的其他人,我通过在以下行中将验证设置为 false 来修复它: await remoteFile.download({ destination: originalFile, validation: false });

我将添加逻辑以在不使用模拟器时打开验证。此外,请确保扩展的所有环境变量都具有默认值(请参阅扩展源代码中的 config.ts 文件,并查看 GCP 中函数详细信息页面中的变量选项卡)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-15
    • 2021-03-21
    • 2018-02-25
    相关资源
    最近更新 更多