Skip to content

fix: address all high/medium/low issues from code review - #5

Open
proxy-turkey wants to merge 3 commits into
KilimcininKorOglu:mainfrom
proxy-turkey:fix/code-review-all-issues
Open

fix: address all high/medium/low issues from code review#5
proxy-turkey wants to merge 3 commits into
KilimcininKorOglu:mainfrom
proxy-turkey:fix/code-review-all-issues

Conversation

@proxy-turkey

Copy link
Copy Markdown
Contributor

Summary

Addresses every high, medium, and low priority issue identified in the post-merge code review of v1.2.0.

High Severity (2 fixes)

  • Guard context type assertions (handlers.go): All 5 r.Context().Value("ccAPIKey").(string) calls replaced with ccAPIKeyFromContext() helper using safe two-value assertion — prevents panic if middleware ordering changes.
  • Handle rand.Read error (converter.go): randomHex now checks the error and falls back to a timestamp-based ID instead of silently returning all-zeros.

Medium Severity (5 fixes)

  • Per-session timeout tracking (handlers.go): Global consecutiveTimeouts atomic replaced with sync.Map keyed by sessionID — prevents one user's timeout from triggering "reduce context" hints for a different user.
  • Guard Choices[0] access (handlers.go): Added length check before indexing — prevents panic if upstream returns zero choices.
  • Configurable CORS origin (middleware.go): CORS now accepts an allowedOrigin parameter instead of hardcoding "*".
  • Safe JSON construction (claude-proxy.sh): Settings JSON now built via python3 json.dumps() with bash escaping fallback — prevents injection if the token contains quotes or backslashes.
  • Config package tests (config_test.go): 8 new test cases covering missing file, permission denied, invalid JSON, valid JSON, env overrides, validation, and defaults.

Low Severity (5 fixes)

  • Merge double message iteration (converter.go): OpenAI converter looped messages twice (convert + extract system); merged into single pass.
  • Extract buildCommandCodeConfig helper (converter.go): Eliminated ~30 lines of duplicated Config block across both OpenAI and Anthropic converters.
  • Fix snake_case param (client.go, init.go): cc_apiKeyccAPIKey across 7 functions.
  • Header allowlist (client.go): Replaced blocklist with allowlist (anthropic-*, accept, user-agent) for safer upstream forwarding.
  • Streaming-safe transport (client.go): Replaced http.Client{Timeout: 90s} with custom http.Transport + connection pooling — prevents long streaming responses from being killed.
  • Duration tag fix (config.go): modelRefreshIntervalMsmodelRefreshInterval (was silently treated as nanoseconds).

Verification

  • go build ./...
  • go vet ./...
  • go test ./... -count=1 ✅ (52 tests pass)
  • Live streaming test: 5 consecutive requests, all HTTP 200, ~1.7s consistent (pooling verified)
  • Long streaming test: 1000 tokens over 21.4s without timeout kill ✅
  • ccp interactive multi-turn tool use: ✅
  • Zero errors/warnings in proxy logs during all tests

Files changed

File Changes
internal/protocol/converter.go randomHex error handling, merged iteration, extracted helper
internal/http/handlers.go Safe type assertions, per-session timeouts, guard Choices[0]
internal/http/middleware.go Configurable CORS origin
internal/http/server.go Updated CORS call
internal/http/handlers_test.go Updated test for new function signature
internal/client/client.go Naming fix, header allowlist, streaming transport
internal/client/init.go Naming fix
internal/config/config.go Duration tag fix
internal/config/config_test.go New: 8 test cases
claude-proxy.sh Safe JSON construction

High:
- Guard all 5 context type assertions with ccAPIKeyFromContext helper
  (handlers.go) — prevents panic if middleware ordering changes
- Handle rand.Read error in randomHex, fall back to timestamp (converter.go)

Medium:
- Replace global consecutiveTimeouts with per-session sync.Map keyed
  by sessionID — prevents timeout counter leaking across users
