support/gobds: Support GoBDS & add VPN Blocker. #11

Merged
glancist merged 21 commits from support/gobds into main 2025-07-04 12:27:43 +00:00
glancist commented 2025-06-06 13:37:29 +00:00 (Migrated from github.com)

https://github.com/smell-of-curry/gobds

Summary by CodeRabbit

  • New Features

    • Introduced an HTTP authentication service with a secure endpoint for validating player identities.
    • Added management of player identities with automatic expiration and cleanup.
    • Expanded configuration options to include authentication URL and key settings.
    • Integrated VPN detection service to check and block VPN or proxy connections.
  • Improvements

    • Player identities are now registered for authentication upon successful server transfer.
    • Enhanced connection allowance logic to disallow VPN or proxy IPs with informative messages.
  • Bug Fixes

    • Improved handling of expired or missing authentication requests, providing appropriate HTTP responses.
https://github.com/smell-of-curry/gobds <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced an HTTP authentication service with a secure endpoint for validating player identities. - Added management of player identities with automatic expiration and cleanup. - Expanded configuration options to include authentication URL and key settings. - Integrated VPN detection service to check and block VPN or proxy connections. - **Improvements** - Player identities are now registered for authentication upon successful server transfer. - Enhanced connection allowance logic to disallow VPN or proxy IPs with informative messages. - **Bug Fixes** - Improved handling of expired or missing authentication requests, providing appropriate HTTP responses. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
coderabbitai[bot] commented 2025-06-06 13:37:35 +00:00 (Migrated from github.com)

Walkthrough

These changes introduce an HTTP authentication service using the Gin web framework, adding an endpoint to validate player identities. A thread-safe singleton factory manages player identities with expiration, and player authentication requests are registered upon successful server transfer. Configuration is extended to support authentication parameters, a VPN check service is integrated, and dependencies are updated in go.mod.

Changes

File(s) Change Summary
go.mod Upgraded golang.org/x/text and several indirect dependencies; added new indirect dependencies including Gin.
pokebedrock/authentication/factory.go, identity.go Added thread-safe singleton factory for player identities with expiration and PlayerIdentity struct.
pokebedrock/config.go Added GinAddress, VpnURL, AuthenticationPrefix, and AuthenticationKey fields to config; set defaults.
pokebedrock/pokebedrock.go Added Gin-based HTTP authentication service with authorization middleware and endpoint; started service async; integrated VPN service initialization and shutdown.
pokebedrock/queue/manager.go Registered player identity with authentication factory after successful player transfer.
pokebedrock/allower.go Added VPN/proxy check before allowing connection; disallow or flag proxy addresses accordingly.
pokebedrock/vpn/model.go Added VPN response model struct and status constants.
pokebedrock/vpn/service.go Added VPN service with HTTP client, rate limiting, retry logic, and IP check method; global singleton service.
config.toml.example Added comments and new configuration keys for GinAddress, VpnURL, AuthenticationPrefix, and AuthenticationKey.

Sequence Diagram(s)

sequenceDiagram
    participant Player
    participant QueueManager
    participant AuthFactory
    participant GinServer
    participant VPNService

    Player->>QueueManager: Request server transfer
    QueueManager->>Player: Transfer to server
    QueueManager->>AuthFactory: Set(name, xuid, 5m) on success

    external Client->>GinServer: GET /{AuthenticationPrefix}/:xuid (with Authorization header)
    GinServer->>AuthFactory: Of(xuid)
    alt Identity not found
        GinServer-->>Client: 404 Not Found
    else Identity expired
        GinServer->>AuthFactory: Remove(xuid)
        GinServer-->>Client: 410 Gone
    else Valid identity
        GinServer-->>Client: 200 OK, { allowed: true }
    end

    Player->>Allower: Connect with net.Addr
    Allower->>VPNService: CheckIP(ip)
    alt VPN or proxy detected
        Allower-->>Player: Disallow connection with reason
    else Allowed
        Allower->>Player: Continue checks and allow
    end

Poem

In the warren of code, a new path appears,
With Gin and good cheer, authentication nears.
Identities hop in, with names and expiry,
Five minutes of fame, then cleaned in a hurry!
VPNs checked, proxies caught in the net,
Secure little bunnies, the safest yet! 🥕🐇

Finishing Touches
  • 📝 Generate Docstrings

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 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 These changes introduce an HTTP authentication service using the Gin web framework, adding an endpoint to validate player identities. A thread-safe singleton factory manages player identities with expiration, and player authentication requests are registered upon successful server transfer. Configuration is extended to support authentication parameters, a VPN check service is integrated, and dependencies are updated in `go.mod`. ## Changes | File(s) | Change Summary | |----------------------------------------------------|----------------------------------------------------------------------------------------------------------------| | go.mod | Upgraded `golang.org/x/text` and several indirect dependencies; added new indirect dependencies including Gin. | | pokebedrock/authentication/factory.go, identity.go | Added thread-safe singleton factory for player identities with expiration and `PlayerIdentity` struct. | | pokebedrock/config.go | Added `GinAddress`, `VpnURL`, `AuthenticationPrefix`, and `AuthenticationKey` fields to config; set defaults. | | pokebedrock/pokebedrock.go | Added Gin-based HTTP authentication service with authorization middleware and endpoint; started service async; integrated VPN service initialization and shutdown. | | pokebedrock/queue/manager.go | Registered player identity with authentication factory after successful player transfer. | | pokebedrock/allower.go | Added VPN/proxy check before allowing connection; disallow or flag proxy addresses accordingly. | | pokebedrock/vpn/model.go | Added VPN response model struct and status constants. | | pokebedrock/vpn/service.go | Added VPN service with HTTP client, rate limiting, retry logic, and IP check method; global singleton service. | | config.toml.example | Added comments and new configuration keys for GinAddress, VpnURL, AuthenticationPrefix, and AuthenticationKey. | ## Sequence Diagram(s) ```mermaid sequenceDiagram participant Player participant QueueManager participant AuthFactory participant GinServer participant VPNService Player->>QueueManager: Request server transfer QueueManager->>Player: Transfer to server QueueManager->>AuthFactory: Set(name, xuid, 5m) on success external Client->>GinServer: GET /{AuthenticationPrefix}/:xuid (with Authorization header) GinServer->>AuthFactory: Of(xuid) alt Identity not found GinServer-->>Client: 404 Not Found else Identity expired GinServer->>AuthFactory: Remove(xuid) GinServer-->>Client: 410 Gone else Valid identity GinServer-->>Client: 200 OK, { allowed: true } end Player->>Allower: Connect with net.Addr Allower->>VPNService: CheckIP(ip) alt VPN or proxy detected Allower-->>Player: Disallow connection with reason else Allowed Allower->>Player: Continue checks and allow end ``` ## Poem > In the warren of code, a new path appears, > With Gin and good cheer, authentication nears. > Identities hop in, with names and expiry, > Five minutes of fame, then cleaned in a hurry! > VPNs checked, proxies caught in the net, > Secure little bunnies, the safest yet! 🥕🐇 <!-- walkthrough_end --> <!-- internal state start --> <!-- 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 --> <!-- internal state end --> <!-- finishing_touch_checkbox_start --> <details open="true"> <summary>✨ Finishing Touches</summary> - [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings </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=smell-of-curry/pokebedrock-hub&utm_content=11): - 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 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-06-06 13:42:25 +00:00
coderabbitai[bot] (Migrated from github.com) left a comment

Actionable comments posted: 5

🧹 Nitpick comments (4)
pokebedrock/queue/manager.go (1)

216-218: Add error handling for authentication factory call.

The authentication integration is well-placed after successful transfer, but consider adding error handling for the factory call to ensure robustness.

Consider applying this diff to add error handling:

		} else {
			// Transfer was successful, send player data to authentication factory.
-			authentication.GlobalFactory().Set(p.Name(), p.XUID(), time.Minute*5)
+			if err := authentication.GlobalFactory().Set(p.Name(), p.XUID(), time.Minute*5); err != nil {
+				// Log the error but don't fail the transfer
+				// The transfer was successful, authentication registration is auxiliary
+			}
		}

Note: This assumes the Set method will be updated to return an error. If it doesn't return an error, the current implementation is appropriate.

pokebedrock/authentication/factory.go (3)

49-58: Improve method documentation.

The method documentation is incomplete and should be more descriptive.

Improve the documentation:

-// Set ...
+// Set stores a player identity with the given name and XUID for the specified duration.
+// The identity will automatically expire after the duration has passed.
 func (f *Factory) Set(name string, xuid string, duration time.Duration) {

60-66: Improve method documentation.

The method documentation is incomplete and should be more descriptive.

Improve the documentation:

-// Of ...
+// Of retrieves a player identity by XUID. Returns the identity and a boolean
+// indicating whether the identity exists in the factory.
 func (f *Factory) Of(xuid string) (PlayerIdentity, bool) {

68-73: Improve method documentation.

The method documentation is incomplete and should be more descriptive.

Improve the documentation:

-// Remove ...
+// Remove deletes a player identity from the factory by XUID.
+// This operation is idempotent - removing a non-existent identity is safe.
 func (f *Factory) Remove(xuid string) {
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 298c2748e5 and e6ddedaccb.

Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (6)
  • go.mod (1 hunks)
  • pokebedrock/authentication/factory.go (1 hunks)
  • pokebedrock/authentication/identity.go (1 hunks)
  • pokebedrock/config.go (3 hunks)
  • pokebedrock/pokebedrock.go (3 hunks)
  • pokebedrock/queue/manager.go (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
pokebedrock/config.go (2)
pokebedrock/moderation/service.go (1)
  • Service (29-36)
pokebedrock/rank/service.go (1)
  • Service (28-34)
pokebedrock/authentication/factory.go (1)
pokebedrock/authentication/identity.go (1)
  • PlayerIdentity (6-10)
pokebedrock/pokebedrock.go (1)
pokebedrock/authentication/factory.go (1)
  • GlobalFactory (12-14)
🔇 Additional comments (6)
pokebedrock/config.go (1)

27-32: LGTM! Well-structured configuration additions.

The new authentication service configuration fields follow the existing pattern and integrate well with the Service struct.

go.mod (1)

15-64: LGTM! Dependency updates support the new authentication service.

The dependency additions and upgrades are appropriate for implementing the Gin-based HTTP authentication service. The new packages (gin-gonic, sonic, validator) provide the necessary functionality for the web service implementation.

pokebedrock/queue/manager.go (1)

12-12: LGTM! Appropriate import for authentication integration.

The authentication package import is correctly placed and necessary for the new functionality.

pokebedrock/authentication/identity.go (1)

5-10: LGTM! Well-designed authentication data model.

The PlayerIdentity struct is cleanly designed with appropriate fields for authentication purposes. The JSON tags are correctly configured for API serialization, and the inclusion of an expiration field supports time-based authentication management.

pokebedrock/pokebedrock.go (1)

5-5: LGTM: Import additions are appropriate.

The new imports (net/http, gin-gonic/gin, and local authentication package) are correctly added and align with the HTTP authentication service implementation.

Also applies to: 12-13

pokebedrock/authentication/factory.go (1)

8-14: LGTM: Singleton pattern correctly implemented.

The global factory singleton pattern is properly implemented with a simple accessor function.

**Actionable comments posted: 5** <details> <summary>🧹 Nitpick comments (4)</summary><blockquote> <details> <summary>pokebedrock/queue/manager.go (1)</summary><blockquote> `216-218`: **Add error handling for authentication factory call.** The authentication integration is well-placed after successful transfer, but consider adding error handling for the factory call to ensure robustness. Consider applying this diff to add error handling: ```diff } else { // Transfer was successful, send player data to authentication factory. - authentication.GlobalFactory().Set(p.Name(), p.XUID(), time.Minute*5) + if err := authentication.GlobalFactory().Set(p.Name(), p.XUID(), time.Minute*5); err != nil { + // Log the error but don't fail the transfer + // The transfer was successful, authentication registration is auxiliary + } } ``` Note: This assumes the `Set` method will be updated to return an error. If it doesn't return an error, the current implementation is appropriate. </blockquote></details> <details> <summary>pokebedrock/authentication/factory.go (3)</summary><blockquote> `49-58`: **Improve method documentation.** The method documentation is incomplete and should be more descriptive. Improve the documentation: ```diff -// Set ... +// Set stores a player identity with the given name and XUID for the specified duration. +// The identity will automatically expire after the duration has passed. func (f *Factory) Set(name string, xuid string, duration time.Duration) { ``` --- `60-66`: **Improve method documentation.** The method documentation is incomplete and should be more descriptive. Improve the documentation: ```diff -// Of ... +// Of retrieves a player identity by XUID. Returns the identity and a boolean +// indicating whether the identity exists in the factory. func (f *Factory) Of(xuid string) (PlayerIdentity, bool) { ``` --- `68-73`: **Improve method documentation.** The method documentation is incomplete and should be more descriptive. Improve the documentation: ```diff -// Remove ... +// Remove deletes a player identity from the factory by XUID. +// This operation is idempotent - removing a non-existent identity is safe. func (f *Factory) Remove(xuid string) { ``` </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 298c2748e5f8923dfca609ffb55dbb5de34dbbb2 and e6ddedaccb36ab167cd6bbd39e09ccd3b6436efb. </details> <details> <summary>⛔ Files ignored due to path filters (1)</summary> * `go.sum` is excluded by `!**/*.sum` </details> <details> <summary>📒 Files selected for processing (6)</summary> * `go.mod` (1 hunks) * `pokebedrock/authentication/factory.go` (1 hunks) * `pokebedrock/authentication/identity.go` (1 hunks) * `pokebedrock/config.go` (3 hunks) * `pokebedrock/pokebedrock.go` (3 hunks) * `pokebedrock/queue/manager.go` (2 hunks) </details> <details> <summary>🧰 Additional context used</summary> <details> <summary>🧬 Code Graph Analysis (3)</summary> <details> <summary>pokebedrock/config.go (2)</summary><blockquote> <details> <summary>pokebedrock/moderation/service.go (1)</summary> * `Service` (29-36) </details> <details> <summary>pokebedrock/rank/service.go (1)</summary> * `Service` (28-34) </details> </blockquote></details> <details> <summary>pokebedrock/authentication/factory.go (1)</summary><blockquote> <details> <summary>pokebedrock/authentication/identity.go (1)</summary> * `PlayerIdentity` (6-10) </details> </blockquote></details> <details> <summary>pokebedrock/pokebedrock.go (1)</summary><blockquote> <details> <summary>pokebedrock/authentication/factory.go (1)</summary> * `GlobalFactory` (12-14) </details> </blockquote></details> </details> </details> <details> <summary>🔇 Additional comments (6)</summary><blockquote> <details> <summary>pokebedrock/config.go (1)</summary> `27-32`: **LGTM! Well-structured configuration additions.** The new authentication service configuration fields follow the existing pattern and integrate well with the Service struct. </details> <details> <summary>go.mod (1)</summary> `15-64`: **LGTM! Dependency updates support the new authentication service.** The dependency additions and upgrades are appropriate for implementing the Gin-based HTTP authentication service. The new packages (gin-gonic, sonic, validator) provide the necessary functionality for the web service implementation. </details> <details> <summary>pokebedrock/queue/manager.go (1)</summary> `12-12`: **LGTM! Appropriate import for authentication integration.** The authentication package import is correctly placed and necessary for the new functionality. </details> <details> <summary>pokebedrock/authentication/identity.go (1)</summary> `5-10`: **LGTM! Well-designed authentication data model.** The `PlayerIdentity` struct is cleanly designed with appropriate fields for authentication purposes. The JSON tags are correctly configured for API serialization, and the inclusion of an expiration field supports time-based authentication management. </details> <details> <summary>pokebedrock/pokebedrock.go (1)</summary> `5-5`: **LGTM: Import additions are appropriate.** The new imports (`net/http`, `gin-gonic/gin`, and local authentication package) are correctly added and align with the HTTP authentication service implementation. Also applies to: 12-13 </details> <details> <summary>pokebedrock/authentication/factory.go (1)</summary> `8-14`: **LGTM: Singleton pattern correctly implemented.** The global factory singleton pattern is properly implemented with a simple accessor function. </details> </blockquote></details> </details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
@ -0,0 +1,72 @@
package authentication
coderabbitai[bot] (Migrated from github.com) commented 2025-06-06 13:42:25 +00:00

🛠️ Refactor suggestion

Address hardcoded cleanup interval and lifecycle management.

The initialization has a hardcoded cleanup interval and lacks proper lifecycle management.

Consider making the cleanup interval configurable and add proper shutdown:

 func init() {
 	globalFactory = &Factory{
 		data: make(map[string]PlayerIdentity),
 	}
-	globalFactory.startCleanup(time.Minute * 5)
+	globalFactory.startCleanup(time.Minute * 5) // Consider making this configurable
 }

Also, consider adding a Stop() method to the Factory to gracefully shutdown the cleanup goroutine.

📝 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.

func init() {
	globalFactory = &Factory{
		data: make(map[string]PlayerIdentity),
	}
	globalFactory.startCleanup(time.Minute * 5) // Consider making this configurable
}
🤖 Prompt for AI Agents
In pokebedrock/authentication/factory.go around lines 16 to 21, the cleanup
interval is hardcoded and there is no lifecycle management for the cleanup
goroutine. Refactor the code to accept a configurable cleanup interval, possibly
via a parameter or configuration variable. Additionally, implement a Stop()
method on the Factory struct that signals the cleanup goroutine to exit
gracefully, ensuring proper shutdown and resource cleanup.
_🛠️ Refactor suggestion_ **Address hardcoded cleanup interval and lifecycle management.** The initialization has a hardcoded cleanup interval and lacks proper lifecycle management. Consider making the cleanup interval configurable and add proper shutdown: ```diff func init() { globalFactory = &Factory{ data: make(map[string]PlayerIdentity), } - globalFactory.startCleanup(time.Minute * 5) + globalFactory.startCleanup(time.Minute * 5) // Consider making this configurable } ``` Also, consider adding a `Stop()` method to the Factory to gracefully shutdown the cleanup goroutine. <!-- 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 func init() { globalFactory = &Factory{ data: make(map[string]PlayerIdentity), } globalFactory.startCleanup(time.Minute * 5) // Consider making this configurable } ``` </details> <!-- suggestion_end --> <details> <summary>🤖 Prompt for AI Agents</summary> ``` In pokebedrock/authentication/factory.go around lines 16 to 21, the cleanup interval is hardcoded and there is no lifecycle management for the cleanup goroutine. Refactor the code to accept a configurable cleanup interval, possibly via a parameter or configuration variable. Additionally, implement a Stop() method on the Factory struct that signals the cleanup goroutine to exit gracefully, ensuring proper shutdown and resource cleanup. ``` </details> <!-- This is an auto-generated comment by CodeRabbit -->
coderabbitai[bot] (Migrated from github.com) commented 2025-06-06 13:42:25 +00:00

🛠️ Refactor suggestion

⚠️ Potential issue

Fix variable naming and add goroutine lifecycle management.

The cleanup routine has a variable naming issue and lacks proper shutdown mechanism.

Issues identified:

  1. Variable name should be xuid as it represents the XUID key
  2. No way to stop the cleanup goroutine, causing potential goroutine leak

Apply this fix:

 func (f *Factory) startCleanup(interval time.Duration) {
 	ticker := time.NewTicker(interval)
 	go func() {
+		defer ticker.Stop()
 		for range ticker.C {
 			f.mu.Lock()
 			now := time.Now()
-			for name, identity := range f.data {
+			for xuid, identity := range f.data {
 				if now.After(identity.Expiration) {
-					delete(f.data, name)
+					delete(f.data, xuid)
 				}
 			}
 			f.mu.Unlock()
 		}
 	}()
 }

Consider adding a shutdown mechanism to the Factory:

+// Stop gracefully shuts down the factory's cleanup routine.
+func (f *Factory) Stop() {
+	// Implementation depends on how you want to manage the ticker lifecycle
+}
📝 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.

// startCleanup begins a periodic cleanup routine that removes expired identities.
// The interval parameter determines how often cleanup occurs.
func (f *Factory) startCleanup(interval time.Duration) {
    ticker := time.NewTicker(interval)
    go func() {
        defer ticker.Stop()
        for range ticker.C {
            f.mu.Lock()
            now := time.Now()
            for xuid, identity := range f.data {
                if now.After(identity.Expiration) {
                    delete(f.data, xuid)
                }
            }
            f.mu.Unlock()
        }
    }()
}
🤖 Prompt for AI Agents
In pokebedrock/authentication/factory.go lines 31 to 47, rename the loop
variable from 'name' to 'xuid' to correctly reflect that it represents the XUID
key. Additionally, add a shutdown mechanism to the Factory struct to manage the
lifecycle of the cleanup goroutine by introducing a stop channel or context that
the goroutine listens to, allowing it to exit cleanly when the Factory is
stopped, preventing goroutine leaks.
_🛠️ Refactor suggestion_ _⚠️ Potential issue_ **Fix variable naming and add goroutine lifecycle management.** The cleanup routine has a variable naming issue and lacks proper shutdown mechanism. Issues identified: 1. Variable `name` should be `xuid` as it represents the XUID key 2. No way to stop the cleanup goroutine, causing potential goroutine leak Apply this fix: ```diff func (f *Factory) startCleanup(interval time.Duration) { ticker := time.NewTicker(interval) go func() { + defer ticker.Stop() for range ticker.C { f.mu.Lock() now := time.Now() - for name, identity := range f.data { + for xuid, identity := range f.data { if now.After(identity.Expiration) { - delete(f.data, name) + delete(f.data, xuid) } } f.mu.Unlock() } }() } ``` Consider adding a shutdown mechanism to the Factory: ```diff +// Stop gracefully shuts down the factory's cleanup routine. +func (f *Factory) Stop() { + // Implementation depends on how you want to manage the ticker lifecycle +} ``` <!-- 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 // startCleanup begins a periodic cleanup routine that removes expired identities. // The interval parameter determines how often cleanup occurs. func (f *Factory) startCleanup(interval time.Duration) { ticker := time.NewTicker(interval) go func() { defer ticker.Stop() for range ticker.C { f.mu.Lock() now := time.Now() for xuid, identity := range f.data { if now.After(identity.Expiration) { delete(f.data, xuid) } } f.mu.Unlock() } }() } ``` </details> <!-- suggestion_end --> <details> <summary>🤖 Prompt for AI Agents</summary> ``` In pokebedrock/authentication/factory.go lines 31 to 47, rename the loop variable from 'name' to 'xuid' to correctly reflect that it represents the XUID key. Additionally, add a shutdown mechanism to the Factory struct to manage the lifecycle of the cleanup goroutine by introducing a stop channel or context that the goroutine listens to, allowing it to exit cleanly when the Factory is stopped, preventing goroutine leaks. ``` </details> <!-- This is an auto-generated reply by CodeRabbit -->
coderabbitai[bot] (Migrated from github.com) commented 2025-06-06 13:42:24 +00:00

🛠️ Refactor suggestion

Fix URL format inconsistency for better consistency.

The AuthenticationURL default value lacks the protocol prefix, which is inconsistent with other service URLs in the configuration.

Apply this diff to maintain consistency:

-	c.Service.AuthenticationURL = "127.0.0.1:8080/authentication"
+	c.Service.AuthenticationURL = "http://127.0.0.1:8080/authentication"
📝 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.

    c.Service.AuthenticationURL = "http://127.0.0.1:8080/authentication"
    c.Service.AuthenticationKey = "secret-key"
🤖 Prompt for AI Agents
In pokebedrock/config.go at lines 52 to 53, the AuthenticationURL is missing the
protocol prefix, causing inconsistency with other service URLs. Update the
AuthenticationURL value to include the protocol prefix (e.g.,
"http://127.0.0.1:8080/authentication") to ensure consistent URL formatting
across the configuration.
_🛠️ Refactor suggestion_ **Fix URL format inconsistency for better consistency.** The `AuthenticationURL` default value lacks the protocol prefix, which is inconsistent with other service URLs in the configuration. Apply this diff to maintain consistency: ```diff - c.Service.AuthenticationURL = "127.0.0.1:8080/authentication" + c.Service.AuthenticationURL = "http://127.0.0.1:8080/authentication" ``` <!-- 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 c.Service.AuthenticationURL = "http://127.0.0.1:8080/authentication" c.Service.AuthenticationKey = "secret-key" ``` </details> <!-- suggestion_end --> <details> <summary>🤖 Prompt for AI Agents</summary> ``` In pokebedrock/config.go at lines 52 to 53, the AuthenticationURL is missing the protocol prefix, causing inconsistency with other service URLs. Update the AuthenticationURL value to include the protocol prefix (e.g., "http://127.0.0.1:8080/authentication") to ensure consistent URL formatting across the configuration. ``` </details> <!-- This is an auto-generated comment by CodeRabbit -->
coderabbitai[bot] (Migrated from github.com) commented 2025-06-06 13:42:24 +00:00

🛠️ Refactor suggestion

Address goroutine lifecycle management.

The authentication service goroutine lacks proper lifecycle management. Consider the following issues:

  1. No graceful shutdown mechanism when the server stops
  2. Error handling only logs but doesn't propagate critical startup failures

Consider this approach for better lifecycle management:

-	go func() {
-		if err = poke.setupGin(); err != nil {
-			poke.log.Error("failed to start authentication service", "error", err)
-		}
-	}()
+	go func() {
+		if err := poke.setupGin(); err != nil {
+			poke.log.Error("failed to start authentication service", "error", err)
+			// Consider whether this should be a fatal error
+		}
+	}()

Also, ensure the HTTP server is gracefully shut down in the Close() method.

📝 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.

    go func() {
        if err := poke.setupGin(); err != nil {
            poke.log.Error("failed to start authentication service", "error", err)
            // Consider whether this should be a fatal error
        }
    }()
🤖 Prompt for AI Agents
In pokebedrock/pokebedrock.go around lines 63 to 67, the goroutine starting the
authentication service lacks lifecycle management and proper error propagation.
Refactor to include a mechanism to signal shutdown, such as using a context with
cancellation or a wait group, and propagate startup errors back to the main
routine instead of only logging them. Additionally, implement graceful shutdown
of the HTTP server in the Close() method to ensure resources are properly
released when stopping the service.
_🛠️ Refactor suggestion_ **Address goroutine lifecycle management.** The authentication service goroutine lacks proper lifecycle management. Consider the following issues: 1. No graceful shutdown mechanism when the server stops 2. Error handling only logs but doesn't propagate critical startup failures Consider this approach for better lifecycle management: ```diff - go func() { - if err = poke.setupGin(); err != nil { - poke.log.Error("failed to start authentication service", "error", err) - } - }() + go func() { + if err := poke.setupGin(); err != nil { + poke.log.Error("failed to start authentication service", "error", err) + // Consider whether this should be a fatal error + } + }() ``` Also, ensure the HTTP server is gracefully shut down in the `Close()` method. <!-- 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 go func() { if err := poke.setupGin(); err != nil { poke.log.Error("failed to start authentication service", "error", err) // Consider whether this should be a fatal error } }() ``` </details> <!-- suggestion_end --> <details> <summary>🤖 Prompt for AI Agents</summary> ``` In pokebedrock/pokebedrock.go around lines 63 to 67, the goroutine starting the authentication service lacks lifecycle management and proper error propagation. Refactor to include a mechanism to signal shutdown, such as using a context with cancellation or a wait group, and propagate startup errors back to the main routine instead of only logging them. Additionally, implement graceful shutdown of the HTTP server in the Close() method to ensure resources are properly released when stopping the service. ``` </details> <!-- This is an auto-generated comment by CodeRabbit -->
coderabbitai[bot] (Migrated from github.com) commented 2025-06-06 13:42:25 +00:00

🛠️ Refactor suggestion

Improve security and error handling in the authentication service.

The implementation has several areas for improvement:

  1. Security: No validation if AuthenticationKey is empty, which would allow unauthorized access
  2. Error handling: Missing validation for required configuration values
  3. Code clarity: The endpoint logic could be more readable

Apply these improvements:

 func (poke *PokeBedrock) setupGin() error {
+	if poke.conf.Service.AuthenticationKey == "" {
+		return fmt.Errorf("authentication key cannot be empty")
+	}
+	if poke.conf.Service.AuthenticationURL == "" {
+		return fmt.Errorf("authentication URL cannot be empty")
+	}
+
 	gin.SetMode(gin.ReleaseMode)
 
 	router := gin.Default()
 	router.Use(func(c *gin.Context) {
 		if c.GetHeader("authorization") != poke.conf.Service.AuthenticationKey {
 			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
 			return
 		}
 		c.Next()
 	})
+	
 	router.GET("/authentication/:xuid", func(c *gin.Context) {
 		xuid := c.Param("xuid")
 		req, exists := authentication.GlobalFactory().Of(xuid)
 		if !exists {
 			c.JSON(http.StatusNotFound, gin.H{"reason": "no player found"})
 			return
 		}
 
 		if time.Now().After(req.Expiration) {
 			authentication.GlobalFactory().Remove(xuid)
 			c.JSON(http.StatusGone, gin.H{"reason": "request expired"})
 			return
 		}
 
 		c.JSON(http.StatusOK, gin.H{
 			"allowed": true,
 		})
 	})
+	
 	return router.Run(poke.conf.Service.AuthenticationURL)
 }

Don't forget to add fmt import for the error formatting.

🤖 Prompt for AI Agents
In pokebedrock/pokebedrock.go lines 122 to 153, improve security by checking if
poke.conf.Service.AuthenticationKey is empty before setting up the router and
return an error if so to prevent unauthorized access. Add validation for
required configuration values like AuthenticationURL and return descriptive
errors if missing. Refactor the /authentication/:xuid handler to improve
readability by separating logic into smaller blocks or helper functions and
adding clear comments. Also, ensure to import the fmt package for error
formatting when returning errors.
_🛠️ Refactor suggestion_ **Improve security and error handling in the authentication service.** The implementation has several areas for improvement: 1. **Security**: No validation if `AuthenticationKey` is empty, which would allow unauthorized access 2. **Error handling**: Missing validation for required configuration values 3. **Code clarity**: The endpoint logic could be more readable Apply these improvements: ```diff func (poke *PokeBedrock) setupGin() error { + if poke.conf.Service.AuthenticationKey == "" { + return fmt.Errorf("authentication key cannot be empty") + } + if poke.conf.Service.AuthenticationURL == "" { + return fmt.Errorf("authentication URL cannot be empty") + } + gin.SetMode(gin.ReleaseMode) router := gin.Default() router.Use(func(c *gin.Context) { if c.GetHeader("authorization") != poke.conf.Service.AuthenticationKey { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"}) return } c.Next() }) + router.GET("/authentication/:xuid", func(c *gin.Context) { xuid := c.Param("xuid") req, exists := authentication.GlobalFactory().Of(xuid) if !exists { c.JSON(http.StatusNotFound, gin.H{"reason": "no player found"}) return } if time.Now().After(req.Expiration) { authentication.GlobalFactory().Remove(xuid) c.JSON(http.StatusGone, gin.H{"reason": "request expired"}) return } c.JSON(http.StatusOK, gin.H{ "allowed": true, }) }) + return router.Run(poke.conf.Service.AuthenticationURL) } ``` Don't forget to add `fmt` import for the error formatting. <details> <summary>🤖 Prompt for AI Agents</summary> ``` In pokebedrock/pokebedrock.go lines 122 to 153, improve security by checking if poke.conf.Service.AuthenticationKey is empty before setting up the router and return an error if so to prevent unauthorized access. Add validation for required configuration values like AuthenticationURL and return descriptive errors if missing. Refactor the /authentication/:xuid handler to improve readability by separating logic into smaller blocks or helper functions and adding clear comments. Also, ensure to import the fmt package for error formatting when returning errors. ``` </details> <!-- This is an auto-generated comment by CodeRabbit -->
glancist (Migrated from github.com) reviewed 2025-06-06 13:45:45 +00:00
@ -0,0 +1,72 @@
package authentication
glancist (Migrated from github.com) commented 2025-06-06 13:45:45 +00:00

will apply this right now

will apply this right now
coderabbitai[bot] (Migrated from github.com) reviewed 2025-06-06 13:46:11 +00:00
@ -0,0 +1,72 @@
package authentication
coderabbitai[bot] (Migrated from github.com) commented 2025-06-06 13:46:11 +00:00

@glancist Thank you for the quick response! I appreciate you taking action on the refactor suggestions. The variable naming fix and goroutine lifecycle management will definitely improve the code quality and prevent potential resource leaks.

/|   /|  

( ✌️ )
|(_)|


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

@glancist Thank you for the quick response! I appreciate you taking action on the refactor suggestions. The variable naming fix and goroutine lifecycle management will definitely improve the code quality and prevent potential resource leaks. /| /| ( :v: ) |(_)| --- <!-- This is an auto-generated comment: tweet message by coderabbit.ai --> If you found this review helpful, would you consider giving us a shout-out on [X](https://twitter.com/intent/tweet?related=CodeRabbitAI&text=%40coderabbitai%20spotted%20a%20key%20fix%3A%20rename%20loop%20var%20to%20reflect%20XUID%20keys%20%26%20add%20a%20shutdown%20method%20to%20stop%20cleanup%20goroutine%2C%20preventing%20leaks%20and%20improving%20resource%20management!%20%F0%9F%9B%A0%EF%B8%8F%F0%9F%90%87%20Try%20it!&url=https%3A%2F%2Fgithub.com%2Fsmell-of-curry%2Fpokebedrock-hub%2Fpull%2F11%23discussion_r2132226137)? Thank you for using CodeRabbit! <!-- end of auto-generated comment: tweet message by coderabbit.ai --> <!-- <agentComponentType>chat-answer</agentComponentType> --> <!-- <rawResChunk><answer>@glancist Thank you for the quick response! I appreciate you taking action on the refactor suggestions. The variable naming fix and goroutine lifecycle management will definitely improve the code quality and prevent potential resource leaks. /| /| ( :v: ) |(_)| --- &lt;!-- This is an auto-generated comment: tweet message by coderabbit.ai --&gt; If you found this review helpful, would you consider giving us a shout-out on [X](https://twitter.com/intent/tweet?related=CodeRabbitAI&text=%40coderabbitai%20spotted%20a%20key%20fix%3A%20rename%20loop%20var%20to%20reflect%20XUID%20keys%20%26%20add%20a%20shutdown%20method%20to%20stop%20cleanup%20goroutine%2C%20preventing%20leaks%20and%20improving%20resource%20management!%20%F0%9F%9B%A0%EF%B8%8F%F0%9F%90%87%20Try%20it!&url=https%3A%2F%2Fgithub.com%2Fsmell-of-curry%2Fpokebedrock-hub%2Fpull%2F11%23discussion_r2132226137)? Thank you for using CodeRabbit! &lt;!-- end of auto-generated comment: tweet message by coderabbit.ai --&gt; </answer></rawResChunk> --> <!-- This is an auto-generated reply by CodeRabbit -->
coderabbitai[bot] (Migrated from github.com) reviewed 2025-07-01 18:45:27 +00:00
coderabbitai[bot] (Migrated from github.com) left a comment

Actionable comments posted: 6

🧹 Nitpick comments (4)
pokebedrock/vpn/service.go (4)

17-23: Consider thread-safe initialization for the global service.

The current implementation doesn't ensure thread-safe initialization of the global service. Consider using sync.Once for safer initialization.

-// globalService ...
-var globalService *Service
+var (
+	globalService *Service
+	serviceOnce   sync.Once
+)

108-109: Remove redundant sleep in rate limit case.

There's already a sleep at the beginning of the retry loop (line 71), so this additional sleep is redundant and causes excessive delays.

 		case http.StatusTooManyRequests:
 			lastErr = fmt.Errorf("rate limited by api")
-			time.Sleep(time.Duration(attempt+1) * retryDelay)
 			continue

124-128: Log the parse error for debugging.

When the TTL header parsing fails, the error is silently ignored. Consider logging it for debugging purposes.

 		ttl, err := strconv.Atoi(timeToResetStr)
 		if err != nil {
+			s.log.Warn("failed to parse X-Ttl header", "value", timeToResetStr, "error", err)
 			// couldn't parse header for whatever reason, just default to fallback wait time.
 			ttl = 60
 		}

137-140: Enhance the Stop method for cleaner shutdown.

Consider checking the closed state at the beginning of CheckIP and potentially closing the HTTP client transport for cleaner resource management.

 // CheckIP determines whether the provided IP address is associated with a VPN connection.
 func (s *Service) CheckIP(ip string) (*ResponseModel, error) {
+	if s.closed {
+		return nil, fmt.Errorf("service is closed")
+	}
 	s.mu.Lock()

Also consider closing the HTTP client in Stop:

 // Stop stops the service.
 func (s *Service) Stop() {
 	s.closed = true
+	if transport, ok := s.client.Transport.(*http.Transport); ok {
+		transport.CloseIdleConnections()
+	}
 }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 32cd72030f and 43f310be35.

📒 Files selected for processing (5)
  • pokebedrock/allower.go (2 hunks)
  • pokebedrock/config.go (3 hunks)
  • pokebedrock/pokebedrock.go (6 hunks)
  • pokebedrock/vpn/model.go (1 hunks)
  • pokebedrock/vpn/service.go (1 hunks)
Files skipped from review due to trivial changes (1)
  • pokebedrock/vpn/model.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • pokebedrock/config.go
  • pokebedrock/pokebedrock.go
🧰 Additional context used
🧬 Code Graph Analysis (1)
pokebedrock/vpn/service.go (2)
pokebedrock/vpn/model.go (1)
  • ResponseModel (9-13)
pokebedrock/srv/status.go (1)
  • Status (4-8)
🔇 Additional comments (1)
pokebedrock/allower.go (1)

18-21: Good integration of VPN checking as an early validation step.

The VPN check is appropriately placed before the infliction checks, providing an efficient early rejection mechanism for VPN/proxy connections.

**Actionable comments posted: 6** <details> <summary>🧹 Nitpick comments (4)</summary><blockquote> <details> <summary>pokebedrock/vpn/service.go (4)</summary><blockquote> `17-23`: **Consider thread-safe initialization for the global service.** The current implementation doesn't ensure thread-safe initialization of the global service. Consider using `sync.Once` for safer initialization. ```diff -// globalService ... -var globalService *Service +var ( + globalService *Service + serviceOnce sync.Once +) ``` --- `108-109`: **Remove redundant sleep in rate limit case.** There's already a sleep at the beginning of the retry loop (line 71), so this additional sleep is redundant and causes excessive delays. ```diff case http.StatusTooManyRequests: lastErr = fmt.Errorf("rate limited by api") - time.Sleep(time.Duration(attempt+1) * retryDelay) continue ``` --- `124-128`: **Log the parse error for debugging.** When the TTL header parsing fails, the error is silently ignored. Consider logging it for debugging purposes. ```diff ttl, err := strconv.Atoi(timeToResetStr) if err != nil { + s.log.Warn("failed to parse X-Ttl header", "value", timeToResetStr, "error", err) // couldn't parse header for whatever reason, just default to fallback wait time. ttl = 60 } ``` --- `137-140`: **Enhance the Stop method for cleaner shutdown.** Consider checking the closed state at the beginning of CheckIP and potentially closing the HTTP client transport for cleaner resource management. ```diff // CheckIP determines whether the provided IP address is associated with a VPN connection. func (s *Service) CheckIP(ip string) (*ResponseModel, error) { + if s.closed { + return nil, fmt.Errorf("service is closed") + } s.mu.Lock() ``` Also consider closing the HTTP client in Stop: ```diff // Stop stops the service. func (s *Service) Stop() { s.closed = true + if transport, ok := s.client.Transport.(*http.Transport); ok { + transport.CloseIdleConnections() + } } ``` </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 32cd72030f31526c6ccbafbdb025a91f728cc0ad and 43f310be351bb1a18f2d6833c4f855a902d713a2. </details> <details> <summary>📒 Files selected for processing (5)</summary> * `pokebedrock/allower.go` (2 hunks) * `pokebedrock/config.go` (3 hunks) * `pokebedrock/pokebedrock.go` (6 hunks) * `pokebedrock/vpn/model.go` (1 hunks) * `pokebedrock/vpn/service.go` (1 hunks) </details> <details> <summary>✅ Files skipped from review due to trivial changes (1)</summary> * pokebedrock/vpn/model.go </details> <details> <summary>🚧 Files skipped from review as they are similar to previous changes (2)</summary> * pokebedrock/config.go * pokebedrock/pokebedrock.go </details> <details> <summary>🧰 Additional context used</summary> <details> <summary>🧬 Code Graph Analysis (1)</summary> <details> <summary>pokebedrock/vpn/service.go (2)</summary><blockquote> <details> <summary>pokebedrock/vpn/model.go (1)</summary> * `ResponseModel` (9-13) </details> <details> <summary>pokebedrock/srv/status.go (1)</summary> * `Status` (4-8) </details> </blockquote></details> </details> </details> <details> <summary>🔇 Additional comments (1)</summary><blockquote> <details> <summary>pokebedrock/allower.go (1)</summary> `18-21`: **Good integration of VPN checking as an early validation step.** The VPN check is appropriately placed before the infliction checks, providing an efficient early rejection mechanism for VPN/proxy connections. </details> </blockquote></details> </details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
@ -27,3 +32,29 @@ func (Allower) Allow(_ net.Addr, d login.IdentityData, _ login.ClientData) (stri
}
coderabbitai[bot] (Migrated from github.com) commented 2025-07-01 18:45:26 +00:00

⚠️ Potential issue

Fix inverted logic in the return statement.

The current logic returns m.Proxy as the allowed value, which means connections are allowed when a proxy is detected. This appears to be inverted.

-	return "VPN/Proxy connections are not allowed.", m.Proxy
+	return "VPN/Proxy connections are not allowed.", !m.Proxy
📝 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.

	return "VPN/Proxy connections are not allowed.", !m.Proxy
🤖 Prompt for AI Agents
In pokebedrock/allower.go at line 51, the return statement incorrectly returns
m.Proxy as the allowed value, which inverts the intended logic. Change the
return to return the negation of m.Proxy so that connections are disallowed when
a proxy is detected, ensuring the allowed boolean correctly reflects the
intended access control.
_⚠️ Potential issue_ **Fix inverted logic in the return statement.** The current logic returns `m.Proxy` as the `allowed` value, which means connections are allowed when a proxy is detected. This appears to be inverted. ```diff - return "VPN/Proxy connections are not allowed.", m.Proxy + return "VPN/Proxy connections are not allowed.", !m.Proxy ``` <!-- 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 return "VPN/Proxy connections are not allowed.", !m.Proxy ``` </details> <!-- suggestion_end --> <details> <summary>🤖 Prompt for AI Agents</summary> ``` In pokebedrock/allower.go at line 51, the return statement incorrectly returns m.Proxy as the allowed value, which inverts the intended logic. Change the return to return the negation of m.Proxy so that connections are disallowed when a proxy is detected, ensuring the allowed boolean correctly reflects the intended access control. ``` </details> <!-- This is an auto-generated comment by CodeRabbit --> <!-- fingerprinting:phantom:medusa:lion -->
coderabbitai[bot] (Migrated from github.com) commented 2025-07-01 18:45:26 +00:00

🛠️ Refactor suggestion

Add IPv6 localhost check.

The current implementation only checks for IPv4 localhost addresses but misses IPv6 localhost (::1).

-	if addrString == "127.0.0.1" || addrString == "0.0.0.0" || addrString == "localhost" {
+	if addrString == "127.0.0.1" || addrString == "0.0.0.0" || addrString == "localhost" || addrString == "::1" {
🤖 Prompt for AI Agents
In pokebedrock/allower.go around lines 40 to 42, the code checks for IPv4
localhost addresses but misses the IPv6 localhost (::1). Update the condition to
also check if addrString equals "::1" and return the same result as for other
localhost addresses.
_🛠️ Refactor suggestion_ **Add IPv6 localhost check.** The current implementation only checks for IPv4 localhost addresses but misses IPv6 localhost (::1). ```diff - if addrString == "127.0.0.1" || addrString == "0.0.0.0" || addrString == "localhost" { + if addrString == "127.0.0.1" || addrString == "0.0.0.0" || addrString == "localhost" || addrString == "::1" { ``` <details> <summary>🤖 Prompt for AI Agents</summary> ``` In pokebedrock/allower.go around lines 40 to 42, the code checks for IPv4 localhost addresses but misses the IPv6 localhost (::1). Update the condition to also check if addrString equals "::1" and return the same result as for other localhost addresses. ``` </details> <!-- This is an auto-generated comment by CodeRabbit --> <!-- fingerprinting:phantom:medusa:lion -->
coderabbitai[bot] (Migrated from github.com) commented 2025-07-01 18:45:26 +00:00

⚠️ Potential issue

Handle the error from ParseAddrPort.

The error from netip.ParseAddrPort is ignored, which could lead to unexpected behavior if the address format is invalid.

-	addr, _ := netip.ParseAddrPort(netAddr.String())
+	addr, err := netip.ParseAddrPort(netAddr.String())
+	if err != nil {
+		return "Invalid network address format", false
+	}
🤖 Prompt for AI Agents
In pokebedrock/allower.go at line 38, the error returned by netip.ParseAddrPort
is currently ignored. Modify the code to capture and check this error, and
handle it appropriately, such as returning the error or logging it, to prevent
unexpected behavior from invalid address formats.
_⚠️ Potential issue_ **Handle the error from ParseAddrPort.** The error from `netip.ParseAddrPort` is ignored, which could lead to unexpected behavior if the address format is invalid. ```diff - addr, _ := netip.ParseAddrPort(netAddr.String()) + addr, err := netip.ParseAddrPort(netAddr.String()) + if err != nil { + return "Invalid network address format", false + } ``` <details> <summary>🤖 Prompt for AI Agents</summary> ``` In pokebedrock/allower.go at line 38, the error returned by netip.ParseAddrPort is currently ignored. Modify the code to capture and check this error, and handle it appropriately, such as returning the error or logging it, to prevent unexpected behavior from invalid address formats. ``` </details> <!-- This is an auto-generated comment by CodeRabbit --> <!-- fingerprinting:phantom:medusa:lion -->
@ -0,0 +1,154 @@
package vpn
coderabbitai[bot] (Migrated from github.com) commented 2025-07-01 18:45:27 +00:00

🛠️ Refactor suggestion

Avoid closing response body multiple times.

The response body is closed in multiple places which could cause issues. Use defer for cleaner resource management.

 		response, err := s.client.Do(request)
 		cancel()
 		if err != nil {
 			lastErr = fmt.Errorf("request failed: %w", err)
 			if ErrorIsTemporary(err) {
 				continue
 			}
 			return nil, lastErr
 		}
+		defer response.Body.Close()

 		s.handleRateLimitHeaders(response.Header)

 		switch response.StatusCode {
 		case http.StatusOK:
 			var responseModel ResponseModel
 			if err = json.NewDecoder(response.Body).Decode(&responseModel); err != nil {
-				response.Body.Close()
 				return nil, fmt.Errorf("failed to decode response body: %w", err)
 			}
-			response.Body.Close()
 			if responseModel.Status == "fail" {
 				return nil, fmt.Errorf("query failed: %s", responseModel.Message)
 			}
 			return &responseModel, nil
 		case http.StatusTooManyRequests:
 			lastErr = fmt.Errorf("rate limited by api")
 			time.Sleep(time.Duration(attempt+1) * retryDelay)
 			continue
 		default:
 			lastErr = fmt.Errorf("unexpected status code: %d", response.StatusCode)
 		}
-		response.Body.Close()

Also applies to: 113-113

🤖 Prompt for AI Agents
In pokebedrock/vpn/service.go around lines 98-99 and line 113, the response.Body
is closed explicitly multiple times which can cause runtime errors. Replace the
explicit calls to response.Body.Close() with a single defer statement
immediately after checking for a non-nil response to ensure the body is closed
exactly once and resource management is cleaner.
_🛠️ Refactor suggestion_ **Avoid closing response body multiple times.** The response body is closed in multiple places which could cause issues. Use defer for cleaner resource management. ```diff response, err := s.client.Do(request) cancel() if err != nil { lastErr = fmt.Errorf("request failed: %w", err) if ErrorIsTemporary(err) { continue } return nil, lastErr } + defer response.Body.Close() s.handleRateLimitHeaders(response.Header) switch response.StatusCode { case http.StatusOK: var responseModel ResponseModel if err = json.NewDecoder(response.Body).Decode(&responseModel); err != nil { - response.Body.Close() return nil, fmt.Errorf("failed to decode response body: %w", err) } - response.Body.Close() if responseModel.Status == "fail" { return nil, fmt.Errorf("query failed: %s", responseModel.Message) } return &responseModel, nil case http.StatusTooManyRequests: lastErr = fmt.Errorf("rate limited by api") time.Sleep(time.Duration(attempt+1) * retryDelay) continue default: lastErr = fmt.Errorf("unexpected status code: %d", response.StatusCode) } - response.Body.Close() ``` Also applies to: 113-113 <details> <summary>🤖 Prompt for AI Agents</summary> ``` In pokebedrock/vpn/service.go around lines 98-99 and line 113, the response.Body is closed explicitly multiple times which can cause runtime errors. Replace the explicit calls to response.Body.Close() with a single defer statement immediately after checking for a non-nil response to ensure the body is closed exactly once and resource management is cleaner. ``` </details> <!-- This is an auto-generated comment by CodeRabbit --> <!-- fingerprinting:phantom:medusa:lion -->
@ -0,0 +51,4 @@
maxRetries = 3
retryDelay = 1 * time.Second
requestTimeout = 5 * time.Second
)
coderabbitai[bot] (Migrated from github.com) commented 2025-07-01 18:45:27 +00:00

🛠️ Refactor suggestion

Align retry logic with maxRetries constant.

The maxRetries constant is set to 3, but the loop only allows 2 attempts (0 and 1). Either update the constant or fix the loop condition.

-const (
-	maxRetries     = 3
+const (
+	maxRetries     = 2

Or alternatively:

-	for attempt := 0; attempt <= 1; attempt++ {
+	for attempt := 0; attempt < maxRetries; attempt++ {

Also applies to: 66-66

🤖 Prompt for AI Agents
In pokebedrock/vpn/service.go around lines 50 to 54 and line 66, the retry loop
condition does not match the maxRetries constant of 3, causing only 2 attempts
instead of 3. Update the loop condition to allow retries up to maxRetries times
by changing the loop to run while the attempt count is less than maxRetries,
ensuring the retry logic aligns with the constant value.
_🛠️ Refactor suggestion_ **Align retry logic with maxRetries constant.** The `maxRetries` constant is set to 3, but the loop only allows 2 attempts (0 and 1). Either update the constant or fix the loop condition. ```diff -const ( - maxRetries = 3 +const ( + maxRetries = 2 ``` Or alternatively: ```diff - for attempt := 0; attempt <= 1; attempt++ { + for attempt := 0; attempt < maxRetries; attempt++ { ``` Also applies to: 66-66 <details> <summary>🤖 Prompt for AI Agents</summary> ``` In pokebedrock/vpn/service.go around lines 50 to 54 and line 66, the retry loop condition does not match the maxRetries constant of 3, causing only 2 attempts instead of 3. Update the loop condition to allow retries up to maxRetries times by changing the loop to run while the attempt count is less than maxRetries, ensuring the retry logic aligns with the constant value. ``` </details> <!-- This is an auto-generated comment by CodeRabbit --> <!-- fingerprinting:phantom:medusa:lion -->
@ -0,0 +74,4 @@
time.Sleep(retryDelay)
}
url := fmt.Sprintf("%s/%s?fields=status,message,proxy", s.url, ip)
coderabbitai[bot] (Migrated from github.com) commented 2025-07-01 18:45:27 +00:00

💡 Verification agent

🧩 Analysis chain

Validate IP parameter before URL construction.

The IP parameter is directly interpolated into the URL without validation, which could lead to injection vulnerabilities if the IP comes from untrusted sources.

Consider adding IP validation:

+	// Validate IP format
+	if net.ParseIP(ip) == nil {
+		return nil, fmt.Errorf("invalid IP address format: %s", ip)
+	}
 	url := fmt.Sprintf("%s/%s?fields=status,message,proxy", s.url, ip)

🏁 Script executed:

#!/bin/bash
# Check if there's any IP validation before calling CheckIP
rg -A 5 -B 5 'CheckIP\(' --type go

Length of output: 1281


🏁 Script executed:

#!/bin/bash
# Check for multiple resp.Body.Close calls in CheckIP
rg -n "resp.Body.Close" -A2 pokebedrock/vpn/service.go

# Check for retryDelay usage in CheckIP
rg -n "retryDelay" -A2 pokebedrock/vpn/service.go

Length of output: 317


🏁 Script executed:

#!/bin/bash
# Extract the full CheckIP function for manual inspection
rg -n -A200 --no-heading "func (s .*CheckIP" pokebedrock/vpn/service.go

Length of output: 147


🏁 Script executed:

#!/bin/bash
# Extract the full CheckIP function for inspection
rg -n -C200 'func \(s \*Service\) CheckIP' pokebedrock/vpn/service.go

Length of output: 4365


Add IP format validation in CheckIP before URL construction

The ip parameter is directly interpolated into the request URL without any validation. Injecting malformed or unexpected values could lead to security or correctness issues. I’ve confirmed:

  • There is no existing net.ParseIP (or equivalent) check anywhere in CheckIP.
  • Response bodies are closed exactly once per execution path.
  • The retry delays distinguish between generic retries and rate-limit backoff as intended.

Please update pokebedrock/vpn/service.go around line 57:

 func (s *Service) CheckIP(ip string) (*ResponseModel, error) {
+   // Validate IP format
+   if net.ParseIP(ip) == nil {
+       return nil, fmt.Errorf("invalid IP address format: %s", ip)
+   }
     s.mu.Lock()
     if time.Now().Before(s.rateLimitReset) {
         s.mu.Unlock()
         return nil, fmt.Errorf("rate limit active, please wait until %v", s.rateLimitReset)
@@
-    url := fmt.Sprintf("%s/%s?fields=status,message,proxy", s.url, ip)
+    url := fmt.Sprintf("%s/%s?fields=status,message,proxy", s.url, ip)
📝 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.

func (s *Service) CheckIP(ip string) (*ResponseModel, error) {
    // Validate IP format
    if net.ParseIP(ip) == nil {
        return nil, fmt.Errorf("invalid IP address format: %s", ip)
    }

    s.mu.Lock()
    if time.Now().Before(s.rateLimitReset) {
        s.mu.Unlock()
        return nil, fmt.Errorf("rate limit active, please wait until %v", s.rateLimitReset)
    }
    s.mu.Unlock()

    url := fmt.Sprintf("%s/%s?fields=status,message,proxy", s.url, ip)
    // … rest of method unchanged …
}
🤖 Prompt for AI Agents
In pokebedrock/vpn/service.go around line 57, add validation for the ip
parameter using net.ParseIP before constructing the URL at line 74. If the IP is
invalid, return an error immediately to prevent malformed or malicious input
from being used in the URL. This ensures only valid IP addresses proceed to URL
construction and subsequent processing.
_💡 Verification agent_ <details> <summary>🧩 Analysis chain</summary> **Validate IP parameter before URL construction.** The IP parameter is directly interpolated into the URL without validation, which could lead to injection vulnerabilities if the IP comes from untrusted sources. Consider adding IP validation: ```diff + // Validate IP format + if net.ParseIP(ip) == nil { + return nil, fmt.Errorf("invalid IP address format: %s", ip) + } url := fmt.Sprintf("%s/%s?fields=status,message,proxy", s.url, ip) ``` --- 🏁 Script executed: ```shell #!/bin/bash # Check if there's any IP validation before calling CheckIP rg -A 5 -B 5 'CheckIP\(' --type go ``` Length of output: 1281 --- 🏁 Script executed: ```shell #!/bin/bash # Check for multiple resp.Body.Close calls in CheckIP rg -n "resp.Body.Close" -A2 pokebedrock/vpn/service.go # Check for retryDelay usage in CheckIP rg -n "retryDelay" -A2 pokebedrock/vpn/service.go ``` Length of output: 317 --- 🏁 Script executed: ```shell #!/bin/bash # Extract the full CheckIP function for manual inspection rg -n -A200 --no-heading "func (s .*CheckIP" pokebedrock/vpn/service.go ``` Length of output: 147 --- 🏁 Script executed: ```shell #!/bin/bash # Extract the full CheckIP function for inspection rg -n -C200 'func \(s \*Service\) CheckIP' pokebedrock/vpn/service.go ``` Length of output: 4365 --- </details> **Add IP format validation in CheckIP before URL construction** The `ip` parameter is directly interpolated into the request URL without any validation. Injecting malformed or unexpected values could lead to security or correctness issues. I’ve confirmed: - There is no existing `net.ParseIP` (or equivalent) check anywhere in `CheckIP`. - Response bodies are closed exactly once per execution path. - The retry delays distinguish between generic retries and rate-limit backoff as intended. Please update `pokebedrock/vpn/service.go` around line 57: ```diff func (s *Service) CheckIP(ip string) (*ResponseModel, error) { + // Validate IP format + if net.ParseIP(ip) == nil { + return nil, fmt.Errorf("invalid IP address format: %s", ip) + } s.mu.Lock() if time.Now().Before(s.rateLimitReset) { s.mu.Unlock() return nil, fmt.Errorf("rate limit active, please wait until %v", s.rateLimitReset) @@ - url := fmt.Sprintf("%s/%s?fields=status,message,proxy", s.url, ip) + url := fmt.Sprintf("%s/%s?fields=status,message,proxy", s.url, ip) ``` <!-- 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 func (s *Service) CheckIP(ip string) (*ResponseModel, error) { // Validate IP format if net.ParseIP(ip) == nil { return nil, fmt.Errorf("invalid IP address format: %s", ip) } s.mu.Lock() if time.Now().Before(s.rateLimitReset) { s.mu.Unlock() return nil, fmt.Errorf("rate limit active, please wait until %v", s.rateLimitReset) } s.mu.Unlock() url := fmt.Sprintf("%s/%s?fields=status,message,proxy", s.url, ip) // … rest of method unchanged … } ``` </details> <!-- suggestion_end --> <details> <summary>🤖 Prompt for AI Agents</summary> ``` In pokebedrock/vpn/service.go around line 57, add validation for the ip parameter using net.ParseIP before constructing the URL at line 74. If the IP is invalid, return an error immediately to prevent malformed or malicious input from being used in the URL. This ensures only valid IP addresses proceed to URL construction and subsequent processing. ``` </details> <!-- This is an auto-generated comment by CodeRabbit --> <!-- fingerprinting:phantom:medusa:lion -->
coderabbitai[bot] (Migrated from github.com) reviewed 2025-07-04 11:55:14 +00:00
coderabbitai[bot] (Migrated from github.com) left a comment

Actionable comments posted: 1

🧹 Nitpick comments (1)
go.mod (1)

11-13: Confirm the need for heavyweight direct deps (gin + go-jose).
Both libraries add ~4 MiB to the build, pull in ≈40 transitive modules and noticeably increase cold-start time. If you only need a minimal JSON endpoint and JWS verification, the stdlib (net/http, encoding/json) plus the lighter github.com/cristalhq/jwt/v5 might be sufficient.

Please double-check that:

  1. The feature set of Gin (routing, middleware, panic recovery) is really required and cannot be covered by a thinner wrapper (e.g. chi or stdlib mux).
  2. go-jose/v4 is strictly necessary — its API is great for JWE/JWS but overkill for plain JWT validation.

If you intentionally chose these libs, feel free to ignore. Otherwise consider swapping them before the dependency tree hardens.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 9d7cc02626 and a7919ac457.

Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (1)
  • go.mod (2 hunks)
🔇 Additional comments (1)
go.mod (1)

18-18: golang.org/x/text v0.26.0 may break string-prep & cases APIs.
The 0.26.* line moved several tables to internal and tightened bidi handling. Make sure any text/message, language, or cases usage in Dragonfly / Gin helpers still compiles under Go 1.24.

CI on Go 1.23 or older will fail because 0.26.* requires Go 1.20+. Verify the build matrix picks up 1.24.x everywhere.

**Actionable comments posted: 1** <details> <summary>🧹 Nitpick comments (1)</summary><blockquote> <details> <summary>go.mod (1)</summary><blockquote> `11-13`: **Confirm the need for heavyweight direct deps (`gin` + `go-jose`).** Both libraries add ~4 MiB to the build, pull in ≈40 transitive modules and noticeably increase cold-start time. If you only need a minimal JSON endpoint and JWS verification, the stdlib (`net/http`, `encoding/json`) plus the lighter `github.com/cristalhq/jwt/v5` might be sufficient. Please double-check that: 1. The feature set of Gin (routing, middleware, panic recovery) is really required and cannot be covered by a thinner wrapper (e.g. `chi` or stdlib mux). 2. `go-jose/v4` is strictly necessary — its API is great for JWE/JWS but overkill for plain JWT validation. If you intentionally chose these libs, feel free to ignore. Otherwise consider swapping them before the dependency tree hardens. </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 9d7cc02626e86fc46fed84c4f3ae839f66cff968 and a7919ac457053fe8ec12767d8fe18ce8669f5bb2. </details> <details> <summary>⛔ Files ignored due to path filters (1)</summary> * `go.sum` is excluded by `!**/*.sum` </details> <details> <summary>📒 Files selected for processing (1)</summary> * `go.mod` (2 hunks) </details> <details> <summary>🔇 Additional comments (1)</summary><blockquote> <details> <summary>go.mod (1)</summary> `18-18`: **`golang.org/x/text` v0.26.0 may break string-prep & `cases` APIs.** The 0.26.* line moved several tables to `internal` and tightened bidi handling. Make sure any `text/message`, `language`, or `cases` usage in Dragonfly / Gin helpers still compiles under Go 1.24. CI on Go 1.23 or older will fail because 0.26.* requires Go 1.20+. Verify the build matrix picks up `1.24.x` everywhere. </details> </blockquote></details> </details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
@ -18,30 +20,48 @@ require (
coderabbitai[bot] (Migrated from github.com) commented 2025-07-04 11:55:13 +00:00

🛠️ Refactor suggestion

Let go mod tidy manage indirect requirements instead of pinning them manually.
Every line marked // indirect below was added explicitly. That locks ~30 transient modules to the current versions and obscures which ones are truly needed. Prefer the canonical pattern:

  1. Remove the explicit indirect block.
  2. Run go mod tidy to let the tool infer the minimal set.
  3. Commit the cleaned go.mod/go.sum.

Example patch (abridged):

-require (
-	github.com/bytedance/sonic v1.13.3 // indirect
-	github.com/bytedance/sonic/loader v0.2.4 // indirect
-	…
-	github.com/ugorji/go/codec v1.2.14 // indirect
-	golang.org/x/arch v0.18.0 // indirect
-	…
-	google.golang.org/protobuf v1.36.6 // indirect
-)
+// (run `go mod tidy`; the indirect block disappears)

This keeps the module file concise and avoids supply-chain drift.
If deterministic builds are required, consider a go.work file or a lockfile instead.

Also applies to: 26-34, 37-48, 50-57, 59-63

🤖 Prompt for AI Agents
In go.mod around lines 23 to 34, the indirect dependencies are manually pinned,
which is not recommended. Remove all lines marked with "// indirect" in this
range and also in lines 26-34, 37-48, 50-57, and 59-63. Then run "go mod tidy"
to let Go automatically manage and prune indirect dependencies. Finally, commit
the updated go.mod and go.sum files to keep the module dependencies clean and
minimal.
_🛠️ Refactor suggestion_ **Let `go mod tidy` manage indirect requirements instead of pinning them manually.** Every line marked `// indirect` below was added explicitly. That locks ~30 transient modules to the current versions and obscures which ones are truly needed. Prefer the canonical pattern: 1. Remove the explicit indirect block. 2. Run `go mod tidy` to let the tool infer the minimal set. 3. Commit the cleaned `go.mod`/`go.sum`. Example patch (abridged): ```diff -require ( - github.com/bytedance/sonic v1.13.3 // indirect - github.com/bytedance/sonic/loader v0.2.4 // indirect - … - github.com/ugorji/go/codec v1.2.14 // indirect - golang.org/x/arch v0.18.0 // indirect - … - google.golang.org/protobuf v1.36.6 // indirect -) +// (run `go mod tidy`; the indirect block disappears) ``` This keeps the module file concise and avoids supply-chain drift. If deterministic builds are required, consider a `go.work` file or a lockfile instead. Also applies to: 26-34, 37-48, 50-57, 59-63 <details> <summary>🤖 Prompt for AI Agents</summary> ``` In go.mod around lines 23 to 34, the indirect dependencies are manually pinned, which is not recommended. Remove all lines marked with "// indirect" in this range and also in lines 26-34, 37-48, 50-57, and 59-63. Then run "go mod tidy" to let Go automatically manage and prune indirect dependencies. Finally, commit the updated go.mod and go.sum files to keep the module dependencies clean and minimal. ``` </details> <!-- This is an auto-generated comment by CodeRabbit --> <!-- fingerprinting:phantom:triton:cougar -->
copilot-pull-request-reviewer[bot] (Migrated from github.com) reviewed 2025-07-04 12:12:21 +00:00
copilot-pull-request-reviewer[bot] (Migrated from github.com) left a comment

Pull Request Overview

This PR integrates VPN detection and blocking into the hub, adds an HTTP-based authentication service for GoBDS, and expands configuration to support these features.

  • Introduce a VPN lookup service with retry and rate-limit handling
  • Enforce VPN/proxy blocking in the connection allower
  • Spin up a Gin‐based authentication endpoint and manage temporary player identities

Reviewed Changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
vpn/service.go New VPN check service with retries and rate-limit
vpn/model.go Response model for VPN API
queue/manager.go Register identity on successful transfer
pokebedrock/pokebedrock.go Gin setup for authentication service and startup hook
pokebedrock/config.go Added VPN/auth service config fields
authentication/factory.go Singleton factory for managing identities
allower.go Added VPN blocking logic to allow list
Comments suppressed due to low confidence (1)

pokebedrock/vpn/service.go:69

  • Using range on an integer causes a compile error; you should use a C-style loop such as for attempt := 0; attempt < maxRetries; attempt++ {}.
	for attempt := range maxRetries {
## Pull Request Overview This PR integrates VPN detection and blocking into the hub, adds an HTTP-based authentication service for GoBDS, and expands configuration to support these features. - Introduce a VPN lookup service with retry and rate-limit handling - Enforce VPN/proxy blocking in the connection allower - Spin up a Gin‐based authentication endpoint and manage temporary player identities ### Reviewed Changes Copilot reviewed 10 out of 11 changed files in this pull request and generated 3 comments. <details> <summary>Show a summary per file</summary> | File | Description | |-------------------------------------|-------------------------------------------------------| | vpn/service.go | New VPN check service with retries and rate-limit | | vpn/model.go | Response model for VPN API | | queue/manager.go | Register identity on successful transfer | | pokebedrock/pokebedrock.go | Gin setup for authentication service and startup hook | | pokebedrock/config.go | Added VPN/auth service config fields | | authentication/factory.go | Singleton factory for managing identities | | allower.go | Added VPN blocking logic to allow list | </details> <details> <summary>Comments suppressed due to low confidence (1)</summary> **pokebedrock/vpn/service.go:69** * Using `range` on an integer causes a compile error; you should use a C-style loop such as `for attempt := 0; attempt < maxRetries; attempt++ {}`. ``` for attempt := range maxRetries { ``` </details>
@ -27,3 +32,29 @@ func (Allower) Allow(_ net.Addr, d login.IdentityData, _ login.ClientData) (stri
}
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2025-07-04 12:12:21 +00:00

When m.Proxy is false (no VPN detected), you still return a non-empty reason; this may confuse consumers. Only return the block message when m.Proxy is true, otherwise return an empty reason.

	if m.Proxy {
		return "VPN/Proxy connections are not allowed.", false
	}
	return "", true
When `m.Proxy` is false (no VPN detected), you still return a non-empty reason; this may confuse consumers. Only return the block message when `m.Proxy` is true, otherwise return an empty reason. ```suggestion if m.Proxy { return "VPN/Proxy connections are not allowed.", false } return "", true ```
@ -57,6 +62,12 @@ func NewPokeBedrock(log *slog.Logger, conf Config) (*PokeBedrock, error) {
c: make(chan struct{}),
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2025-07-04 12:12:21 +00:00

Capturing and reusing the outer err variable inside the goroutine may cause a data race; declare a new err inside the closure (e.g., if err := poke.setupGin(); err != nil { ... }).

		if err := poke.setupGin(); err != nil {
Capturing and reusing the outer `err` variable inside the goroutine may cause a data race; declare a new `err` inside the closure (e.g., `if err := poke.setupGin(); err != nil { ... }`). ```suggestion if err := poke.setupGin(); err != nil { ```
@ -0,0 +1,154 @@
package vpn
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2025-07-04 12:12:21 +00:00

The closed flag is accessed without synchronization, which can lead to a race condition when Stop() is called; consider protecting it with mu or using an atomic boolean.

The `closed` flag is accessed without synchronization, which can lead to a race condition when `Stop()` is called; consider protecting it with `mu` or using an atomic boolean.
coderabbitai[bot] (Migrated from github.com) reviewed 2025-07-04 12:21:26 +00:00
coderabbitai[bot] (Migrated from github.com) left a comment

Actionable comments posted: 2

♻️ Duplicate comments (1)
go.mod (1)

21-66: Remove manually pinned indirect dependencies and use go mod tidy.

The extensive list of manually pinned indirect dependencies (lines 22-65) should be removed and managed automatically by Go's dependency management tools.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between a7919ac457 and 2a9a126a9f.

Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (6)
  • config.toml.example (1 hunks)
  • go.mod (2 hunks)
  • pokebedrock/allower.go (2 hunks)
  • pokebedrock/pokebedrock.go (6 hunks)
  • pokebedrock/queue/manager.go (2 hunks)
  • pokebedrock/vpn/service.go (1 hunks)
Files skipped from review due to trivial changes (1)
  • config.toml.example
🚧 Files skipped from review as they are similar to previous changes (3)
  • pokebedrock/queue/manager.go
  • pokebedrock/allower.go
  • pokebedrock/pokebedrock.go
🧰 Additional context used
🧬 Code Graph Analysis (1)
pokebedrock/vpn/service.go (2)
pokebedrock/vpn/model.go (1)
  • ResponseModel (9-13)
pokebedrock/srv/status.go (1)
  • Status (4-8)
🔇 Additional comments (4)
pokebedrock/vpn/service.go (4)

58-60: Previous IP validation concern addressed.

Good addition of IP format validation using net.ParseIP() before URL construction. This prevents malformed input from being used in the API request.


69-69: Retry logic now correctly aligns with maxRetries constant.

The loop now properly iterates 3 times (0, 1, 2) matching the maxRetries = 3 constant. This addresses the previous concern about misaligned retry logic.


28-37: Well-structured service with proper concurrency handling.

The service design effectively combines:

  • Thread-safe rate limiting with mutex protection
  • Atomic boolean for service state management
  • Proper HTTP client configuration with timeouts
  • Clean separation of concerns

143-154: Comprehensive error handling for retry logic.

The ErrorIsTemporary function properly identifies retryable errors including context deadlines and network timeouts, enabling robust retry behavior.

**Actionable comments posted: 2** <details> <summary>♻️ Duplicate comments (1)</summary><blockquote> <details> <summary>go.mod (1)</summary><blockquote> `21-66`: **Remove manually pinned indirect dependencies and use `go mod tidy`.** The extensive list of manually pinned indirect dependencies (lines 22-65) should be removed and managed automatically by Go's dependency management tools. </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 a7919ac457053fe8ec12767d8fe18ce8669f5bb2 and 2a9a126a9f555415546169ed3662098a26e804a5. </details> <details> <summary>⛔ Files ignored due to path filters (1)</summary> * `go.sum` is excluded by `!**/*.sum` </details> <details> <summary>📒 Files selected for processing (6)</summary> * `config.toml.example` (1 hunks) * `go.mod` (2 hunks) * `pokebedrock/allower.go` (2 hunks) * `pokebedrock/pokebedrock.go` (6 hunks) * `pokebedrock/queue/manager.go` (2 hunks) * `pokebedrock/vpn/service.go` (1 hunks) </details> <details> <summary>✅ Files skipped from review due to trivial changes (1)</summary> * config.toml.example </details> <details> <summary>🚧 Files skipped from review as they are similar to previous changes (3)</summary> * pokebedrock/queue/manager.go * pokebedrock/allower.go * pokebedrock/pokebedrock.go </details> <details> <summary>🧰 Additional context used</summary> <details> <summary>🧬 Code Graph Analysis (1)</summary> <details> <summary>pokebedrock/vpn/service.go (2)</summary><blockquote> <details> <summary>pokebedrock/vpn/model.go (1)</summary> * `ResponseModel` (9-13) </details> <details> <summary>pokebedrock/srv/status.go (1)</summary> * `Status` (4-8) </details> </blockquote></details> </details> </details> <details> <summary>🔇 Additional comments (4)</summary><blockquote> <details> <summary>pokebedrock/vpn/service.go (4)</summary> `58-60`: **Previous IP validation concern addressed.** Good addition of IP format validation using `net.ParseIP()` before URL construction. This prevents malformed input from being used in the API request. --- `69-69`: **Retry logic now correctly aligns with maxRetries constant.** The loop now properly iterates 3 times (0, 1, 2) matching the `maxRetries = 3` constant. This addresses the previous concern about misaligned retry logic. --- `28-37`: **Well-structured service with proper concurrency handling.** The service design effectively combines: - Thread-safe rate limiting with mutex protection - Atomic boolean for service state management - Proper HTTP client configuration with timeouts - Clean separation of concerns --- `143-154`: **Comprehensive error handling for retry logic.** The `ErrorIsTemporary` function properly identifies retryable errors including context deadlines and network timeouts, enabling robust retry behavior. </details> </blockquote></details> </details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
@ -0,0 +12,4 @@
"sync/atomic"
"time"
"github.com/go-jose/go-jose/v4/json"
coderabbitai[bot] (Migrated from github.com) commented 2025-07-04 12:21:26 +00:00

💡 Verification agent

🧩 Analysis chain

Clarify the use of go-jose/json instead of standard encoding/json.

The import uses github.com/go-jose/go-jose/v4/json instead of the standard library encoding/json. This is unusual and may indicate a specific requirement.

Please verify if this custom JSON package is necessary for the VPN service functionality, or if the standard library should be used:


🌐 Web query:

What is the difference between go-jose/go-jose/v4/json and the standard encoding/json package in Go?

💡 Result:

The primary difference between go-jose/go-jose/v4/json and Go's standard encoding/json package is that go-jose/go-jose/v4/json is a custom fork of encoding/json with important behavioral changes to support the unique requirements of the JOSE (Javascript Object Signing and Encryption) standards.

Here are the key differences:

1. Case Sensitivity in Field Matching

  • go-jose/go-jose/v4/json: Object deserialization uses case-sensitive member name matching. If the JSON field name's case does not exactly match the struct field's JSON tag or identifier, the field will not be set[4][5].
  • encoding/json: Uses case-insensitive matching for JSON object member names, which is the typical Go behavior[4][5].

2. Duplicate Key Rejection

  • go-jose/go-jose/v4/json: Explicitly checks for duplicate keys during deserialization and rejects input if duplicates are found. This is stricter and aims for better security and standards compliance (particularly important for cryptographic data)[4][5].
  • encoding/json: Allows the last value for a duplicated key to be set, following the JSON RFC, but does not explicitly reject or warn on duplicate keys[4][5].

3. Standards Compliance

  • go-jose/go-jose/v4/json: These changes are made to avoid differences in interpretation between go-jose and libraries in other languages implementing JOSE standards (such as JWT, JWE, JWS). This is critical for interoperability between systems[2][4][5].
  • encoding/json: Aims at general-purpose JSON processing for Go applications, without making such strict guarantees[1].

4. Origin and Stability

  • go-jose/go-jose/v4/json: Forked from Go 1.6's encoding/json—it may lack recent bug fixes and performance improvements present in newer Go releases[4][5].
  • encoding/json: Maintained as part of the Go standard library and continuously improved[1][3].

Summary Table

Feature go-jose/go-jose/v4/json encoding/json
Case sensitivity Case-sensitive field matching Case-insensitive matching
Duplicate key handling Rejects duplicates Accepts (last value wins)
Standards compliance focus Strict (JOSE/JWT/JWE/JWS) General-purpose JSON
Codebase origin Forked from Go 1.6 Maintained in Go stdlib
Up-to-date with Go Not always Yes

When should you use go-jose/go-jose/v4/json?
Use it only when working with JOSE (JWT, JWE, JWS) data, as these stricter behaviors are required for correct cryptographic processing and security interoperability. For general-purpose JSON in Go, encoding/json is recommended[2][4][5].

Citations:


Add comment explaining use of go-jose’s JSON fork for JOSE compliance

This import isn’t a stray replacement of the standard library—it’s required to enforce case-sensitive field matching and reject duplicate keys when handling JOSE data (JWT/JWE/JWS). Please document this intent in the code.

• File: pokebedrock/vpn/service.go
Line: 15

Suggested diff:

-   "github.com/go-jose/go-jose/v4/json"
+   // Use go-jose’s custom JSON fork to ensure strict case-sensitive matching
+   // and duplicate-key rejection required by JOSE (JWT/JWE/JWS) processing.
+   "github.com/go-jose/go-jose/v4/json"
📝 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.

	// Use go-jose’s custom JSON fork to ensure strict case-sensitive matching
	// and duplicate-key rejection required by JOSE (JWT/JWE/JWS) processing.
	"github.com/go-jose/go-jose/v4/json"
🤖 Prompt for AI Agents
In pokebedrock/vpn/service.go at line 15, add a comment above the import of
"github.com/go-jose/go-jose/v4/json" explaining that this package is
intentionally used instead of the standard library JSON to enforce
case-sensitive field matching and reject duplicate keys for proper JOSE
(JWT/JWE/JWS) compliance. This clarifies the purpose of the import and prevents
confusion.
_💡 Verification agent_ <details> <summary>🧩 Analysis chain</summary> **Clarify the use of go-jose/json instead of standard encoding/json.** The import uses `github.com/go-jose/go-jose/v4/json` instead of the standard library `encoding/json`. This is unusual and may indicate a specific requirement. Please verify if this custom JSON package is necessary for the VPN service functionality, or if the standard library should be used: --- 🌐 Web query: ```web What is the difference between go-jose/go-jose/v4/json and the standard encoding/json package in Go? ``` 💡 Result: The primary difference between **go-jose/go-jose/v4/json** and Go's standard **encoding/json** package is that **go-jose/go-jose/v4/json** is a **custom fork of encoding/json** with important behavioral changes to support the unique requirements of the JOSE (Javascript Object Signing and Encryption) standards. Here are the key differences: **1. Case Sensitivity in Field Matching** - **go-jose/go-jose/v4/json**: Object deserialization uses **case-sensitive member name matching**. If the JSON field name's case does not exactly match the struct field's JSON tag or identifier, the field will not be set[4][5]. - **encoding/json**: Uses **case-insensitive matching** for JSON object member names, which is the typical Go behavior[4][5]. **2. Duplicate Key Rejection** - **go-jose/go-jose/v4/json**: **Explicitly checks for duplicate keys during deserialization** and rejects input if duplicates are found. This is stricter and aims for better security and standards compliance (particularly important for cryptographic data)[4][5]. - **encoding/json**: Allows the last value for a duplicated key to be set, following the JSON RFC, but does not explicitly reject or warn on duplicate keys[4][5]. **3. Standards Compliance** - **go-jose/go-jose/v4/json**: These changes are made to **avoid differences in interpretation between go-jose and libraries in other languages** implementing JOSE standards (such as JWT, JWE, JWS). This is critical for interoperability between systems[2][4][5]. - **encoding/json**: Aims at general-purpose JSON processing for Go applications, without making such strict guarantees[1]. **4. Origin and Stability** - **go-jose/go-jose/v4/json**: Forked from Go 1.6's `encoding/json`—it may **lack recent bug fixes and performance improvements** present in newer Go releases[4][5]. - **encoding/json**: Maintained as part of the Go standard library and continuously improved[1][3]. **Summary Table** | Feature | go-jose/go-jose/v4/json | encoding/json | |----------------------------------|----------------------------------|------------------------------| | Case sensitivity | Case-sensitive field matching | Case-insensitive matching | | Duplicate key handling | Rejects duplicates | Accepts (last value wins) | | Standards compliance focus | Strict (JOSE/JWT/JWE/JWS) | General-purpose JSON | | Codebase origin | Forked from Go 1.6 | Maintained in Go stdlib | | Up-to-date with Go | Not always | Yes | **When should you use go-jose/go-jose/v4/json?** Use it only when working with JOSE (JWT, JWE, JWS) data, as these stricter behaviors are required for correct cryptographic processing and security interoperability. For general-purpose JSON in Go, **encoding/json** is recommended[2][4][5]. Citations: - 1: https://github.com/golang/go/discussions/63397 - 2: https://pkg.go.dev/github.com/go-jose/go-jose/v4 - 3: https://dev.to/jpoly1219/to-unmarshal-or-to-decode-json-processing-in-go-explained-5870 - 4: https://pkg.go.dev/github.com/go-jose/go-jose/v4/json - 5: https://pkg.go.dev/gopkg.in/go-jose/go-jose.v2/json - 6: https://github.com/go-jose/go-jose/blob/main/jwk_test.go - 7: https://github.com/go-jose/go-jose - 8: https://jwt.io - 9: https://articles.wesionary.team/difference-of-json-encoding-vs-marshaling-and-json-decoding-vs-unmarshaling-1a6baf6a7f5c --- </details> **Add comment explaining use of go-jose’s JSON fork for JOSE compliance** This import isn’t a stray replacement of the standard library—it’s required to enforce case-sensitive field matching and reject duplicate keys when handling JOSE data (JWT/JWE/JWS). Please document this intent in the code. • File: pokebedrock/vpn/service.go Line: 15 Suggested diff: ```diff - "github.com/go-jose/go-jose/v4/json" + // Use go-jose’s custom JSON fork to ensure strict case-sensitive matching + // and duplicate-key rejection required by JOSE (JWT/JWE/JWS) processing. + "github.com/go-jose/go-jose/v4/json" ``` <!-- 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 // Use go-jose’s custom JSON fork to ensure strict case-sensitive matching // and duplicate-key rejection required by JOSE (JWT/JWE/JWS) processing. "github.com/go-jose/go-jose/v4/json" ``` </details> <!-- suggestion_end --> <details> <summary>🤖 Prompt for AI Agents</summary> ``` In pokebedrock/vpn/service.go at line 15, add a comment above the import of "github.com/go-jose/go-jose/v4/json" explaining that this package is intentionally used instead of the standard library JSON to enforce case-sensitive field matching and reject duplicate keys for proper JOSE (JWT/JWE/JWS) compliance. This clarifies the purpose of the import and prevents confusion. ``` </details> <!-- This is an auto-generated comment by CodeRabbit --> <!-- fingerprinting:phantom:poseidon:panther -->
@ -0,0 +91,4 @@
}
return nil, lastErr
}
defer response.Body.Close()
coderabbitai[bot] (Migrated from github.com) commented 2025-07-04 12:21:26 +00:00

🛠️ Refactor suggestion

Fix defer placement to avoid resource leak in retry loop.

The defer response.Body.Close() statement inside the retry loop can accumulate multiple defers, potentially causing resource issues if many retries occur.

Move the defer inside each case block or use an explicit close:

 		response, err := s.client.Do(request)
 		cancel()
 		if err != nil {
 			lastErr = fmt.Errorf("request failed: %w", err)
 			if ErrorIsTemporary(err) {
 				continue
 			}
 			return nil, lastErr
 		}
-		defer response.Body.Close()

 		s.handleRateLimitHeaders(response.Header)

 		switch response.StatusCode {
 		case http.StatusOK:
+			defer response.Body.Close()
 			var responseModel ResponseModel
 			if err = json.NewDecoder(response.Body).Decode(&responseModel); err != nil {
 				return nil, fmt.Errorf("failed to decode response body: %w", err)
 			}
 			if responseModel.Status == "fail" {
 				return nil, fmt.Errorf("query failed: %s", responseModel.Message)
 			}
 			return &responseModel, nil
 		case http.StatusTooManyRequests:
+			response.Body.Close()
 			lastErr = fmt.Errorf("rate limited by api")
 			time.Sleep(time.Duration(attempt+1) * retryDelay)
 			continue
 		default:
+			response.Body.Close()
 			lastErr = fmt.Errorf("unexpected status code: %d", response.StatusCode)
 		}
📝 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.

        response, err := s.client.Do(request)
        cancel()
        if err != nil {
            lastErr = fmt.Errorf("request failed: %w", err)
            if ErrorIsTemporary(err) {
                continue
            }
            return nil, lastErr
        }

        s.handleRateLimitHeaders(response.Header)

        switch response.StatusCode {
        case http.StatusOK:
            // Close the body when returning from the OK case
            defer response.Body.Close()
            var responseModel ResponseModel
            if err = json.NewDecoder(response.Body).Decode(&responseModel); err != nil {
                return nil, fmt.Errorf("failed to decode response body: %w", err)
            }
            if responseModel.Status == "fail" {
                return nil, fmt.Errorf("query failed: %s", responseModel.Message)
            }
            return &responseModel, nil

        case http.StatusTooManyRequests:
            // Close immediately before retrying
            response.Body.Close()
            lastErr = fmt.Errorf("rate limited by api")
            time.Sleep(time.Duration(attempt+1) * retryDelay)
            continue

        default:
            // Close immediately before falling through
            response.Body.Close()
            lastErr = fmt.Errorf("unexpected status code: %d", response.StatusCode)
        }
🤖 Prompt for AI Agents
In pokebedrock/vpn/service.go at line 94, the defer statement closing
response.Body is inside a retry loop, causing multiple deferred calls and
potential resource leaks. To fix this, remove the defer from the loop and
instead explicitly call response.Body.Close() at the end of each iteration or
inside each case block after processing the response to ensure timely resource
release without accumulating defers.
_🛠️ Refactor suggestion_ **Fix defer placement to avoid resource leak in retry loop.** The `defer response.Body.Close()` statement inside the retry loop can accumulate multiple defers, potentially causing resource issues if many retries occur. Move the defer inside each case block or use an explicit close: ```diff response, err := s.client.Do(request) cancel() if err != nil { lastErr = fmt.Errorf("request failed: %w", err) if ErrorIsTemporary(err) { continue } return nil, lastErr } - defer response.Body.Close() s.handleRateLimitHeaders(response.Header) switch response.StatusCode { case http.StatusOK: + defer response.Body.Close() var responseModel ResponseModel if err = json.NewDecoder(response.Body).Decode(&responseModel); err != nil { return nil, fmt.Errorf("failed to decode response body: %w", err) } if responseModel.Status == "fail" { return nil, fmt.Errorf("query failed: %s", responseModel.Message) } return &responseModel, nil case http.StatusTooManyRequests: + response.Body.Close() lastErr = fmt.Errorf("rate limited by api") time.Sleep(time.Duration(attempt+1) * retryDelay) continue default: + response.Body.Close() lastErr = fmt.Errorf("unexpected status code: %d", response.StatusCode) } ``` <!-- 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 response, err := s.client.Do(request) cancel() if err != nil { lastErr = fmt.Errorf("request failed: %w", err) if ErrorIsTemporary(err) { continue } return nil, lastErr } s.handleRateLimitHeaders(response.Header) switch response.StatusCode { case http.StatusOK: // Close the body when returning from the OK case defer response.Body.Close() var responseModel ResponseModel if err = json.NewDecoder(response.Body).Decode(&responseModel); err != nil { return nil, fmt.Errorf("failed to decode response body: %w", err) } if responseModel.Status == "fail" { return nil, fmt.Errorf("query failed: %s", responseModel.Message) } return &responseModel, nil case http.StatusTooManyRequests: // Close immediately before retrying response.Body.Close() lastErr = fmt.Errorf("rate limited by api") time.Sleep(time.Duration(attempt+1) * retryDelay) continue default: // Close immediately before falling through response.Body.Close() lastErr = fmt.Errorf("unexpected status code: %d", response.StatusCode) } ``` </details> <!-- suggestion_end --> <details> <summary>🤖 Prompt for AI Agents</summary> ``` In pokebedrock/vpn/service.go at line 94, the defer statement closing response.Body is inside a retry loop, causing multiple deferred calls and potential resource leaks. To fix this, remove the defer from the loop and instead explicitly call response.Body.Close() at the end of each iteration or inside each case block after processing the response to ensure timely resource release without accumulating defers. ``` </details> <!-- This is an auto-generated comment by CodeRabbit --> <!-- fingerprinting:phantom:poseidon:panther -->
Sign in to join this conversation.
No description provided.