优化代码结构,支持h2 #39

Merged
sky22333 merged 7 commits from dev into main 2025-07-27 12:11:39 +08:00
sky22333 commented 2025-07-27 11:54:19 +08:00 (Migrated from github.com)

Summary by CodeRabbit

  • New Features

    • Added support for HTTP/2 Cleartext (H2C) multiplexing, configurable via settings and environment variables.
    • Introduced a GitHub proxy endpoint for handling GitHub-related requests with smart script processing and redirect handling.
  • Improvements

    • Increased default rate limit window and request limit for enhanced throughput.
    • Refined configuration options and documentation for easier setup and management.
    • Docker proxy and image tar streaming features are now modular and more maintainable.
  • Refactor

    • Major codebase reorganization: proxy logic, handlers, configuration, and utilities are now separated into dedicated packages for improved clarity and maintainability.
    • Exported key functions and variables for better modularity and extensibility.
  • Documentation

    • Updated README and configuration examples to reflect new options and improved clarity.
  • Style

    • Code comments streamlined and formatting improved for consistency.

No changes to core user-facing workflows except as noted above.

<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added support for HTTP/2 Cleartext (H2C) multiplexing, configurable via settings and environment variables. * Introduced a GitHub proxy endpoint for handling GitHub-related requests with smart script processing and redirect handling. * **Improvements** * Increased default rate limit window and request limit for enhanced throughput. * Refined configuration options and documentation for easier setup and management. * Docker proxy and image tar streaming features are now modular and more maintainable. * **Refactor** * Major codebase reorganization: proxy logic, handlers, configuration, and utilities are now separated into dedicated packages for improved clarity and maintainability. * Exported key functions and variables for better modularity and extensibility. * **Documentation** * Updated README and configuration examples to reflect new options and improved clarity. * **Style** * Code comments streamlined and formatting improved for consistency. No changes to core user-facing workflows except as noted above. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
coderabbitai[bot] commented 2025-07-27 11:54:33 +08:00 (Migrated from github.com)

Walkthrough

This update refactors and modularizes the codebase, moving logic from the main entry point into dedicated packages for configuration, utilities, and handlers. It introduces a new GitHub proxy handler, adds HTTP/2 Cleartext (H2C) support, revises configuration defaults, and exports previously internal functions and variables for broader package use.

Changes

File(s) / Path(s) Change Summary
README.md, src/config.toml Updated documentation and config examples: added enableH2C option, increased rate limit period, renamed [proxy] to [access], removed example proxy URLs.
docker-compose.yml Changed indentation of hubproxy service for consistency; no functional changes.
src/go.mod Promoted golang.org/x/net to direct dependency.
src/config/config.go Refactored to config package, added EnableH2C field, increased default rate limit, added env override for H2C, removed comments.
src/handlers/docker.go, src/handlers/imagetar.go, src/handlers/search.go Refactored to use handlers package, centralized config and utilities, renamed and exported several functions, removed redundant comments.
src/handlers/github.go Added: new GitHub proxy handler with URL validation, access control, redirect handling, and smart shell script processing.
src/main.go Major refactor: moved proxy logic to handlers, modularized initialization, added H2C support, improved health endpoint, cleaned up imports and comments.
src/utils/access_control.go, src/utils/cache.go, src/utils/http_client.go, src/utils/proxy_shell.go, src/utils/ratelimiter.go Refactored to utils package, updated imports, exported previously internal functions/variables, introduced shared whitelist limiter in rate limiter, removed or simplified comments.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant GinRouter
    participant GitHubProxyHandler
    participant AccessController
    participant HTTPClient

    Client->>GinRouter: HTTP request (unmatched route)
    GinRouter->>GitHubProxyHandler: Call handler
    GitHubProxyHandler->>AccessController: Check GitHub URL access
    AccessController-->>GitHubProxyHandler: Access allowed/denied
    GitHubProxyHandler->>HTTPClient: Proxy request (with redirects)
    HTTPClient-->>GitHubProxyHandler: Response (possibly redirect)
    GitHubProxyHandler->>GinRouter: Stream response to client
    GinRouter-->>Client: Return proxied content or error
sequenceDiagram
    participant Main
    participant Config
    participant Utils
    participant Handlers
    participant GinRouter

    Main->>Config: LoadConfig()
    Main->>Utils: InitHTTPClients()
    Main->>Utils: InitGlobalLimiter()
    Main->>Handlers: InitDockerProxy()
    Main->>Handlers: InitImageStreamer()
    Main->>Handlers: InitDebouncer()
    Main->>GinRouter: Register routes (search, docker, image, health, NoRoute)
    Main->>GinRouter: Start HTTP server (with optional H2C)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Poem

Oh, what a hop through the code today!
We’ve split up the logic, sent main on its way.
Now handlers and utils, so neat and so spry,
Serve GitHub and Docker as requests hop by.
With H2C speed and a proxy so bright,
This rabbit’s code garden grows just right!
🐇

Note

️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dev

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.
<!-- This is an auto-generated comment: summarize by coderabbit.ai --> <!-- walkthrough_start --> ## Walkthrough This update refactors and modularizes the codebase, moving logic from the main entry point into dedicated packages for configuration, utilities, and handlers. It introduces a new GitHub proxy handler, adds HTTP/2 Cleartext (H2C) support, revises configuration defaults, and exports previously internal functions and variables for broader package use. ## Changes | File(s) / Path(s) | Change Summary | |--------------------------------------------------------|---------------| | README.md, src/config.toml | Updated documentation and config examples: added `enableH2C` option, increased rate limit period, renamed `[proxy]` to `[access]`, removed example proxy URLs. | | docker-compose.yml | Changed indentation of `hubproxy` service for consistency; no functional changes. | | src/go.mod | Promoted `golang.org/x/net` to direct dependency. | | src/config/config.go | Refactored to `config` package, added `EnableH2C` field, increased default rate limit, added env override for H2C, removed comments. | | src/handlers/docker.go, src/handlers/imagetar.go, src/handlers/search.go | Refactored to use `handlers` package, centralized config and utilities, renamed and exported several functions, removed redundant comments. | | src/handlers/github.go | Added: new GitHub proxy handler with URL validation, access control, redirect handling, and smart shell script processing. | | src/main.go | Major refactor: moved proxy logic to handlers, modularized initialization, added H2C support, improved health endpoint, cleaned up imports and comments. | | src/utils/access_control.go, src/utils/cache.go, src/utils/http_client.go, src/utils/proxy_shell.go, src/utils/ratelimiter.go | Refactored to `utils` package, updated imports, exported previously internal functions/variables, introduced shared whitelist limiter in rate limiter, removed or simplified comments. | ## Sequence Diagram(s) ```mermaid sequenceDiagram participant Client participant GinRouter participant GitHubProxyHandler participant AccessController participant HTTPClient Client->>GinRouter: HTTP request (unmatched route) GinRouter->>GitHubProxyHandler: Call handler GitHubProxyHandler->>AccessController: Check GitHub URL access AccessController-->>GitHubProxyHandler: Access allowed/denied GitHubProxyHandler->>HTTPClient: Proxy request (with redirects) HTTPClient-->>GitHubProxyHandler: Response (possibly redirect) GitHubProxyHandler->>GinRouter: Stream response to client GinRouter-->>Client: Return proxied content or error ``` ```mermaid sequenceDiagram participant Main participant Config participant Utils participant Handlers participant GinRouter Main->>Config: LoadConfig() Main->>Utils: InitHTTPClients() Main->>Utils: InitGlobalLimiter() Main->>Handlers: InitDockerProxy() Main->>Handlers: InitImageStreamer() Main->>Handlers: InitDebouncer() Main->>GinRouter: Register routes (search, docker, image, health, NoRoute) Main->>GinRouter: Start HTTP server (with optional H2C) ``` ## Estimated code review effort 🎯 4 (Complex) | ⏱️ ~40 minutes ## Poem > Oh, what a hop through the code today! > We’ve split up the logic, sent main on its way. > Now handlers and utils, so neat and so spry, > Serve GitHub and Docker as requests hop by. > With H2C speed and a proxy so bright, > This rabbit’s code garden grows just right! > 🐇✨ <!-- walkthrough_end --> <!-- announcements_start --> > [!NOTE] > <details open="true"> > <summary>⚡️ Unit Test Generation is now available in beta!</summary> > > Learn more [here](https://docs.coderabbit.ai/finishing-touches/unit-test-generation), or try it out under "Finishing Touches" below. > > </details> <!-- announcements_end --> <!-- internal state start --> <!-- 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 --> <!-- internal state end --> <!-- finishing_touch_checkbox_start --> <details> <summary>✨ Finishing Touches</summary> - [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings <details> <summary>🧪 Generate unit tests</summary> - [ ] <!-- {"checkboxId": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} --> Create PR with unit tests - [ ] <!-- {"checkboxId": "07f1e7d6-8a8e-4e23-9900-8731c2c87f58", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} --> Post copyable unit tests in a comment - [ ] <!-- {"checkboxId": "6ba7b810-9dad-11d1-80b4-00c04fd430c8", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} --> Commit unit tests in branch `dev` </details> </details> <!-- finishing_touch_checkbox_end --> <!-- tips_start --> --- 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. <details> <summary>❤️ Share</summary> - [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai) - [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai) - [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai) - [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code) </details> <details> <summary>🪧 Tips</summary> ### Chat There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=sky22333/hubproxy&utm_content=39): - Review comments: Directly reply to a review comment made by CodeRabbit. Example: - `I pushed a fix in commit <commit_id>, please review it.` - `Explain this complex logic.` - `Open a follow-up GitHub issue for this discussion.` - Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples: - `@coderabbitai explain this code block.` - `@coderabbitai modularize this function.` - PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples: - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.` - `@coderabbitai read src/utils.ts and explain its main purpose.` - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.` - `@coderabbitai help me debug CodeRabbit configuration file.` ### Support Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. ### CodeRabbit Commands (Invoked using PR comments) - `@coderabbitai pause` to pause the reviews on a PR. - `@coderabbitai resume` to resume the paused reviews. - `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository. - `@coderabbitai full review` to do a full review from scratch and review all the files again. - `@coderabbitai summary` to regenerate the summary of the PR. - `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR. - `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR. - `@coderabbitai generate unit tests` to generate unit tests for this PR. - `@coderabbitai resolve` resolve all the CodeRabbit review comments. - `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository. - `@coderabbitai help` to get help. ### Other keywords and placeholders - Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed. - Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description. - Add `@coderabbitai` anywhere in the PR title to generate the title automatically. ### CodeRabbit Configuration File (`.coderabbit.yaml`) - You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository. - Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information. - If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json` ### Documentation and Community - Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit. - Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback. - Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements. </details> <!-- tips_end -->
coderabbitai[bot] (Migrated from github.com) reviewed 2025-07-27 12:00:56 +08:00
coderabbitai[bot] (Migrated from github.com) left a comment

Actionable comments posted: 2

🧹 Nitpick comments (7)
docker-compose.yml (1)

1-8: Add trailing newline to satisfy YAML linters and POSIX tools

yamllint flagged the missing newline at EOF. Some tools (e.g. POSIX sed, cat) expect the last line to be newline-terminated; adding it avoids subtle processing glitches.

       - ./src/config.toml:/root/config.toml
+
src/go.mod (1)

5-11: Run go mod tidy after promoting golang.org/x/net to direct

