From fdec66a3c18a8e80d629d0808891e65564c5fad7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E9=AD=8F=E6=B4=AA?= Date: Thu, 26 Feb 2026 15:35:17 +0800 Subject: [PATCH] fix: code support http url --- package.json | 3 +- src/subCommands/deploy/impl/function.ts | 84 +++++++++++++++++++++++-- 2 files changed, 82 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index aee0aef..c2c87e9 100644 --- a/package.json +++ b/package.json @@ -26,10 +26,10 @@ "@alicloud/fc2": "^2.6.6", "@alicloud/fc20230330": "4.6.7", "@alicloud/pop-core": "^1.8.0", + "@serverless-cd/srm-aliyun-oss": "^0.0.1-beta.8", "@serverless-cd/srm-aliyun-pop-core": "^0.0.8-beta.1", "@serverless-cd/srm-aliyun-ram20150501": "^0.0.2-beta.9", "@serverless-cd/srm-aliyun-sls20201230": "0.0.5-beta.3", - "@serverless-cd/srm-aliyun-oss": "^0.0.1-beta.8", "@serverless-devs/diff": "^0.0.3-beta.6", "@serverless-devs/downloads": "^0.0.7", "@serverless-devs/load-component": "^0.0.9", @@ -38,6 +38,7 @@ "ajv": "^8.17.1", "ali-oss": "6.18.1", "aliyun-sdk": "^1.12.10", + "axios": "^1.13.5", "chalk": "^4.1.0", "crc64-ecma182.js": "^2.0.2", "decompress": "^4.2.1", diff --git a/src/subCommands/deploy/impl/function.ts b/src/subCommands/deploy/impl/function.ts index c55048f..ac1f1f2 100644 --- a/src/subCommands/deploy/impl/function.ts +++ b/src/subCommands/deploy/impl/function.ts @@ -2,6 +2,8 @@ import _ from 'lodash'; import { diffConvertYaml } from '@serverless-devs/diff'; import inquirer from 'inquirer'; import fs from 'fs'; +import os from 'os'; +import axios from 'axios'; import assert from 'assert'; import path from 'path'; import { yellow } from 'chalk'; @@ -277,12 +279,16 @@ export default class Service extends Base { return true; } - let zipPath: string = path.isAbsolute(codeUri) - ? codeUri - : path.join(this.inputs.baseDir, codeUri); + let zipPath: string; + // 处理不同类型的 codeUri + if (codeUri.startsWith('http://') || codeUri.startsWith('https://')) { + zipPath = await this._downloadFromUrl(codeUri); + } else { + zipPath = path.isAbsolute(codeUri) ? codeUri : path.join(this.inputs.baseDir, codeUri); + } logger.debug(`Code path absolute path: ${zipPath}`); - const needZip = this._assertNeedZip(codeUri); + const needZip = this._assertNeedZip(zipPath); logger.debug(`Need zip file: ${needZip}`); let generateZipFilePath = ''; @@ -313,6 +319,15 @@ export default class Service extends Base { logger.debug( yellow(`skip uploadCode because code is no changed, codeChecksum=${crc64Value}`), ); + // 清理临时文件 + if (generateZipFilePath) { + try { + fs.rmSync(generateZipFilePath); + } catch (ex) { + logger.debug(`Unable to remove zip file: ${zipPath}`); + } + } + return false; } else { logger.debug(`\x1b[33mcodeChecksum from ${this.codeChecksum} to ${crc64Value}\x1b[0m`); @@ -333,6 +348,67 @@ export default class Service extends Base { return true; } + /** + * 从URL下载文件到本地临时目录 + */ + private async _downloadFromUrl(url: string): Promise { + logger.warn(`Downloading code from URL: ${url}`); + + // 创建临时目录 + const tempDir = path.join(os.tmpdir(), 'fc_code_download', Date.now().toString()); + fs.mkdirSync(tempDir, { recursive: true }); + let downloadPath: string; + + try { + // 从URL获取文件名 + const urlPath = new URL(url).pathname; + const filename = path.basename(urlPath) || `downloaded_code_${Date.now()}`; + downloadPath = path.join(tempDir, filename); + + // 下载文件 + const response = await axios({ + method: 'GET', + url, + responseType: 'stream', + }); + + const writer = fs.createWriteStream(downloadPath); + + // 创建一个 Promise 来处理流操作 + await new Promise((resolve, reject) => { + response.data.on('error', (err) => { + reject(new Error(`Source stream error: ${err.message}`)); + // 确保 writer 被关闭 + writer.destroy(err); + }); + + writer.on('finish', resolve); + + writer.on('error', (err) => { + reject(new Error(`Write stream error: ${err.message}`)); + response.data.destroy(); + }); + + response.data.pipe(writer); + }); + + logger.debug(`Downloaded file to: ${downloadPath}`); + + // 返回下载文件路径,由主流程决定是否需要压缩 + return downloadPath; + } catch (error) { + // 如果下载失败,清理临时目录 + try { + fs.rmSync(tempDir, { recursive: true, force: true }); + logger.debug(`Cleaned up temporary directory after error: ${tempDir}`); + } catch (cleanupError) { + logger.debug(`Failed to clean up temporary directory: ${cleanupError.message}`); + } + + throw new Error(`Failed to download code from URL: ${error.message}`); + } + } + /** * 生成 auto 资源,非 FC 资源,主要指 vpc、nas、log、role(oss mount 挂载点才有) */