Skip to content

[Duplicate Code] Provider adapter auth-header scaffolding repeated across API proxy providers #5736

Description

@github-actions

Duplicate Code Opportunity

Summary

Evidence

containers/api-proxy/providers/openai.js lines 30-125:

function createOpenAIAdapter(env, deps = {}) {
  const { apiKey: openaiApiKey, rawTarget: openaiTarget, basePath: openaiBasePath } = createBaseAdapterConfig(env, {
    keyEnvVar: OPENAI_ENV.KEY,
    targetEnvVar: OPENAI_ENV.TARGET,
    basePathEnvVar: OPENAI_ENV.BASE_PATH,
    defaultTarget: 'api.openai.com',
  });
  // ...provider-specific target resolution...
  const bodyTransform = deps.bodyTransform || null;
  const { authProvider, oidcConfigured, runtimeMethods: oidcRuntimeMethods, validationSkip, skipModelsFetch, resolveAuthHeaders } = createProviderOidcAuth(env, { staticAuthToken: apiKey });
  function buildStaticAuthHeaders(key) {
    if (customAuthHeader) return { [customAuthHeader]: key };
    return { 'Authorization': `Bearer ${key}` };
  }
  const adapterMethods = createAdapterMethods({
    apiKey, rawTarget, basePath, provider: 'openai', port: 10000,
    validationHeaders: () => buildStaticAuthHeaders(apiKey),
    modelsFetchHeaders: () => buildStaticAuthHeaders(apiKey),
  });
  return buildProviderAdapter({
    name: 'openai', port: 10000, adapterMethods,
    getAuthHeaders() { return resolveAuthHeaders(/* token headers */, buildStaticAuthHeaders(apiKey)); },
    bodyTransform,
  });
}

containers/api-proxy/providers/anthropic.js lines 50-150:

function createAnthropicAdapter(env, deps = {}) {
  const { apiKey, rawTarget, basePath } = createBaseAdapterConfig(env, {
    keyEnvVar: ANTHROPIC_ENV.KEY,
    targetEnvVar: ANTHROPIC_ENV.TARGET,
    basePathEnvVar: ANTHROPIC_ENV.BASE_PATH,
    defaultTarget: 'api.anthropic.com',
  });
  const authHeaderName = validateAuthHeaderEnv(ANTHROPIC_ENV.AUTH_HEADER, env[ANTHROPIC_ENV.AUTH_HEADER], 'x-api-key');
  const { oidcProvider, oidcConfigured, runtimeMethods: oidcRuntimeMethods } = createProviderOidcAuth(env, { staticAuthToken: apiKey, oidcProviderFactory: /* ... */ });
  const bodyTransform = deps.bodyTransform || null;
  const adapterMethods = createAdapterMethods({
    apiKey, rawTarget, basePath, provider: 'anthropic', port: 10001,
    validationHeaders: () => ({
      ...resolveAuthHeadersWithFallback({ buildOidcHeaders: (token) => ({ 'Authorization': `Bearer ${token}` }), staticHeaders: { [authHeaderName]: apiKey } }),
      'anthropic-version': '2023-06-01',
    }),
    modelsFetchHeaders: () => ({ ...resolveAuthHeadersWithFallback(/* same auth inputs */) }),
  });
}

containers/api-proxy/providers/gemini.js lines 27-73:

function createGeminiAdapter(env, deps = {}) {
  const { apiKey, rawTarget, basePath } = createBaseAdapterConfig(env, {
    keyEnvVar: GEMINI_ENV.KEY,
    targetEnvVar: GEMINI_ENV.TARGET,
    basePathEnvVar: GEMINI_ENV.BASE_PATH,
    defaultTarget: 'generativelanguage.googleapis.com',
  });
  const bodyTransform = deps.bodyTransform || null;
  const adapterMethods = createAdapterMethods({
    apiKey, rawTarget, basePath, provider: 'gemini', port: 10003,
    validationHeaders: () => ({ 'x-goog-api-key': apiKey }),
    modelsFetchHeaders: () => ({ 'x-goog-api-key': apiKey }),
  });
  return buildProviderAdapter({
    name: 'gemini', port: 10003, adapterMethods,
    getAuthHeaders() { return { 'x-goog-api-key': apiKey }; },
    bodyTransform,
  });
}

Suggested Refactoring

Add a shared provider-auth helper near containers/api-proxy/adapter-factory.js, for example createProviderAuthScaffold({ env, envVars, defaults, headerBuilder, oidc, validation, models }), that returns { apiKey, rawTarget, basePath, bodyTransform, adapterMethods, getAuthHeaders }. Provider modules would supply only provider-specific target overrides, headers, transforms, and unconfigured responses.

Affected Files

  • containers/api-proxy/providers/openai.js — lines 30-125
  • containers/api-proxy/providers/anthropic.js — lines 50-150
  • containers/api-proxy/providers/gemini.js — lines 27-73

Effort Estimate

Medium


Detected by Duplicate Code Detector workflow. Run date: 2026-06-30

Generated by Duplicate Code Detector · 105.8 AIC · ⊞ 23.1K ·

  • expires on Jul 30, 2026, 10:07 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