Promoting the dependency is sensible given the new H2C handler. Running

go mod tidy

will prune any now-unused transitive deps and lock in the minimal go.sum.

README.md (2)

112-114: Highlight security caveat for enableH2C

H2C (HTTP/2 cleartext) omits TLS. Recommend adding a doc note that it should only be enabled behind a trusted TLS-terminating reverse proxy to avoid downgrading security.


119-120: Rate-limit window change: update examples & alerts

The period changed to 3 h; ensure any alerting/monitoring or README examples (e.g. “每小时请求数”) are likewise updated so users don’t mis-interpret the limits.

src/config.toml (2)

7-8: enableH2C defaults to false — ensure reverse proxy handles HTTP/2 if later enabled

Enabling H2C exposes the service over cleartext HTTP/2; verify your ingress (Caddy / Nginx) supports h2c upgrade, otherwise clients will fall back to HTTP/1.1 and lose multiplexing benefits.


14-14: Keep comment in sync: limit is now 3 h, not “每小时”

The Chinese comment still says “每小时允许的请求数”; with a 3-hour window that’s misleading. Consider updating to “每 3 小时”.

src/handlers/search.go (1)

152-161: Consider goroutine lifecycle management.

The cleanup goroutine started in init() runs indefinitely without a shutdown mechanism. Consider:

  1. Using a context for graceful shutdown
  2. Providing a way to stop the cleanup routine when the application shuts down
-func init() {
-	go func() {
-		ticker := time.NewTicker(5 * time.Minute)
-		defer ticker.Stop()
-
-		for range ticker.C {
-			searchCache.Cleanup()
-		}
-	}()
-}
+var cleanupDone chan struct{}
+
+func init() {
+	cleanupDone = make(chan struct{})
+	go func() {
+		ticker := time.NewTicker(5 * time.Minute)
+		defer ticker.Stop()
+
+		for {
+			select {
+			case <-ticker.C:
+				searchCache.Cleanup()
+			case <-cleanupDone:
+				return
+			}
+		}
+	}()
+}
+
+// StopCacheCleanup stops the cache cleanup goroutine
+func StopCacheCleanup() {
+	if cleanupDone != nil {
+		close(cleanupDone)
+	}
+}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between badafd2899 and 07a926902a.