- Guard Choices[0] index access with length check (handlers.go)
- Make CORS origin configurable instead of hardcoded "*" (middleware.go)
- Build settings JSON via python3 json.dumps in claude-proxy.sh to
  prevent injection if token contains quotes/backslashes
- Add config package tests: missing file, permission denied, invalid
  JSON, valid JSON, env overrides, validation (config_test.go)

Low:
- Merge double message iteration into single pass (converter.go)
- Extract buildCommandCodeConfig helper to eliminate duplicated
  14-field Config block across both converters
- Fix snake_case cc_apiKey param to ccAPIKey across client.go/init.go
- Replace header blocklist with allowlist (anthropic-* + standard)
  for safer upstream forwarding (client.go)
- Use custom http.Transport with connection pooling instead of
  http.Client timeout that kills long streaming responses (client.go)
- Fix modelRefreshIntervalMs JSON tag to modelRefreshInterval
  (was silently treated as nanoseconds instead of duration)

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces several improvements, including safer JSON construction in claude-proxy.sh using Python, session-specific timeout tracking in HTTP handlers to prevent cross-user state leakage, and an allowlist-based header forwarding mechanism in the client. It also refactors configuration metadata building and adds a comprehensive test suite for configuration loading. Feedback on these changes highlights a few critical issues: the custom http.Transport should clone http.DefaultTransport to retain essential default settings like dial timeouts, and the new configuration tests should be updated to use t.TempDir() instead of hardcoded /tmp paths and platform-specific calls like os.Getuid() to ensure cross-platform compatibility on Windows.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread internal/client/client.go
Comment on lines +35 to +39
transport := &http.Transport{
MaxIdleConns: 20,
MaxIdleConnsPerHost: 10,
IdleConnTimeout: 90 * time.Second,
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Creating a raw &http.Transport{} from scratch without copying http.DefaultTransport or configuring a custom DialContext means you lose critical default settings. Specifically, you lose the default 30-second dial timeout, keep-alive settings, TLS handshake timeouts, and system proxy support. This can cause connection attempts to hang indefinitely under poor network conditions.

Instead, clone http.DefaultTransport and customize only the connection pooling fields.

	transport := http.DefaultTransport.(*http.Transport).Clone()
	transport.MaxIdleConns = 20
	transport.MaxIdleConnsPerHost = 10
	transport.IdleConnTimeout = 90 * time.Second

Comment on lines +26 to +46
func TestLoadFailsOnPermissionDenied(t *testing.T) {
dir := t.TempDir()
path := filepath.Join(dir, "config.json")
if err := os.WriteFile(path, []byte(`{"port":3050}`), 0644); err != nil {
t.Fatalf("setup: %v", err)
}
if err := os.Chmod(path, 0000); err != nil {
t.Fatalf("chmod: %v", err)
}
t.Cleanup(func() { os.Chmod(path, 0644) })

// Skip if running as root (root bypasses file permissions).
if os.Getuid() == 0 {
t.Skip("running as root, permission test not applicable")
}

_, err := Load(path)
if err == nil {
t.Fatal("Load() error = nil, want error for unreadable file")
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

os.Getuid() is not supported on Windows, which will cause this test file to fail compilation on Windows platforms. Additionally, os.Chmod(path, 0000) does not reliably make files unreadable on Windows.

To test the read failure path in a fully cross-platform and robust manner without needing root/administrator checks, you can pass a directory path (like t.TempDir()) to Load(). Attempting to read a directory as a file will fail with a read error on all operating systems.

func TestLoadFailsOnReadError(t *testing.T) {
	dir := t.TempDir()
	_, err := Load(dir)
	if err == nil {
		t.Fatal("Load() error = nil, want error when path is a directory")
	}
}

Comment thread internal/config/config_test.go Outdated
Comment thread internal/config/config_test.go Outdated
@KilimcininKorOglu

Copy link
Copy Markdown
Owner

@proxy-turkey gemini'nin önerilerini kontrol ettin mi?

KilimcininKorOglu and others added 2 commits July 15, 2026 16:51
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants