Skip to content

fix: code support http url#142

Open
mozhou52 wants to merge 1 commit intomasterfrom
support-http
Open

fix: code support http url#142
mozhou52 wants to merge 1 commit intomasterfrom
support-http

Conversation

@mozhou52
Copy link
Collaborator

@mozhou52 mozhou52 commented Feb 26, 2026

fix: code support http url

Summary by CodeRabbit

  • New Features
    • Added support for deploying code directly from remote URLs (HTTP/HTTPS). The system now downloads remote packages to a temporary location as part of the deployment flow.
    • Improved deployment workflow with more robust temporary file cleanup and management to reduce leftover artifacts and improve reliability.

@mozhou52 mozhou52 requested a review from rsonghuster February 26, 2026 07:38
@coderabbitai
Copy link

coderabbitai bot commented Feb 26, 2026

📝 Walkthrough

Walkthrough

Added HTTP(S) code download support to the deployment flow: _uploadCode now detects codeUri URLs and downloads them via a new private _downloadFromUrl method (uses axios), writing to a temp directory and integrating with existing packaging and cleanup logic.

Changes

Cohort / File(s) Summary
Dependency Updates
package.json
Moved @serverless-cd/srm-aliyun-oss declaration within dependencies and added axios (^1.13.5) to dependencies.
URL Code Download Feature
src/subCommands/deploy/impl/function.ts
Added imports for os and axios; implemented _downloadFromUrl(url: string): Promise<string>; updated _uploadCode to detect http(s) codeUri, download to temp dir, integrate with packaging flow, and add temp-file cleanup in relevant branches while preserving local-path handling and checksum logic.

Sequence Diagram

sequenceDiagram
    participant Deploy as Deploy Process
    participant Upload as _uploadCode()
    participant Download as _downloadFromUrl()
    participant HTTP as HTTP Client (axios)
    participant FS as File System
    participant Packager as Packaging Logic

    Deploy->>Upload: provide codeUri
    Upload->>Upload: detect if codeUri starts with http(s)
    alt codeUri is URL
        Upload->>Download: downloadFromUrl(url)
        Download->>HTTP: GET url (stream)
        HTTP-->>Download: response stream
        Download->>FS: create temp dir & write file
        FS-->>Download: temp file path
        Download-->>Upload: return temp file path
        Upload->>Packager: package/process temp file
        Packager->>FS: upload packaged artifact
        Packager->>FS: cleanup temp file (delete)
    else codeUri is local
        Upload->>FS: resolve absolute/local path
        Upload->>Packager: package/process local path
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped to fetch code from a distant URL,
With axios in paw and a temp file to shel(l),
I pack what I find and tidy the track—
Fluffy uploads done, then I bounce right back! 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: code support http url' directly describes the main change: adding support for HTTP(S) URLs in code deployment, which is evidenced by the new _downloadFromUrl method and axios dependency.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch support-http

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/subCommands/deploy/impl/function.ts (2)

282-349: ⚠️ Potential issue | 🟠 Major

Always clean downloaded temp artifacts (including failure paths).

Downloaded files/dirs created for URL sources are never removed, and current cleanup is not in a finally path. This can leak temp storage over repeated deploys or failed uploads.

💡 Proposed fix
-    let zipPath: string;
+    let zipPath: string;
+    let downloadedPath = '';
+    let downloadedTempDir = '';
...
-      zipPath = await this._downloadFromUrl(codeUri);
+      zipPath = await this._downloadFromUrl(codeUri);
+      downloadedPath = zipPath;
+      downloadedTempDir = path.dirname(downloadedPath);
...
-    const ossConfig = await this.fcSdk.uploadCodeToTmpOss(zipPath);
-    logger.debug('ossConfig: ', ossConfig);
-    _.set(this.local, 'code', ossConfig);
-
-    if (generateZipFilePath) {
-      try {
-        fs.rmSync(generateZipFilePath);
-      } catch (ex) {
-        logger.debug(`Unable to remove zip file: ${zipPath}`);
-      }
-    }
+    try {
+      const ossConfig = await this.fcSdk.uploadCodeToTmpOss(zipPath);
+      logger.debug('ossConfig: ', ossConfig);
+      _.set(this.local, 'code', ossConfig);
+    } finally {
+      if (generateZipFilePath) {
+        try {
+          fs.rmSync(generateZipFilePath, { force: true });
+        } catch (ex) {
+          logger.debug(`Unable to remove zip file: ${generateZipFilePath}`);
+        }
+      }
+      if (downloadedTempDir) {
+        try {
+          fs.rmSync(downloadedTempDir, { recursive: true, force: true });
+        } catch (ex) {
+          logger.debug(`Unable to remove downloaded temp dir: ${downloadedTempDir}`);
+        }
+      }
+    }

Also applies to: 354-366

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/subCommands/deploy/impl/function.ts` around lines 282 - 349, The code
currently only removes generated zip files in the success path and when
codeChecksum matches, but never guarantees cleanup of downloaded temp artifacts
(from _downloadFromUrl) on failures; update the upload flow in the function
(references: _downloadFromUrl, needZip/_assertNeedZip, generateZipFilePath, and
the cleanup blocks that call fs.rmSync) to always remove any temp files/dirs
created (both the downloaded path and generatedZipFilePath) by moving cleanup
into a finally block or equivalent, ensure both success and error paths call the
same remover, handle and swallow fs.rmSync errors with debug logging, and apply
the same change to the similar cleanup at the other location noted (around the
code at 354-366).

284-292: ⚠️ Potential issue | 🟠 Major

Fix zip/packaging decision for URL inputs.

Line 291 uses this._assertNeedZip(codeUri). For URLs like https://x/a.zip?token=..., suffix checks fail and can trigger incorrect re-packaging. Base the decision on the URL pathname (or resolved download filename), not the raw URL string.

💡 Proposed fix
-    const needZip = this._assertNeedZip(codeUri);
+    const zipDecisionSource =
+      codeUri.startsWith('http://') || codeUri.startsWith('https://')
+        ? new URL(codeUri).pathname
+        : codeUri;
+    const needZip = this._assertNeedZip(zipDecisionSource);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/subCommands/deploy/impl/function.ts` around lines 284 - 292, The
packaging decision incorrectly calls this._assertNeedZip(codeUri) using the raw
URL string; update the logic so when codeUri is an HTTP(S) URL you determine the
filename from the URL (e.g. new URL(codeUri).pathname) or from the resolved
download filename returned by this._downloadFromUrl and pass that filename/path
into this._assertNeedZip (or call _assertNeedZip after download using zipPath)
so suffix checks operate on the actual filename/path rather than the full
query-string URL.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/subCommands/deploy/impl/function.ts`:
- Around line 368-372: The axios download calls lack timeout and payload limits;
update the axios options in _downloadFromUrl() (in
src/subCommands/deploy/impl/function.ts) and in downloadFile() (in
src/utils/index.ts) to include a timeout and content/body size caps (e.g.,
timeout: 30000, maxContentLength and maxBodyLength set to a reasonable limit
such as 50 * 1024 * 1024) so slow or very large responses fail fast and avoid
exhausting disk/memory; ensure the same keys (timeout, maxContentLength,
maxBodyLength) are added to the existing axios({...}) call objects used for
downloads.

---

Outside diff comments:
In `@src/subCommands/deploy/impl/function.ts`:
- Around line 282-349: The code currently only removes generated zip files in
the success path and when codeChecksum matches, but never guarantees cleanup of
downloaded temp artifacts (from _downloadFromUrl) on failures; update the upload
flow in the function (references: _downloadFromUrl, needZip/_assertNeedZip,
generateZipFilePath, and the cleanup blocks that call fs.rmSync) to always
remove any temp files/dirs created (both the downloaded path and
generatedZipFilePath) by moving cleanup into a finally block or equivalent,
ensure both success and error paths call the same remover, handle and swallow
fs.rmSync errors with debug logging, and apply the same change to the similar
cleanup at the other location noted (around the code at 354-366).
- Around line 284-292: The packaging decision incorrectly calls
this._assertNeedZip(codeUri) using the raw URL string; update the logic so when
codeUri is an HTTP(S) URL you determine the filename from the URL (e.g. new
URL(codeUri).pathname) or from the resolved download filename returned by
this._downloadFromUrl and pass that filename/path into this._assertNeedZip (or
call _assertNeedZip after download using zipPath) so suffix checks operate on
the actual filename/path rather than the full query-string URL.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d4940bc and 7c108dd.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (2)
  • package.json
  • src/subCommands/deploy/impl/function.ts

Comment on lines +368 to +372
const response = await axios({
method: 'GET',
url,
responseType: 'stream',
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's locate the file and check the specific lines mentioned
cat -n src/subCommands/deploy/impl/function.ts | sed -n '365,375p'

Repository: devsapp/fc3

Length of output: 410


🏁 Script executed:

# Check for axios calls with timeout/body limit configurations in the entire file
rg -n -C5 --type=ts 'axios\(\{' src/subCommands/deploy/impl/function.ts

Repository: devsapp/fc3

Length of output: 413


🏁 Script executed:

# Search for timeout and content length configurations in the codebase
rg -n --type=ts 'timeout|maxContentLength|maxBodyLength' src/subCommands/deploy/impl/function.ts

Repository: devsapp/fc3

Length of output: 37


🏁 Script executed:

# Check if axios instance is created with defaults elsewhere
rg -n --type=ts 'axios\.create|axios\.defaults' src/

Repository: devsapp/fc3

Length of output: 37


🏁 Script executed:

# Look for all axios calls in the codebase to see if any have timeout/limits
rg -n --type=ts 'axios\(' . --max-count=20

Repository: devsapp/fc3

Length of output: 196


🏁 Script executed:

# Check if this function has any error handling or resource limits
cat -n src/subCommands/deploy/impl/function.ts | sed -n '340,385p'

Repository: devsapp/fc3

Length of output: 1576


🏁 Script executed:

# Search for any axios configuration or interceptors that might set defaults
rg -n --type=ts -B2 -A2 'interceptor' src/

Repository: devsapp/fc3

Length of output: 37


🏁 Script executed:

# Check the other axios call in utils/index.ts
cat -n src/utils/index.ts | sed -n '12,30p'

Repository: devsapp/fc3

Length of output: 695


🏁 Script executed:

# Get more context on the download function to see if there's any error handling for the stream
cat -n src/subCommands/deploy/impl/function.ts | sed -n '385,410p'

Repository: devsapp/fc3

Length of output: 1273


🏁 Script executed:

# Check if there are any limits set on the file system operations
rg -n --type=ts 'createWriteStream|highWaterMark' src/

Repository: devsapp/fc3

Length of output: 316


Add timeout and payload limits to axios download requests.

The axios calls for remote downloads lack timeout and body size limits. This affects both _downloadFromUrl() in src/subCommands/deploy/impl/function.ts:368 and downloadFile() in src/utils/index.ts:17. A slow or unbounded response can hang deployment or exhaust local disk/memory. Configure timeout, maxContentLength, and maxBodyLength to prevent resource exhaustion.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/subCommands/deploy/impl/function.ts` around lines 368 - 372, The axios
download calls lack timeout and payload limits; update the axios options in
_downloadFromUrl() (in src/subCommands/deploy/impl/function.ts) and in
downloadFile() (in src/utils/index.ts) to include a timeout and content/body
size caps (e.g., timeout: 30000, maxContentLength and maxBodyLength set to a
reasonable limit such as 50 * 1024 * 1024) so slow or very large responses fail
fast and avoid exhausting disk/memory; ensure the same keys (timeout,
maxContentLength, maxBodyLength) are added to the existing axios({...}) call
objects used for downloads.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/subCommands/deploy/impl/function.ts`:
- Around line 282-289: The downloaded temp artifact assigned to zipPath when
codeUri is HTTP(S) is never removed; update the function (the block that calls
this._downloadFromUrl to produce zipPath) to ensure cleanup of the downloaded
file/dir in all cases by wrapping usage in a try/finally (or equivalent) and
deleting the temp artifact in the finally block; apply the same pattern to the
other similar blocks mentioned (lines around the other occurrences) so that any
temp path created by _downloadFromUrl is removed via fs.unlink/fs.rm or a
recursive remover before returning or throwing.
- Line 355: The current logger.warn call logs the full download URL
(logger.warn(`Downloading code from URL: ${url}`)), which can leak sensitive
query parameters; change it to log a redacted form instead by parsing the url
(new URL(url)) and either stripping search params or replacing them with a
placeholder (e.g., show origin+pathname or origin+pathname+"?REDACTED") before
passing to logger.warn so no tokens/signatures appear in logs.
- Line 291: The call to this._assertNeedZip(codeUri) uses the raw codeUri (which
may be a remote URL with query params) causing incorrect zip detection; change
the code to compute the resolved local filesystem path first (e.g., resolve or
download/normalize codeUri into a localPath/resolvedCodeUri variable) and pass
that resolved local path into this._assertNeedZip instead of the raw codeUri so
detection operates on the actual filesystem path.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7c108dd and 48f731c.

📒 Files selected for processing (2)
  • package.json
  • src/subCommands/deploy/impl/function.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json

Comment on lines +282 to 289
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}`);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Downloaded temp artifacts are not cleaned up, causing disk leaks.

