Skip to content

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

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions