Skip to content

[Refactoring] Split containers/api-proxy/proxy-utils.js into focused utility modules (extract adapter-factory) #4880

@github-actions

Description

@github-actions

Refactoring Opportunity

Summary

  • File: containers/api-proxy/proxy-utils.js
  • Current size: 410 lines
  • Responsibilities identified: 5 distinct utility concerns in a single "grab-bag" module
  • Score: 5 (+3 clearly >2 distinct responsibilities, +2 security-critical: credential injection infrastructure)

Evidence

proxy-utils.js has accumulated utilities from multiple conceptual domains:

Concern 1 — URL normalization (lines 20–115, ~96 lines)
Four functions that normalize API target URLs and build upstream request paths:

  • normalizeApiTarget(value) — strips scheme, injects https:// for bare hostnames
  • normalizeBasePath(rawPath) — normalizes URL path prefixes
  • buildUpstreamPath(reqUrl, targetHost, basePath) — constructs the final upstream URL path
  • stripGeminiKeyParam(reqUrl) — strips key= query param from Gemini URLs

Concern 2 — Proxy request utilities (lines 142–202, ~61 lines)
Two functions used during request forwarding:

  • shouldStripHeader(name) — determines which inbound headers to drop
  • composeBodyTransforms(first, second) — chains two body-transform functions

Concern 3 — Provider response factories (lines 205–232, ~28 lines)
Two factory functions for generating standard error/health responses:

  • makeProviderNotConfiguredResponse(provider, port, message)
  • makeUnconfiguredHealthResponse(service, error, status)

Concern 4 — Auth validation utilities (lines 234–274, ~41 lines)
Two auth/credential validation helpers:

  • isValidHeaderName(name) — validates that a custom auth-header name is a legal HTTP header
  • validateAuthHeaderEnv(envVarName, rawValue, defaultHeader) — validates API key env vars

Concern 5 — Provider adapter factory (lines 275–408, ~134 lines)
Two factory functions that are the foundation of the credential-injection infrastructure:

  • createBaseAdapterConfig(env, { keyEnvVar, targetEnvVar, ... }) — reads API key from env and builds base provider config
  • createAdapterMethods(opts)78 lines — creates the getAuthHeaders, injectHeaders, getTargetHost, isConfigured methods used by every provider adapter (OpenAI, Anthropic, Copilot, Gemini)

Concerns #4 and #5 touch security-critical credential handling: createBaseAdapterConfig reads API keys from environment variables, and createAdapterMethods generates the injectHeaders closures that insert x-api-key, Authorization, and x-goog-api-key headers into upstream requests.

All 5 concerns are currently imported à la carte by different callers; providers import URL functions AND adapter factories from the same file.

Proposed Split

containers/api-proxy/adapter-factory.js (~134 lines) — extract concern #5

  • Moves createBaseAdapterConfig and createAdapterMethods here
  • This is the highest-risk section to change (credential injection path); isolating it makes security reviews easier
  • Already referenced in ADDING-A-PROVIDER.md as the canonical import for new providers

containers/api-proxy/proxy-utils.js (reduced to ~275 lines) — retains concerns #1#4

  • URL normalization, proxy request utilities, response factories, auth validation

Or if a further split is desired:

The minimal change (extract only adapter-factory.js) has the best blast-radius/benefit ratio.

Affected Callers

grep -rn "require.*proxy-utils" containers/ src/ 2>/dev/null

Known callers importing from proxy-utils:

  • containers/api-proxy/proxy-request.jsbuildUpstreamPath, shouldStripHeader
  • containers/api-proxy/server.js — URL and response utilities
  • containers/api-proxy/providers/openai.js, anthropic.js, copilot.js, gemini.js — adapter factory + auth utils
  • containers/api-proxy/providers/copilot-byok.jsisValidHeaderName
  • containers/api-proxy/providers/copilot-auth.jsnormalizeApiTarget
  • Test files: server.auth.test.js, server.routing.test.js, server.gemini.test.js, server.models.test.js

Provider callers currently import both URL utilities and adapter factories from the same module; separating them makes each provider's dependency surface explicit.

Effort Estimate

Low — extracting createBaseAdapterConfig and createAdapterMethods to a new adapter-factory.js is a mechanical file split. Only provider files need their require('./proxy-utils') calls updated to require('./adapter-factory') for those two symbols.

Benefits

  • The credential-injection adapter factory is isolated for easier security review
  • proxy-utils.js becomes a focused proxy-request utilities file
  • Providers can import just the adapter factory without pulling in URL normalization utilities
  • ADDING-A-PROVIDER.md already documents createBaseAdapterConfig/createAdapterMethods as the provider extension point — a dedicated module makes this clearer

Detected by Refactoring Scanner workflow. Run date: 2026-06-13

Generated by Refactoring Opportunity Scanner ·

  • expires on Aug 12, 2026, 3:35 PM UTC

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions