doProxyRequestWithTimeout returns an error for every non-200 status and
executeProxyAttempt returned it as a plain, retryable error, so 4xx
client errors (400/404/405/...) were retried with exponential backoff
and the 4xx branch of isRetryableStatusCode was dead code.
Additionally, retry-go's finite-attempt loop only consults the custom
RetryIf, which overrode the default IsRecoverable gate, so retry.
Unrecoverable errors (non-retryable 4xx AND timeouts) were still
retried. Honor IsRecoverable in RetryIf so these never retry.
Now 5xx/429 are retried, other 4xx and timeouts fail fast.
Adds Test_proxyRetryPolicyByStatusCode locking in the policy.
BREAKING CHANGE: upgrades the HTTP framework from gofiber/fiber/v2 to gofiber/fiber/v3, and gofiber/websocket/v2 to gofiber/contrib/v3/websocket.
- Handlers now take fiber.Ctx (interface) instead of *fiber.Ctx. - DisableStartupMessage moved from fiber.Config to fiber.ListenConfig on the proxy/api/monitoring Listen calls. - cors AllowOrigins is now []string; c.BodyParser -> c.Bind().Body(). - app.Test takes fiber.TestConfig instead of an int timeout (tests updated). - WebSocket swapped to contrib/v3/websocket (same Conn/New/Config/IsCloseError/IsWebSocketUpgrade API; Conn.Query preserved). - Adopts fasthttp v1.71.0 (pulled by fiber v3), resolving the v1.71 Host-header enforcement that broke the prior pinned-v1.69 workaround.
fix(connpool): the background keep-alive goroutine no longer reads the mutable global cfg (captures HostGraphQL/HealthcheckGraphQL at pool creation). Under v3 timing it raced with parseConfig/test cfg reassignment; go test -race ./... is now clean (0 data races).
test: make the circuit-breaker cache-fallback and request-coalescing integration tests deterministic (cache TTL outlives the retry loop; coalescing asserts against a measured single-request baseline instead of a hard-coded count); drop the flaky timing-ratio assertion in TestTimingAttackResistance (constant-time guarantee comes from subtle.ConstantTimeCompare, not wall-clock timing).
Verified: go build, go vet, golangci-lint (0 issues), go test -race ./... (all packages pass, 0 races), govulncheck (no vulnerabilities). App + dashboard + WebSocket verified live under v3 in single-node and cluster modes.
* chore(security,refactor): extract sanitization and improve code quality
- [x] Extract sanitization functions to dedicated sanitization.go module
- [x] Add comprehensive golangci-lint v2 configuration with security rules
- [x] Replace interface{} with any type throughout codebase
- [x] Add admin API authentication security warning
- [x] Extract WebSocket and stats streaming constants
- [x] Add best-effort error handling comments for resource cleanup
- [x] Expand sensitive field patterns for improved PII redaction
- [x] Simplify safety checks and remove redundant nil validations
- [x] Improve test coverage for password field redaction patterns
* refactor: replace interface{} with any type alias
- [x] Replace all `map[string]interface{}` with `map[string]any`
- [x] Replace all `interface{}` with `any` in function signatures and type definitions
- [x] Update sync.Pool New function returns from `interface{}` to `any`
- [x] Add package documentation comments to 8 package files
- [x] Update type assertions and casts to work with `any` type
Optimized the getDetailsFromEnv function to reduce redundant lookups and improve type handling
Added direct environment variable access for better performance
Memory Cache Optimization:
Implemented a size-based compression threshold (1KB) to avoid compressing small payloads
Added cache size limits (10,000 entries) to prevent memory leaks
Implemented efficient eviction strategies for the oldest entries
Added atomic counter for thread-safe cache size tracking
Improved cleanup routines with GC triggering for large caches
Proxy Implementation:
Refactored the proxy code into smaller, focused functions for better maintainability
Optimized gzip handling for better performance
Improved error handling and logging
Enhanced tracing integration
GraphQL Processing:
Optimized introspection query checking with fast-path returns
Improved object pool usage
Added detailed comments for better code understanding
Split complex functions into smaller, more focused ones
Fixed test compatibility issues with introspection checking
Request Processing:
Refactored the request processing logic into smaller, focused functions
Separated user extraction, caching, and request handling for better maintainability
Improved error handling and response generation
Tracing Enhancements:
Added better span context management
Implemented custom attributes for more detailed tracing
Added sampling configuration to reduce overhead
Improved resource attribution with host and process information
Added timeout handling for tracing operations
Application Lifecycle:
Implemented graceful shutdown with proper signal handling
Added goroutine management with wait groups
Improved startup sequence with better error handling
Added timeout handling for shutdown operations
When the upstream server returns a redirect HTTP response code but its "Location" header is in lowercase, the proxy will retry the request 5 times and eventually fail with an "missing Location header for http redirect" error.
Since the HTTP spec says header names are case-insensitive, we should handle this case properly. Adjust fasthttp options accordingly
Ref: https://github.com/valyala/fasthttp/issues/1361
* This change introduces ability to set additional endpoint leading to the
instance of the graphql server connected to the read only database.
If regular query is detected and endpoint for `HOST_GRAPHQL_READONLY` value is set,
the query will be proxied to it. Mutations and non-graphql will be sent
to the `HOST_GRAPHQL` endpoint.