When codeUri is HTTP(S), the downloaded file/temp dir is never removed on either success or failure paths. Over repeated deploys, this will leak files under OS temp.

Proposed fix
   private async _uploadCode(): Promise<boolean> {
     const codeUri = this.local.code;
@@
-    let zipPath: string;
+    let zipPath: string;
+    let downloadedTempDir = '';
@@
     if (codeUri.startsWith('http://') || codeUri.startsWith('https://')) {
       zipPath = await this._downloadFromUrl(codeUri);
+      downloadedTempDir = path.dirname(zipPath);
     } else {
       zipPath = path.isAbsolute(codeUri) ? codeUri : path.join(this.inputs.baseDir, codeUri);
     }
@@
-    if (generateZipFilePath) {
-      try {
-        fs.rmSync(generateZipFilePath);
-      } catch (ex) {
-        logger.debug(`Unable to remove zip file: ${zipPath}`);
-      }
-    }
+    if (generateZipFilePath) {
+      try {
+        fs.rmSync(generateZipFilePath, { force: true });
+      } catch (ex) {
+        logger.debug(`Unable to remove zip file: ${zipPath}`);
+      }
+    }
+    if (downloadedTempDir) {
+      try {
+        fs.rmSync(downloadedTempDir, { recursive: true, force: true });
+      } catch (ex) {
+        logger.debug(`Unable to remove temp download dir: ${downloadedTempDir}`);
+      }
+    }

Also applies to: 322-346, 354-389

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/subCommands/deploy/impl/function.ts` around lines 282 - 289, The
downloaded temp artifact assigned to zipPath when codeUri is HTTP(S) is never
removed; update the function (the block that calls this._downloadFromUrl to
produce zipPath) to ensure cleanup of the downloaded file/dir in all cases by
wrapping usage in a try/finally (or equivalent) and deleting the temp artifact
in the finally block; apply the same pattern to the other similar blocks
mentioned (lines around the other occurrences) so that any temp path created by
_downloadFromUrl is removed via fs.unlink/fs.rm or a recursive remover before
returning or throwing.

}
logger.debug(`Code path absolute path: ${zipPath}`);

const needZip = this._assertNeedZip(codeUri);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Use resolved local path for zip-type detection, not raw URL string.

Line 291 uses codeUri for _assertNeedZip(). For URLs like https://host/pkg.zip?token=..., this returns the wrong result and can trigger unnecessary re-zipping.

Proposed fix
-    const needZip = this._assertNeedZip(codeUri);
+    const needZip = this._assertNeedZip(zipPath);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/subCommands/deploy/impl/function.ts` at line 291, The call to
this._assertNeedZip(codeUri) uses the raw codeUri (which may be a remote URL
with query params) causing incorrect zip detection; change the code to compute
the resolved local filesystem path first (e.g., resolve or download/normalize
codeUri into a localPath/resolvedCodeUri variable) and pass that resolved local
path into this._assertNeedZip instead of the raw codeUri so detection operates
on the actual filesystem path.

* 从URL下载文件到本地临时目录
*/
private async _downloadFromUrl(url: string): Promise<string> {
logger.warn(`Downloading code from URL: ${url}`);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid logging full download URL (may leak signed query credentials).

Line 355 logs the full URL. Pre-signed URLs commonly carry sensitive query params (token, signature, etc.), which should not enter logs.

Proposed fix
-    logger.warn(`Downloading code from URL: ${url}`);
+    const parsed = new URL(url);
+    logger.warn(`Downloading code from URL: ${parsed.origin}${parsed.pathname}`);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
logger.warn(`Downloading code from URL: ${url}`);
const parsed = new URL(url);
logger.warn(`Downloading code from URL: ${parsed.origin}${parsed.pathname}`);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/subCommands/deploy/impl/function.ts` at line 355, The current logger.warn
call logs the full download URL (logger.warn(`Downloading code from URL:
${url}`)), which can leak sensitive query parameters; change it to log a
redacted form instead by parsing the url (new URL(url)) and either stripping
search params or replacing them with a placeholder (e.g., show origin+pathname
or origin+pathname+"?REDACTED") before passing to logger.warn so no
tokens/signatures appear in logs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant