UNPKG

@juspay/neurolink

Version:

Universal AI Development Platform with working MCP integration, multi-provider support, and professional CLI. Built-in tools operational, 58+ external MCP servers discoverable. Connect to filesystem, GitHub, database operations, and more. Build, test, and

286 lines (285 loc) 11.1 kB
/** * AWS SDK Global Agent Configuration for Proxy Support * Configures Node.js global HTTP/HTTPS agents to work with AWS SDK * Ensures BedrockRuntimeClient and other AWS services respect proxy settings */ import { logger } from "../utils/logger.js"; /** * Configure global Node.js agents for AWS SDK proxy support * This ensures BedrockRuntimeClient and other AWS SDK clients respect proxy settings */ export async function configureAWSProxySupport() { try { // Check if proxy is needed for AWS endpoints const testUrl = "https://bedrock-runtime.us-east-1.amazonaws.com"; const proxyUrl = await getProxyUrlForTarget(testUrl); if (!proxyUrl) { logger.debug("[AWS Proxy] No proxy configuration needed for AWS SDK"); return; } logger.debug("[AWS Proxy] Configuring global agents for AWS SDK", { proxyUrl: proxyUrl.replace(/\/\/[^:]+:[^@]+@/, "//*****:*****@"), targetEndpoint: testUrl, }); // Configure global agents await configureGlobalAgents(proxyUrl); logger.info("[AWS Proxy] AWS SDK proxy support configured successfully"); } catch (error) { logger.error("[AWS Proxy] Failed to configure AWS SDK proxy support", { error, }); // Don't throw - allow AWS SDK to work without proxy } } /** * Configure Node.js global HTTP/HTTPS agents */ async function configureGlobalAgents(proxyUrl) { try { const parsed = new URL(proxyUrl); logger.debug("[AWS Proxy] Configuring global agents", { protocol: parsed.protocol, hostname: parsed.hostname, port: parsed.port || getDefaultPort(parsed.protocol), }); // For HTTP/HTTPS proxies, we need to set global agents if (parsed.protocol === "http:" || parsed.protocol === "https:") { await configureHttpAgents(proxyUrl); } else if (parsed.protocol === "socks4:" || parsed.protocol === "socks5:") { await configureSocksAgents(proxyUrl); } else { throw new Error(`Unsupported proxy protocol for AWS SDK: ${parsed.protocol}`); } } catch (error) { logger.error("[AWS Proxy] Failed to configure global agents", { proxyUrl, error, }); throw error; } } /** * Configure HTTP/HTTPS proxy agents using existing proxy infrastructure */ async function configureHttpAgents(proxyUrl) { // No-op here. Prefer explicit handler injection at client construction time. logger.debug("[AWS Proxy] Skipping global env/agent mutation; use injected HttpHandler instead", { proxyUrl: proxyUrl.replace(/\/\/[^:]+:[^@]+@/, "//*****:*****@"), }); } /** * Configure SOCKS proxy agents - simplified approach */ async function configureSocksAgents(proxyUrl) { // SOCKS via HTTP(S)_PROXY won't work; avoid setting to socks:// // Setting HTTP_PROXY/HTTPS_PROXY to a socks:// URL is not respected by Node's https module nor by AWS SDK handlers logger.warn("[AWS Proxy] SOCKS proxy configuration not supported for AWS SDK", { proxyUrl: proxyUrl.replace(/\/\/[^:]+:[^@]+@/, "//*****:*****@"), reason: "AWS SDK v3 does not support SOCKS proxies via environment variables", }); throw new Error(`SOCKS proxy configuration not supported for AWS SDK. Consider using HTTP/HTTPS proxy instead. ` + `For SOCKS support, use a proxy-aware agent injected into AWS clients.`); } /** * Minimal HTTP agent configuration (fallback) */ async function _configureMinimalHttpAgents(_proxyUrl) { // Remove broken fallback. Use explicit proxy-aware HttpHandler instead. logger.warn("[AWS Proxy] Minimal agent fallback removed; a proper proxy agent is required."); } /** * Create a proxy-aware HTTP handler for AWS SDK clients * This is the proper way to inject proxy support into AWS SDK v3 clients */ export async function createAWSProxyHandler(targetUrl) { try { const testUrl = targetUrl || "https://bedrock-runtime.us-east-1.amazonaws.com"; const proxyUrl = await getProxyUrlForTarget(testUrl); if (!proxyUrl) { logger.debug("[AWS Proxy] No proxy configured, using default HTTP handler"); return null; } logger.debug("[AWS Proxy] Creating proxy-aware HTTP handler for AWS SDK", { proxyUrl: proxyUrl.replace(/\/\/[^:]+:[^@]+@/, "//*****:*****@"), }); // Dynamically import proxy agent modules const parsed = new URL(proxyUrl); if (parsed.protocol === "http:" || parsed.protocol === "https:") { try { // Use undici ProxyAgent for HTTP/HTTPS proxies const { ProxyAgent } = await import("undici"); const proxyAgent = new ProxyAgent(proxyUrl); // Create a custom dispatcher wrapper for AWS SDK return { async handle(request) { const { fetch } = await import("undici"); const req = request; return fetch(req.url, { method: req.method, headers: req.headers, body: req.body, dispatcher: proxyAgent, }); }, }; } catch (undiciError) { logger.warn("[AWS Proxy] No suitable proxy agent available", { undiciError: undiciError instanceof Error ? undiciError.message : String(undiciError), }); return null; } } else { logger.warn("[AWS Proxy] Unsupported proxy protocol for AWS SDK", { protocol: parsed.protocol, }); return null; } } catch (error) { logger.error("[AWS Proxy] Failed to create proxy-aware HTTP handler", { error, }); return null; } } /** * Get default port for protocol */ function getDefaultPort(protocol) { switch (protocol) { case "http:": return 8080; case "https:": return 8080; case "socks4:": return 1080; case "socks5:": return 1080; default: return 8080; } } // Import shared NO_PROXY utility import { shouldBypassProxySimple } from "./utils/noProxyUtils.js"; /** * Get proxy URL for specific target (reuse existing logic) */ async function getProxyUrlForTarget(targetUrl) { try { // Simple fallback proxy detection using environment variables // This is more reliable than trying to import internal functions const httpProxy = process.env.HTTP_PROXY || process.env.http_proxy; const httpsProxy = process.env.HTTPS_PROXY || process.env.https_proxy; const allProxy = process.env.ALL_PROXY || process.env.all_proxy; const noProxy = process.env.NO_PROXY || process.env.no_proxy; // Check if target should bypass proxy using shared utility if (noProxy && shouldBypassProxySimple(targetUrl, noProxy)) { return null; } // Use HTTPS proxy for HTTPS URLs, HTTP proxy for HTTP URLs const url = new URL(targetUrl); if (url.protocol === "https:" && (httpsProxy || allProxy)) { return httpsProxy || allProxy || null; } else if (url.protocol === "http:" && httpProxy) { return httpProxy; } else if (httpProxy) { // Fallback to HTTP proxy for any protocol return httpProxy; } else if (allProxy) { return allProxy; } return null; } catch (error) { // Fallback to simple environment variable check // (Ensure any logged URLs here are masked before emitting.) logger.warn("[AWS Proxy] Error in proxy detection, using simple fallback", { error: error instanceof Error ? error.message : String(error), }); // Check NO_PROXY bypass first in fallback path too const noProxy = process.env.NO_PROXY || process.env.no_proxy; if (noProxy && shouldBypassProxySimple(targetUrl, noProxy)) { return null; } const url = new URL(targetUrl); const httpsProxy = process.env.HTTPS_PROXY || process.env.https_proxy; const httpProxy = process.env.HTTP_PROXY || process.env.http_proxy; const allProxy = process.env.ALL_PROXY || process.env.all_proxy; if (url.protocol === "https:" && httpsProxy) { return httpsProxy; } if (url.protocol === "http:" && httpProxy) { return httpProxy; } if (allProxy) { return allProxy; } return null; } } /** * Clean up global agents (for testing or shutdown) */ export async function cleanupAWSProxySupport() { try { const http = await import("http"); const https = await import("https"); // Reset to default agents https.globalAgent = new https.Agent(); http.globalAgent = new http.Agent(); logger.debug("[AWS Proxy] Global agents reset to defaults"); } catch (error) { logger.warn("[AWS Proxy] Failed to cleanup global agents", { error }); } } /** * Test AWS endpoint connectivity through proxy */ export async function testAWSProxyConnectivity() { try { const testUrl = "https://bedrock-runtime.us-east-1.amazonaws.com"; const proxyUrl = await getProxyUrlForTarget(testUrl); if (!proxyUrl) { logger.debug("[AWS Proxy] No proxy configured, direct connection test"); return true; // No proxy needed } logger.debug("[AWS Proxy] Testing proxy connectivity to AWS", { testUrl, proxyUrl: proxyUrl.replace(/\/\/[^:]+:[^@]+@/, "//*****:*****@"), }); // Simple connectivity test using fetch with AbortController for timeout const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 5000); // 5 second timeout // Use proxy-aware fetch instead of raw fetch const { createProxyFetch } = await import("./proxyFetch.js"); const proxyAwareFetch = createProxyFetch(); const response = await proxyAwareFetch(testUrl, { method: "HEAD", signal: controller.signal, }); clearTimeout(timeoutId); const success = response.status < 500; // Accept any non-5xx response logger.debug("[AWS Proxy] AWS proxy connectivity test", { success, status: response.status, statusText: response.statusText, }); return success; } catch (error) { logger.warn("[AWS Proxy] AWS proxy connectivity test failed", { error }); return false; } }