📒 Files selected for processing (15)
  • README.md (3 hunks)
  • docker-compose.yml (1 hunks)
  • src/config.toml (1 hunks)
  • src/config/config.go (6 hunks)
  • src/go.mod (1 hunks)
  • src/handlers/docker.go (17 hunks)
  • src/handlers/github.go (1 hunks)
  • src/handlers/imagetar.go (11 hunks)
  • src/handlers/search.go (1 hunks)
  • src/main.go (5 hunks)
  • src/utils/access_control.go (4 hunks)
  • src/utils/cache.go (6 hunks)
  • src/utils/http_client.go (2 hunks)
  • src/utils/proxy_shell.go (1 hunks)
  • src/utils/ratelimiter.go (7 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (5)
src/utils/http_client.go (2)
src/config/config.go (1)
  • GetConfig (148-184)
src/http_client.go (3)
  • initHTTPClients (18-58)
  • GetGlobalHTTPClient (61-63)
  • GetSearchHTTPClient (66-68)
src/handlers/imagetar.go (3)
src/config/config.go (1)
  • GetConfig (148-184)
src/utils/http_client.go (1)
  • GetGlobalHTTPClient (60-62)
src/imagetar.go (9)
  • initDebouncer (131-136)
  • handleSimpleBatchDownload (657-724)
  • initImageTarRoutes (595-602)
  • handleDirectImageDownload (605-654)
  • StreamMultipleImages (786-884)
  • cleanup (81-87)
  • NewDownloadDebouncer (43-49)
  • processImageForBatch (460-482)
  • StreamImageToGin (223-237)
src/utils/access_control.go (1)
src/config/config.go (1)
  • GetConfig (148-184)
src/utils/cache.go (1)
src/config/config.go (1)
  • GetConfig (148-184)
src/handlers/docker.go (5)
src/config/config.go (2)
  • GetConfig (148-184)
  • RegistryMapping (15-20)
src/utils/http_client.go (1)
  • GetGlobalHTTPClient (60-62)
src/utils/access_control.go (1)
  • GlobalAccessController (32-32)
src/utils/cache.go (9)
  • IsCacheEnabled (132-135)
  • BuildManifestCacheKey (70-73)
  • GlobalCache (28-28)
  • WriteCachedResponse (119-129)
  • GetManifestTTL (75-94)
  • IsTokenCacheEnabled (138-140)
  • BuildTokenCacheKey (66-68)
  • WriteTokenResponse (114-117)
  • ExtractTTLFromResponse (97-112)
src/docker.go (9)
  • proxyDockerAuthOriginal (388-466)
  • ProxyDockerRegistryGin (85-100)
  • handleRegistryRequest (103-150)
  • rewriteAuthHeader (469-477)
  • handleUpstreamManifestRequest (520-593)
  • handleMultiRegistryRequest (480-517)
  • handleManifestRequest (180-256)
  • ProxyDockerAuthGin (331-338)
  • proxyDockerAuthWithCache (341-370)
🪛 YAMLlint (1.37.1)
docker-compose.yml

[error] 8-8: no new line character at the end of file

(new-line-at-end-of-file)

🔇 Additional comments (25)
docker-compose.yml (1)

1-8: Confirm indentation convention is now 2 spaces project-wide

You switched this file from 4- to 2-space indents. If other YAML manifests in the repo still use 4 spaces, consider normalising to one style to avoid churn in future diffs.

src/utils/proxy_shell.go (1)

1-1: Package rename looks correct; verify all import paths compile

Moving the file into package utils is consistent with the refactor, but make sure all call-sites have updated imports (hubproxy/utils or equivalent).
A quick go vet ./... + go test ./... after go mod tidy will catch any dangling references.

README.md (2)

40-41: Verify updated install script URL exists

install-service.shinstall.sh change is fine, but please confirm the new script is pushed to main and is executable; broken quick-start links frustrate first-time users.


137-149: Section renamed to [access]; double-check code uses new key

Config struct tags and env-var overrides must match this rename. A mismatch silently falls back to defaults.

src/utils/access_control.go (3)

1-1: LGTM! Package restructuring looks good.

The package name change to utils and the addition of the config import are consistent with the modularization efforts in this PR.

Also applies to: 6-7


31-31: Good improvement: English documentation.

Translating the comment to English improves code accessibility for international contributors.


84-84: Correct usage of centralized config.

The updates to use config.GetConfig() properly leverage the centralized configuration package.

Also applies to: 109-109

src/utils/http_client.go (2)

1-1: Package restructuring is consistent.

The package name change and config import align with the overall modularization approach.

Also applies to: 8-9


17-19: Properly exported HTTP client functions.

The exported function names follow Go conventions and provide appropriate access to the HTTP clients from other packages.

Also applies to: 59-60, 64-65

src/config/config.go (4)

1-1: Appropriate package name for configuration module.

The config package name correctly reflects the module's purpose.


28-28: Well-implemented H2C support.

The HTTP/2 Cleartext support is properly implemented with:

  • Opt-in by default (false)
  • Configuration via TOML and environment variable
  • Proper error handling for boolean parsing

This aligns perfectly with the PR objective.

Also applies to: 76-77, 81-81, 225-229


87-88: Verify the rate limit configuration changes.

The request limit increased from 20 to 200 (10x increase). The AI summary mentions the period was extended to 3 hours, but the code shows PeriodHours: 1.0. Please confirm:

  1. Is the 10x rate limit increase intentional and based on actual usage patterns?
  2. Should PeriodHours be 3.0 instead of 1.0?

Likely an incorrect or invalid review comment.


16-20: Well-structured configuration types.

The struct definitions with TOML tags are properly implemented for configuration serialization.

Also applies to: 25-29

src/handlers/search.go (2)

1-17: Well-structured handler package.

The package organization and imports are appropriate for a search handler module.


279-279: Correct usage of search HTTP client.

Properly uses the search-specific HTTP client from utils package with appropriate timeouts for API calls.

Also applies to: 432-432

src/handlers/github.go (2)

17-30: Comprehensive URL pattern matching.

The regex patterns cover all major GitHub-related services and are pre-compiled for performance.


93-98: Good redirect loop protection.

The implementation properly limits redirects to 20 and returns an appropriate HTTP 508 status code.

src/utils/ratelimiter.go (3)

1-1: LGTM! Package refactoring aligns with modularization.

The package rename from main to utils and import update to use hubproxy/config are consistent with the broader refactoring effort.

Also applies to: 12-12


28-28: Good optimization for whitelist IP handling.

The addition of a shared whitelistLimiter with infinite rate is an efficient approach that:

  • Reduces memory usage by avoiding individual limiter creation for each whitelist IP
  • Clearly indicates that whitelist IPs have no rate limiting
  • Maintains burst size configuration for consistency

Also applies to: 85-85, 174-175


45-45: Minor: String concatenation style change.

The change from compound assignment to explicit concatenation is functionally equivalent. Both approaches work correctly in this context.

Also applies to: 60-60

src/handlers/imagetar.go (1)

1-1: LGTM! Clean modularization of image streaming functionality.

The refactoring successfully:

  • Moves functionality to the handlers package
  • Exports initialization functions for external use
  • Centralizes configuration and HTTP client access through config and utils packages
  • Maintains all core functionality while improving modularity

Also applies to: 26-27, 123-127, 141-157, 563-566, 576-584

src/utils/cache.go (1)

1-1: LGTM! Well-structured cache utilities export.

The refactoring properly:

  • Exports cache types and functions for cross-package use
  • Creates a global GlobalCache instance safely initialized
  • Centralizes configuration access through the config package
  • Maintains thread-safe operations with the existing sync.Map

Also applies to: 12-12, 15-28, 61-140

src/handlers/docker.go (1)

1-1: LGTM! Comprehensive refactoring of Docker proxy handlers.

The refactoring successfully:

  • Migrates all configuration access to use config.GetConfig()
  • Updates all cache operations to use utils.GlobalCache and related functions
  • Properly uses utils.GlobalAccessController for access control
  • Updates function signatures to use the exported config.RegistryMapping type
  • Maintains all proxy functionality while improving modularity

Also applies to: 15-16, 32-58, 62-80, 122-122, 170-177, 219-223, 299-330, 440-440, 461-467, 513-517

src/main.go (2)

12-13: H2C support implementation looks good.

The HTTP/2 Cleartext support is properly implemented with:

  • Conditional enablement based on configuration
  • Reasonable stream limits and buffer sizes
  • Appropriate timeout configurations
  • Clear logging of H2C status

Also applies to: 124-150


44-116: Excellent modularization of main.go!

The refactoring successfully:

  • Delegates all initialization to dedicated packages
  • Removes embedded proxy logic in favor of handler packages
  • Simplifies the main function to focus on server setup
  • Improves the health check endpoint with cleaner implementation

Also applies to: 173-187

**Actionable comments posted: 2** <details> <summary>🧹 Nitpick comments (7)</summary><blockquote> <details> <summary>docker-compose.yml (1)</summary><blockquote> `1-8`: **Add trailing newline to satisfy YAML linters and POSIX tools** `yamllint` flagged the missing newline at EOF. Some tools (e.g. POSIX `sed`, `cat`) expect the last line to be newline-terminated; adding it avoids subtle processing glitches. ```diff - ./src/config.toml:/root/config.toml + ``` </blockquote></details> <details> <summary>src/go.mod (1)</summary><blockquote> `5-11`: **Run `go mod tidy` after promoting `golang.org/x/net` to direct** Promoting the dependency is sensible given the new H2C handler. Running ```bash go mod tidy ``` will prune any now-unused transitive deps and lock in the minimal `go.sum`. </blockquote></details> <details> <summary>README.md (2)</summary><blockquote> `112-114`: **Highlight security caveat for `enableH2C`** H2C (HTTP/2 cleartext) omits TLS. Recommend adding a doc note that it should only be enabled behind a trusted TLS-terminating reverse proxy to avoid downgrading security. --- `119-120`: **Rate-limit window change: update examples & alerts** The period changed to 3 h; ensure any alerting/monitoring or README examples (e.g. “每小时请求数”) are likewise updated so users don’t mis-interpret the limits. </blockquote></details> <details> <summary>src/config.toml (2)</summary><blockquote> `7-8`: **`enableH2C` defaults to false — ensure reverse proxy handles HTTP/2 if later enabled** Enabling H2C exposes the service over cleartext HTTP/2; verify your ingress (Caddy / Nginx) supports `h2c` upgrade, otherwise clients will fall back to HTTP/1.1 and lose multiplexing benefits. --- `14-14`: **Keep comment in sync: limit is now 3 h, not “每小时”** The Chinese comment still says “每小时允许的请求数”; with a 3-hour window that’s misleading. Consider updating to “每 3 小时”. </blockquote></details> <details> <summary>src/handlers/search.go (1)</summary><blockquote> `152-161`: **Consider goroutine lifecycle management.** The cleanup goroutine started in `init()` runs indefinitely without a shutdown mechanism. Consider: 1. Using a context for graceful shutdown 2. Providing a way to stop the cleanup routine when the application shuts down ```diff -func init() { - go func() { - ticker := time.NewTicker(5 * time.Minute) - defer ticker.Stop() - - for range ticker.C { - searchCache.Cleanup() - } - }() -} +var cleanupDone chan struct{} + +func init() { + cleanupDone = make(chan struct{}) + go func() { + ticker := time.NewTicker(5 * time.Minute) + defer ticker.Stop() + + for { + select { + case <-ticker.C: + searchCache.Cleanup() + case <-cleanupDone: + return + } + } + }() +} + +// StopCacheCleanup stops the cache cleanup goroutine +func StopCacheCleanup() { + if cleanupDone != nil { + close(cleanupDone) + } +} ``` </blockquote></details> </blockquote></details> <details> <summary>📜 Review details</summary> **Configuration used: CodeRabbit UI** **Review profile: CHILL** **Plan: Pro** <details> <summary>📥 Commits</summary> Reviewing files that changed from the base of the PR and between badafd289996837c6403fbfcc091481017c3ee66 and 07a926902accd889bff095d5b8ecf5b7ecbb0e1a. </details> <details> <summary>📒 Files selected for processing (15)</summary> * `README.md` (3 hunks) * `docker-compose.yml` (1 hunks) * `src/config.toml` (1 hunks) * `src/config/config.go` (6 hunks) * `src/go.mod` (1 hunks) * `src/handlers/docker.go` (17 hunks) * `src/handlers/github.go` (1 hunks) * `src/handlers/imagetar.go` (11 hunks) * `src/handlers/search.go` (1 hunks) * `src/main.go` (5 hunks) * `src/utils/access_control.go` (4 hunks) * `src/utils/cache.go` (6 hunks) * `src/utils/http_client.go` (2 hunks) * `src/utils/proxy_shell.go` (1 hunks) * `src/utils/ratelimiter.go` (7 hunks) </details> <details> <summary>🧰 Additional context used</summary> <details> <summary>🧬 Code Graph Analysis (5)</summary> <details> <summary>src/utils/http_client.go (2)</summary><blockquote> <details> <summary>src/config/config.go (1)</summary> * `GetConfig` (148-184) </details> <details> <summary>src/http_client.go (3)</summary> * `initHTTPClients` (18-58) * `GetGlobalHTTPClient` (61-63) * `GetSearchHTTPClient` (66-68) </details> </blockquote></details> <details> <summary>src/handlers/imagetar.go (3)</summary><blockquote> <details> <summary>src/config/config.go (1)</summary> * `GetConfig` (148-184) </details> <details> <summary>src/utils/http_client.go (1)</summary> * `GetGlobalHTTPClient` (60-62) </details> <details> <summary>src/imagetar.go (9)</summary> * `initDebouncer` (131-136) * `handleSimpleBatchDownload` (657-724) * `initImageTarRoutes` (595-602) * `handleDirectImageDownload` (605-654) * `StreamMultipleImages` (786-884) * `cleanup` (81-87) * `NewDownloadDebouncer` (43-49) * `processImageForBatch` (460-482) * `StreamImageToGin` (223-237) </details> </blockquote></details> <details> <summary>src/utils/access_control.go (1)</summary><blockquote> <details> <summary>src/config/config.go (1)</summary> * `GetConfig` (148-184) </details> </blockquote></details> <details> <summary>src/utils/cache.go (1)</summary><blockquote> <details> <summary>src/config/config.go (1)</summary> * `GetConfig` (148-184) </details> </blockquote></details> <details> <summary>src/handlers/docker.go (5)</summary><blockquote> <details> <summary>src/config/config.go (2)</summary> * `GetConfig` (148-184) * `RegistryMapping` (15-20) </details> <details> <summary>src/utils/http_client.go (1)</summary> * `GetGlobalHTTPClient` (60-62) </details> <details> <summary>src/utils/access_control.go (1)</summary> * `GlobalAccessController` (32-32) </details> <details> <summary>src/utils/cache.go (9)</summary> * `IsCacheEnabled` (132-135) * `BuildManifestCacheKey` (70-73) * `GlobalCache` (28-28) * `WriteCachedResponse` (119-129) * `GetManifestTTL` (75-94) * `IsTokenCacheEnabled` (138-140) * `BuildTokenCacheKey` (66-68) * `WriteTokenResponse` (114-117) * `ExtractTTLFromResponse` (97-112) </details> <details> <summary>src/docker.go (9)</summary> * `proxyDockerAuthOriginal` (388-466) * `ProxyDockerRegistryGin` (85-100) * `handleRegistryRequest` (103-150) * `rewriteAuthHeader` (469-477) * `handleUpstreamManifestRequest` (520-593) * `handleMultiRegistryRequest` (480-517) * `handleManifestRequest` (180-256) * `ProxyDockerAuthGin` (331-338) * `proxyDockerAuthWithCache` (341-370) </details> </blockquote></details> </details><details> <summary>🪛 YAMLlint (1.37.1)</summary> <details> <summary>docker-compose.yml</summary> [error] 8-8: no new line character at the end of file (new-line-at-end-of-file) </details> </details> </details> <details> <summary>🔇 Additional comments (25)</summary><blockquote> <details> <summary>docker-compose.yml (1)</summary> `1-8`: **Confirm indentation convention is now 2 spaces project-wide** You switched this file from 4- to 2-space indents. If other YAML manifests in the repo still use 4 spaces, consider normalising to one style to avoid churn in future diffs. </details> <details> <summary>src/utils/proxy_shell.go (1)</summary> `1-1`: **Package rename looks correct; verify all import paths compile** Moving the file into `package utils` is consistent with the refactor, but make sure all call-sites have updated imports (`hubproxy/utils` or equivalent). A quick `go vet ./...` + `go test ./...` after `go mod tidy` will catch any dangling references. </details> <details> <summary>README.md (2)</summary> `40-41`: **Verify updated install script URL exists** `install-service.sh` → `install.sh` change is fine, but please confirm the new script is pushed to `main` and is executable; broken quick-start links frustrate first-time users. --- `137-149`: **Section renamed to `[access]`; double-check code uses new key** Config struct tags and env-var overrides must match this rename. A mismatch silently falls back to defaults. </details> <details> <summary>src/utils/access_control.go (3)</summary> `1-1`: **LGTM! Package restructuring looks good.** The package name change to `utils` and the addition of the config import are consistent with the modularization efforts in this PR. Also applies to: 6-7 --- `31-31`: **Good improvement: English documentation.** Translating the comment to English improves code accessibility for international contributors. --- `84-84`: **Correct usage of centralized config.** The updates to use `config.GetConfig()` properly leverage the centralized configuration package. Also applies to: 109-109 </details> <details> <summary>src/utils/http_client.go (2)</summary> `1-1`: **Package restructuring is consistent.** The package name change and config import align with the overall modularization approach. Also applies to: 8-9 --- `17-19`: **Properly exported HTTP client functions.** The exported function names follow Go conventions and provide appropriate access to the HTTP clients from other packages. Also applies to: 59-60, 64-65 </details> <details> <summary>src/config/config.go (4)</summary> `1-1`: **Appropriate package name for configuration module.** The `config` package name correctly reflects the module's purpose. --- `28-28`: **Well-implemented H2C support.** The HTTP/2 Cleartext support is properly implemented with: - Opt-in by default (false) - Configuration via TOML and environment variable - Proper error handling for boolean parsing This aligns perfectly with the PR objective. Also applies to: 76-77, 81-81, 225-229 --- `87-88`: **Verify the rate limit configuration changes.** The request limit increased from 20 to 200 (10x increase). The AI summary mentions the period was extended to 3 hours, but the code shows `PeriodHours: 1.0`. Please confirm: 1. Is the 10x rate limit increase intentional and based on actual usage patterns? 2. Should `PeriodHours` be 3.0 instead of 1.0? > Likely an incorrect or invalid review comment. --- `16-20`: **Well-structured configuration types.** The struct definitions with TOML tags are properly implemented for configuration serialization. Also applies to: 25-29 </details> <details> <summary>src/handlers/search.go (2)</summary> `1-17`: **Well-structured handler package.** The package organization and imports are appropriate for a search handler module. --- `279-279`: **Correct usage of search HTTP client.** Properly uses the search-specific HTTP client from utils package with appropriate timeouts for API calls. Also applies to: 432-432 </details> <details> <summary>src/handlers/github.go (2)</summary> `17-30`: **Comprehensive URL pattern matching.** The regex patterns cover all major GitHub-related services and are pre-compiled for performance. --- `93-98`: **Good redirect loop protection.** The implementation properly limits redirects to 20 and returns an appropriate HTTP 508 status code. </details> <details> <summary>src/utils/ratelimiter.go (3)</summary> `1-1`: **LGTM! Package refactoring aligns with modularization.** The package rename from `main` to `utils` and import update to use `hubproxy/config` are consistent with the broader refactoring effort. Also applies to: 12-12 --- `28-28`: **Good optimization for whitelist IP handling.** The addition of a shared `whitelistLimiter` with infinite rate is an efficient approach that: - Reduces memory usage by avoiding individual limiter creation for each whitelist IP - Clearly indicates that whitelist IPs have no rate limiting - Maintains burst size configuration for consistency Also applies to: 85-85, 174-175 --- `45-45`: **Minor: String concatenation style change.** The change from compound assignment to explicit concatenation is functionally equivalent. Both approaches work correctly in this context. Also applies to: 60-60 </details> <details> <summary>src/handlers/imagetar.go (1)</summary> `1-1`: **LGTM! Clean modularization of image streaming functionality.** The refactoring successfully: - Moves functionality to the `handlers` package - Exports initialization functions for external use - Centralizes configuration and HTTP client access through `config` and `utils` packages - Maintains all core functionality while improving modularity Also applies to: 26-27, 123-127, 141-157, 563-566, 576-584 </details> <details> <summary>src/utils/cache.go (1)</summary> `1-1`: **LGTM! Well-structured cache utilities export.** The refactoring properly: - Exports cache types and functions for cross-package use - Creates a global `GlobalCache` instance safely initialized - Centralizes configuration access through the `config` package - Maintains thread-safe operations with the existing sync.Map Also applies to: 12-12, 15-28, 61-140 </details> <details> <summary>src/handlers/docker.go (1)</summary> `1-1`: **LGTM! Comprehensive refactoring of Docker proxy handlers.** The refactoring successfully: - Migrates all configuration access to use `config.GetConfig()` - Updates all cache operations to use `utils.GlobalCache` and related functions - Properly uses `utils.GlobalAccessController` for access control - Updates function signatures to use the exported `config.RegistryMapping` type - Maintains all proxy functionality while improving modularity Also applies to: 15-16, 32-58, 62-80, 122-122, 170-177, 219-223, 299-330, 440-440, 461-467, 513-517 </details> <details> <summary>src/main.go (2)</summary> `12-13`: **H2C support implementation looks good.** The HTTP/2 Cleartext support is properly implemented with: - Conditional enablement based on configuration - Reasonable stream limits and buffer sizes - Appropriate timeout configurations - Clear logging of H2C status Also applies to: 124-150 --- `44-116`: **Excellent modularization of main.go!** The refactoring successfully: - Delegates all initialization to dedicated packages - Removes embedded proxy logic in favor of handler packages - Simplifies the main function to focus on server setup - Improves the health check endpoint with cleaner implementation Also applies to: 173-187 </details> </blockquote></details> </details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
@@ -0,0 +109,4 @@
req.Header.Add(key, value)
}
}
req.Header.Del("Host")
coderabbitai[bot] (Migrated from github.com) commented 2025-07-27 12:00:55 +08:00

🛠️ Refactor suggestion

Consider filtering sensitive request headers.

While copying headers, consider filtering out potentially sensitive or problematic headers:

  • Authorization (unless intentionally proxying auth)
  • Cookie and Set-Cookie
  • X-Forwarded-* headers that might conflict
 // 复制请求头
 for key, values := range c.Request.Header {
+    // Skip potentially sensitive headers
+    if key == "Authorization" || key == "Cookie" || strings.HasPrefix(key, "X-Forwarded-") {
+        continue
+    }
     for _, value := range values {
         req.Header.Add(key, value)
     }
 }
 req.Header.Del("Host")
📝 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.

	// 复制请求头
	for key, values := range c.Request.Header {
		// Skip potentially sensitive headers
		if key == "Authorization" || key == "Cookie" || strings.HasPrefix(key, "X-Forwarded-") {
			continue
		}
		for _, value := range values {
			req.Header.Add(key, value)
		}
	}
	req.Header.Del("Host")
🤖 Prompt for AI Agents
In src/handlers/github.go around lines 106 to 112, the code copies all request
headers without filtering, which may expose sensitive headers like
Authorization, Cookie, Set-Cookie, and X-Forwarded-* headers. Modify the header
copying loop to skip these sensitive headers by checking the header key and
excluding them from being added to req.Header.
_🛠️ Refactor suggestion_ **Consider filtering sensitive request headers.** While copying headers, consider filtering out potentially sensitive or problematic headers: - `Authorization` (unless intentionally proxying auth) - `Cookie` and `Set-Cookie` - `X-Forwarded-*` headers that might conflict ```diff // 复制请求头 for key, values := range c.Request.Header { + // Skip potentially sensitive headers + if key == "Authorization" || key == "Cookie" || strings.HasPrefix(key, "X-Forwarded-") { + continue + } for _, value := range values { req.Header.Add(key, value) } } req.Header.Del("Host") ``` <!-- suggestion_start --> <details> <summary>📝 Committable suggestion</summary> > ‼️ **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. ```suggestion // 复制请求头 for key, values := range c.Request.Header { // Skip potentially sensitive headers if key == "Authorization" || key == "Cookie" || strings.HasPrefix(key, "X-Forwarded-") { continue } for _, value := range values { req.Header.Add(key, value) } } req.Header.Del("Host") ``` </details> <!-- suggestion_end --> <details> <summary>🤖 Prompt for AI Agents</summary> ``` In src/handlers/github.go around lines 106 to 112, the code copies all request headers without filtering, which may expose sensitive headers like Authorization, Cookie, Set-Cookie, and X-Forwarded-* headers. Modify the header copying loop to skip these sensitive headers by checking the header key and excluding them from being added to req.Header. ``` </details> <!-- fingerprinting:phantom:medusa:lion --> <!-- This is an auto-generated comment by CodeRabbit -->
@@ -0,0 +187,4 @@
if _, err := io.Copy(c.Writer, processedBody); err != nil {
return
}
} else {
coderabbitai[bot] (Migrated from github.com) commented 2025-07-27 12:00:55 +08:00

💡 Verification agent

🧩 Analysis chain

Clarify the purpose of .sh file processing.

The code performs special processing on .sh files using utils.ProcessSmart. Please document:

  1. What modifications are being made to shell scripts?
  2. Are there security implications of modifying executable content?
  3. What's the use case for this feature?

🏁 Script executed:

#!/bin/bash
# Search for the ProcessSmart implementation to understand what it does
ast-grep --pattern 'func ProcessSmart($$$) {
  $$$
}'

Length of output: 55


🏁 Script executed:

#!/bin/bash
# Search for ProcessSmart references and implementation across the repository
rg "ProcessSmart" -n .

Length of output: 337


🏁 Script executed:

#!/bin/bash
# Display the full implementation of ProcessSmart in utils/proxy_shell.go
sed -n '1,200p' src/utils/proxy_shell.go

Length of output: 2472


Please document and safeguard .sh file processing logic

We’ve confirmed that ProcessSmart in utils/proxy_shell.go:

  • Handles optional gzip by peeking and unwrapping if needed
  • Reads the entire script into memory (unless >10 MB or no GitHub URLs)
  • Uses githubRegex to locate all GitHub‐hosted URLs and rewrites each via transformURL(host)
  • Returns a new io.Reader of the (potentially) modified script

To help future maintainers and ensure safety, please:

• In src/utils/proxy_shell.go (ProcessSmart, lines ~16–54):
– Add a top-level doc comment describing each step (decompression, size check, URL rewrite)
– Call out any edge cases (e.g. very large scripts, scripts without GitHub links)
– Note security considerations around modifying executable content (shebang integrity, unintended regex matches)

• In src/handlers/github.go (lines 150–190):
– Explain the .sh branch’s purpose: why and when you proxy/modify scripts
– Document the impact on downstream clients (chunked responses, URL schemes)

• Add or update unit/integration tests covering:
– A small script with GitHub URLs (verify correct rewrite and valid URL syntax)
– A gzipped script
– A large script (>10 MB) and one without GitHub URLs (ensure no modifications)

This will clarify intent, guard against inadvertent breakage, and surface any security risks.

🤖 Prompt for AI Agents
In src/handlers/github.go around lines 150 to 190, add clear comments explaining
the purpose of the .sh file processing branch, detailing why scripts are proxied
and modified, and how the response headers are adjusted (e.g., chunked transfer
encoding) to inform downstream clients. In src/utils/proxy_shell.go within the
ProcessSmart function (lines ~16–54), add a comprehensive top-level doc comment
describing each processing step: decompression if gzip encoded, size checks to
avoid large memory usage, GitHub URL detection and rewriting, and returning the
modified script reader. Also document edge cases like very large scripts or
scripts without GitHub URLs, and note security considerations such as preserving
shebang integrity and avoiding unintended regex matches. Finally, add or update
unit and integration tests to cover scenarios including small scripts with
GitHub URLs (verifying correct URL rewriting), gzipped scripts, large scripts
over 10 MB, and scripts without GitHub URLs to ensure no modifications occur.
_💡 Verification agent_ <details> <summary>🧩 Analysis chain</summary> **Clarify the purpose of .sh file processing.** The code performs special processing on `.sh` files using `utils.ProcessSmart`. Please document: 1. What modifications are being made to shell scripts? 2. Are there security implications of modifying executable content? 3. What's the use case for this feature? --- 🏁 Script executed: ```shell #!/bin/bash # Search for the ProcessSmart implementation to understand what it does ast-grep --pattern 'func ProcessSmart($$$) { $$$ }' ``` Length of output: 55 --- 🏁 Script executed: ```shell #!/bin/bash # Search for ProcessSmart references and implementation across the repository rg "ProcessSmart" -n . ``` Length of output: 337 --- 🏁 Script executed: ```shell #!/bin/bash # Display the full implementation of ProcessSmart in utils/proxy_shell.go sed -n '1,200p' src/utils/proxy_shell.go ``` Length of output: 2472 --- </details> **Please document and safeguard `.sh` file processing logic** We’ve confirmed that `ProcessSmart` in `utils/proxy_shell.go`: - Handles optional gzip by peeking and unwrapping if needed - Reads the entire script into memory (unless >10 MB or no GitHub URLs) - Uses `githubRegex` to locate all GitHub‐hosted URLs and rewrites each via `transformURL(host)` - Returns a new `io.Reader` of the (potentially) modified script To help future maintainers and ensure safety, please: • In `src/utils/proxy_shell.go` (ProcessSmart, lines ~16–54): – Add a top-level doc comment describing each step (decompression, size check, URL rewrite) – Call out any edge cases (e.g. very large scripts, scripts without GitHub links) – Note security considerations around modifying executable content (shebang integrity, unintended regex matches) • In `src/handlers/github.go` (lines 150–190): – Explain the `.sh` branch’s purpose: why and when you proxy/modify scripts – Document the impact on downstream clients (chunked responses, URL schemes) • Add or update unit/integration tests covering: – A small script with GitHub URLs (verify correct rewrite and valid URL syntax) – A gzipped script – A large script (>10 MB) and one without GitHub URLs (ensure no modifications) This will clarify intent, guard against inadvertent breakage, and surface any security risks. <details> <summary>🤖 Prompt for AI Agents</summary> ``` In src/handlers/github.go around lines 150 to 190, add clear comments explaining the purpose of the .sh file processing branch, detailing why scripts are proxied and modified, and how the response headers are adjusted (e.g., chunked transfer encoding) to inform downstream clients. In src/utils/proxy_shell.go within the ProcessSmart function (lines ~16–54), add a comprehensive top-level doc comment describing each processing step: decompression if gzip encoded, size checks to avoid large memory usage, GitHub URL detection and rewriting, and returning the modified script reader. Also document edge cases like very large scripts or scripts without GitHub URLs, and note security considerations such as preserving shebang integrity and avoiding unintended regex matches. Finally, add or update unit and integration tests to cover scenarios including small scripts with GitHub URLs (verifying correct URL rewriting), gzipped scripts, large scripts over 10 MB, and scripts without GitHub URLs to ensure no modifications occur. ``` </details> <!-- fingerprinting:phantom:medusa:lion --> <!-- This is an auto-generated comment by CodeRabbit -->
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: 3344/hubproxy#39