Skip to content

fix(vfox): avoid auth on release asset downloads#9299

Merged
jdx merged 4 commits intomainfrom
fix/vfox-http-retries
Apr 22, 2026
Merged

fix(vfox): avoid auth on release asset downloads#9299
jdx merged 4 commits intomainfrom
fix/vfox-http-retries

Conversation

@jdx
Copy link
Copy Markdown
Owner

@jdx jdx commented Apr 22, 2026

Summary

  • stop injecting GitHub auth headers into public GitHub release download URLs used by vfox plugins
  • add small retries for transient vfox HTTP failures so plugin HEAD/GET checks are less flaky
  • add unit coverage for both behaviors and verify with the Kotlin vfox e2e

Verification

  • cargo test -p vfox lua_mod::http -- --nocapture
  • mise run test:e2e e2e/backend/test_vfox_kotlin_slow

Note

Medium Risk
Changes HTTP request behavior in the vfox Lua http module (adds automatic retries and adjusts when Authorization is attached), which could affect plugin download/HEAD semantics and private GitHub release access.

Overview
Improves the vfox Lua http module by adding a small retry loop (send_with_retry) for timeouts and transient HTTP statuses (e.g., 429/503/504), and wiring it into get, head, and download paths.

Refines GitHub default header injection so Authorization is not sent to GitHub release asset/CDN hosts (but is still sent to initial github.com release download URLs), and adds unit tests covering both the header behavior and retrying a transient HEAD response.

Updates vfox to enable tokio’s time feature for sleeps, and updates hk.pkl so prettier runs via mise x npm:prettier to keep local/CI formatting consistent.

Reviewed by Cursor Bugbot for commit 465e3f6. Bugbot is set up for automated code reviews on this repo. Configure here.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces an HTTP retry mechanism with backoff for transient errors and modifies header logic to exclude GitHub authorization tokens from release download URLs to prevent redirect issues. Review feedback suggests simplifying error handling in the retry loop and highlights a potential issue where excluding tokens might break downloads from private GitHub repositories.

Comment thread crates/vfox/src/lua_mod/http.rs Outdated
Comment on lines +43 to +46
Err(err) if attempt + 1 < HTTP_RETRY_ATTEMPTS => {
tokio::time::sleep(retry_delay(attempt)).await;
let _ = err;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The let _ = err; statement is redundant as the error variable is already bound and will be dropped at the end of the block. Since the error is not used in this specific retry branch, you can simplify the match arm by using _ in the pattern.

            Err(_) if attempt + 1 < HTTP_RETRY_ATTEMPTS => {
                tokio::time::sleep(retry_delay(attempt)).await;
            }

Comment thread crates/vfox/src/lua_mod/http.rs Outdated

if is_github && let Some(token) = github_token(lua) {
if is_github
&& !is_release_asset_url
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Excluding the Authorization header for all github.com URLs containing /releases/download/ might break downloads from private repositories if they rely on the automatic injection of the environment's GitHub token. While this avoids issues with redirects for public assets (where tokens can sometimes cause 403s or redirect conflicts), it is a functional change for private assets. If private repository support is required, consider if there is a way to distinguish them or ensure that explicitly provided headers (handled at line 131) are the intended workaround for those cases.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 22, 2026

Greptile Summary

This PR adds bounded retry logic (send_with_retry) to all vfox Lua HTTP calls — retrying on timeouts and transient status codes (408/429/502/503/504) with a linear 200 ms × attempt backoff — and adds a clarifying comment to the existing CDN auth-exclusion logic in add_default_headers. The hk.pkl update pins prettier to the mise-managed version for consistency.

Confidence Score: 5/5

Safe to merge; the retry logic is well-bounded and only triggers on genuinely transient conditions.

All findings are P2. The retry implementation is correct: non-timeout errors propagate immediately, status-code retries are capped at 3 attempts, and the unreachable! at the end of the loop is provably unreachable. Auth behavior for github.com release-download URLs and CDN hosts is correctly preserved and tested.

The new test_head_retries_transient_status in http.rs has a minor thread-leak risk on assertion failure, but no production files require special attention.

Important Files Changed

Filename Overview
crates/vfox/src/lua_mod/http.rs Adds send_with_retry (retries on timeouts and 408/429/502/503/504), switches all HTTP calls to use it, and clarifies the existing auth-header exclusion logic for CDN hosts; minor test thread-leak risk in the new retry test.
crates/vfox/Cargo.toml Adds the "time" feature to tokio so tokio::time::sleep can be used in the new retry backoff logic.
hk.pkl Overrides prettier's check/fix commands to run through mise x npm:prettier for consistent tool pinning across local and CI.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Lua HTTP call\nget/head/download_file/…] --> B[add_default_headers]
    B --> C{Host is github.com\nor api.github.com\nor *.githubusercontent.com\nexcl. CDN hosts?}
    C -- Yes --> D[Inject Bearer token\n+ x-github-api-version\nif api.github.com]
    C -- No --> E[Headers unchanged]
    D --> F[send_with_retry]
    E --> F
    F --> G{try_clone\nsucceeds?}
    G -- No --> H[builder.send — no retry]
    G -- Yes --> I[attempt 0..3]
    I --> J{Response?}
    J -- Ok + retryable status\nAND attempt < 3 --> K[sleep 200ms × attempt+1]
    K --> I
    J -- Ok + final or\nnon-retryable status --> L[Return Ok]
    J -- Err timeout\nAND attempt < 3 --> K
    J -- Err non-timeout\nor last attempt --> M[Return Err]
Loading

Fix All in Claude Code

Reviews (5): Last reviewed commit: "fix(vfox): rely on reqwest redirect stri..." | Re-trigger Greptile

Comment thread crates/vfox/src/lua_mod/http.rs Outdated
Comment thread crates/vfox/src/lua_mod/http.rs Outdated
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 22, 2026

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.4.18 x -- echo 21.4 ± 0.5 20.5 23.1 1.00
mise x -- echo 22.2 ± 0.7 21.0 27.3 1.04 ± 0.04

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.4.18 env 21.2 ± 1.0 20.1 33.1 1.00
mise env 21.8 ± 0.7 20.5 23.8 1.03 ± 0.06

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.4.18 hook-env 21.9 ± 0.6 20.7 23.6 1.00
mise hook-env 22.6 ± 0.6 21.3 24.6 1.03 ± 0.04

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.4.18 ls 19.5 ± 0.8 18.2 24.5 1.00
mise ls 20.6 ± 0.7 18.8 22.4 1.06 ± 0.06

xtasks/test/perf

Command mise-2026.4.18 mise Variance
install (cached) 143ms ⚠️ 165ms -13%
ls (cached) 75ms 78ms -3%
bin-paths (cached) 79ms 83ms -4%
task-ls (cached) 814ms 805ms +1%

⚠️ Warning: install cached performance variance is -13%

@jdx jdx force-pushed the fix/vfox-http-retries branch from 975ae30 to 9aea683 Compare April 22, 2026 16:25
jdx and others added 3 commits April 22, 2026 12:03
Retrying on every request error made connection-refused failure-path
tests ~600ms slower each; narrow to timeouts so hard connection
failures propagate immediately. Also document that suppressing
Authorization for github.com release-download URLs is scoped to
public repos — plugins can still pass an explicit Authorization
header for private repos.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Developer shells with another prettier earlier on PATH (Homebrew ships
3.4.x which mishandles multi-line GitHub alerts in markdown) were
disagreeing with CI, which uses mise's pinned npm:prettier 3.8.x.
Resolve via `mise which prettier` so hk always invokes the pinned
binary regardless of PATH order.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Replace the path-based suppression on github.com/*/releases/download/*
with the hostname-only approach used by src/github.rs: attach auth on
the initial github.com request (required for private-repo downloads)
and let reqwest's default redirect policy strip Authorization on the
cross-origin hop to the CDN (objects/release-assets.githubusercontent.com).
Fixes the silent break of private-repo release downloads flagged in
review.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@jdx jdx enabled auto-merge (squash) April 22, 2026 17:51
@jdx jdx merged commit 86dd818 into main Apr 22, 2026
37 checks passed
@jdx jdx deleted the fix/vfox-http-retries branch April 22, 2026 17:55
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