mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-08-27 04:07:05 +00:00
🌐 fix: Centralize Outbound Proxy Handling (#13726)
* fix: centralize outbound proxy handling * chore: sort proxy imports * test: update proxy helper mocks * fix: honor proxy bypasses consistently * fix: support http axios proxy targets
This commit is contained in:
parent
16bbc4b97e
commit
98704f28c1
34 changed files with 668 additions and 250 deletions
|
|
@ -1,12 +1,14 @@
|
|||
const path = require('path');
|
||||
const OpenAI = require('openai');
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
const { ProxyAgent, fetch } = require('undici');
|
||||
const { fetch } = require('undici');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const { Tool } = require('@librechat/agents/langchain/tools');
|
||||
const {
|
||||
getImageBasename,
|
||||
extractBaseURL,
|
||||
getProxyDispatcher,
|
||||
getEnvProxyDispatcher,
|
||||
createMinimalRetentionRequest,
|
||||
} = require('@librechat/api');
|
||||
const { FileContext, ContentTypes } = require('librechat-data-provider');
|
||||
|
|
@ -82,10 +84,10 @@ class DALLE3 extends Tool {
|
|||
config.apiKey = process.env.DALLE3_API_KEY;
|
||||
}
|
||||
|
||||
if (process.env.PROXY) {
|
||||
const proxyAgent = new ProxyAgent(process.env.PROXY);
|
||||
const proxyDispatcher = getProxyDispatcher();
|
||||
if (proxyDispatcher) {
|
||||
config.fetchOptions = {
|
||||
dispatcher: proxyAgent,
|
||||
dispatcher: proxyDispatcher,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -186,9 +188,9 @@ Error Message: ${error.message}`);
|
|||
|
||||
if (this.isAgent) {
|
||||
let fetchOptions = {};
|
||||
if (process.env.PROXY) {
|
||||
const proxyAgent = new ProxyAgent(process.env.PROXY);
|
||||
fetchOptions.dispatcher = proxyAgent;
|
||||
const dispatcher = getEnvProxyDispatcher();
|
||||
if (dispatcher) {
|
||||
fetchOptions.dispatcher = dispatcher;
|
||||
}
|
||||
const imageResponse = await fetch(theImageUrl, fetchOptions);
|
||||
const arrayBuffer = await imageResponse.arrayBuffer();
|
||||
|
|
|
|||
|
|
@ -2,9 +2,12 @@ const axios = require('axios');
|
|||
const fetch = require('node-fetch');
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const { HttpsProxyAgent } = require('https-proxy-agent');
|
||||
const { Tool } = require('@librechat/agents/langchain/tools');
|
||||
const { createMinimalRetentionRequest } = require('@librechat/api');
|
||||
const {
|
||||
applyAxiosProxyConfig,
|
||||
createMinimalRetentionRequest,
|
||||
getHttpsProxyAgent,
|
||||
} = require('@librechat/api');
|
||||
const { FileContext, ContentTypes } = require('librechat-data-provider');
|
||||
|
||||
const fluxApiJsonSchema = {
|
||||
|
|
@ -150,10 +153,7 @@ class FluxAPI extends Tool {
|
|||
|
||||
getAxiosConfig() {
|
||||
const config = {};
|
||||
if (process.env.PROXY) {
|
||||
config.httpsAgent = new HttpsProxyAgent(process.env.PROXY);
|
||||
}
|
||||
return config;
|
||||
return applyAxiosProxyConfig(config, this.baseUrl);
|
||||
}
|
||||
|
||||
/** @param {Object|string} value */
|
||||
|
|
@ -307,8 +307,9 @@ class FluxAPI extends Tool {
|
|||
try {
|
||||
// Fetch the image and convert to base64
|
||||
const fetchOptions = {};
|
||||
if (process.env.PROXY) {
|
||||
fetchOptions.agent = new HttpsProxyAgent(process.env.PROXY);
|
||||
const agent = getHttpsProxyAgent(imageUrl);
|
||||
if (agent) {
|
||||
fetchOptions.agent = agent;
|
||||
}
|
||||
const imageResponse = await fetch(imageUrl, fetchOptions);
|
||||
const arrayBuffer = await imageResponse.arrayBuffer();
|
||||
|
|
@ -539,8 +540,9 @@ class FluxAPI extends Tool {
|
|||
if (this.isAgent) {
|
||||
try {
|
||||
const fetchOptions = {};
|
||||
if (process.env.PROXY) {
|
||||
fetchOptions.agent = new HttpsProxyAgent(process.env.PROXY);
|
||||
const agent = getHttpsProxyAgent(imageUrl);
|
||||
if (agent) {
|
||||
fetchOptions.agent = agent;
|
||||
}
|
||||
const imageResponse = await fetch(imageUrl, fetchOptions);
|
||||
const arrayBuffer = await imageResponse.arrayBuffer();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
const path = require('path');
|
||||
const sharp = require('sharp');
|
||||
const { v4 } = require('uuid');
|
||||
const { ProxyAgent } = require('undici');
|
||||
const { GoogleGenAI } = require('@google/genai');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const { tool } = require('@librechat/agents/langchain/tools');
|
||||
|
|
@ -10,6 +9,7 @@ const {
|
|||
geminiToolkit,
|
||||
loadServiceKey,
|
||||
getBalanceConfig,
|
||||
getEnvProxyDispatcher,
|
||||
getTransactionsConfig,
|
||||
} = require('@librechat/api');
|
||||
const { getStrategyFunctions } = require('~/server/services/Files/strategies');
|
||||
|
|
@ -20,14 +20,14 @@ const { spendTokens, getFiles } = require('~/models');
|
|||
* This wraps globalThis.fetch to add a proxy dispatcher only for googleapis.com URLs
|
||||
* This is necessary because @google/genai SDK doesn't support custom fetch or httpOptions.dispatcher
|
||||
*/
|
||||
if (process.env.PROXY) {
|
||||
const googleApiProxyDispatcher = getEnvProxyDispatcher();
|
||||
if (googleApiProxyDispatcher) {
|
||||
const originalFetch = globalThis.fetch;
|
||||
const proxyAgent = new ProxyAgent(process.env.PROXY);
|
||||
|
||||
globalThis.fetch = function (url, options = {}) {
|
||||
const urlString = url.toString();
|
||||
if (urlString.includes('googleapis.com')) {
|
||||
options = { ...options, dispatcher: proxyAgent };
|
||||
options = { ...options, dispatcher: googleApiProxyDispatcher };
|
||||
}
|
||||
return originalFetch.call(this, url, options);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,12 +2,16 @@ const axios = require('axios');
|
|||
const { v4 } = require('uuid');
|
||||
const OpenAI = require('openai');
|
||||
const FormData = require('form-data');
|
||||
const { ProxyAgent } = require('undici');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const { HttpsProxyAgent } = require('https-proxy-agent');
|
||||
const { tool } = require('@librechat/agents/langchain/tools');
|
||||
const { ContentTypes, EImageOutputType } = require('librechat-data-provider');
|
||||
const { logAxiosError, oaiToolkit, extractBaseURL } = require('@librechat/api');
|
||||
const {
|
||||
logAxiosError,
|
||||
oaiToolkit,
|
||||
extractBaseURL,
|
||||
getProxyDispatcher,
|
||||
applyAxiosProxyConfig,
|
||||
} = require('@librechat/api');
|
||||
const { getStrategyFunctions } = require('~/server/services/Files/strategies');
|
||||
const { getFiles } = require('~/models');
|
||||
|
||||
|
|
@ -123,10 +127,10 @@ function createOpenAIImageTools(fields = {}) {
|
|||
throw new Error('Missing required field: prompt');
|
||||
}
|
||||
const clientConfig = { ...closureConfig };
|
||||
if (process.env.PROXY) {
|
||||
const proxyAgent = new ProxyAgent(process.env.PROXY);
|
||||
const proxyDispatcher = getProxyDispatcher();
|
||||
if (proxyDispatcher) {
|
||||
clientConfig.fetchOptions = {
|
||||
dispatcher: proxyAgent,
|
||||
dispatcher: proxyDispatcher,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -233,10 +237,10 @@ Error Message: ${error.message}`);
|
|||
}
|
||||
|
||||
const clientConfig = { ...closureConfig };
|
||||
if (process.env.PROXY) {
|
||||
const proxyAgent = new ProxyAgent(process.env.PROXY);
|
||||
const proxyDispatcher = getProxyDispatcher();
|
||||
if (proxyDispatcher) {
|
||||
clientConfig.fetchOptions = {
|
||||
dispatcher: proxyAgent,
|
||||
dispatcher: proxyDispatcher,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -349,9 +353,7 @@ Error Message: ${error.message}`);
|
|||
baseURL,
|
||||
};
|
||||
|
||||
if (process.env.PROXY) {
|
||||
axiosConfig.httpsAgent = new HttpsProxyAgent(process.env.PROXY);
|
||||
}
|
||||
applyAxiosProxyConfig(axiosConfig, baseURL);
|
||||
|
||||
if (process.env.IMAGE_GEN_OAI_AZURE_API_VERSION && process.env.IMAGE_GEN_OAI_BASEURL) {
|
||||
axiosConfig.params = {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
const { z } = require('zod');
|
||||
const { ProxyAgent, fetch } = require('undici');
|
||||
const { fetch } = require('undici');
|
||||
const { tool } = require('@librechat/agents/langchain/tools');
|
||||
const { getEnvProxyDispatcher } = require('@librechat/api');
|
||||
const { getApiKey } = require('./credentials');
|
||||
|
||||
function createTavilySearchTool(fields = {}) {
|
||||
|
|
@ -28,8 +29,9 @@ function createTavilySearchTool(fields = {}) {
|
|||
body: JSON.stringify(requestBody),
|
||||
};
|
||||
|
||||
if (process.env.PROXY) {
|
||||
fetchOptions.dispatcher = new ProxyAgent(process.env.PROXY);
|
||||
const dispatcher = getEnvProxyDispatcher();
|
||||
if (dispatcher) {
|
||||
fetchOptions.dispatcher = dispatcher;
|
||||
}
|
||||
|
||||
const response = await fetch('https://api.tavily.com/search', fetchOptions);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
const { ProxyAgent, fetch } = require('undici');
|
||||
const { fetch } = require('undici');
|
||||
const { Tool } = require('@librechat/agents/langchain/tools');
|
||||
const { getEnvironmentVariable } = require('@librechat/agents/langchain/utils/env');
|
||||
const { getEnvProxyDispatcher } = require('@librechat/api');
|
||||
|
||||
const tavilySearchJsonSchema = {
|
||||
type: 'object',
|
||||
|
|
@ -120,8 +121,9 @@ class TavilySearchResults extends Tool {
|
|||
body: JSON.stringify(requestBody),
|
||||
};
|
||||
|
||||
if (process.env.PROXY) {
|
||||
fetchOptions.dispatcher = new ProxyAgent(process.env.PROXY);
|
||||
const dispatcher = getEnvProxyDispatcher();
|
||||
if (dispatcher) {
|
||||
fetchOptions.dispatcher = dispatcher;
|
||||
}
|
||||
|
||||
const response = await fetch('https://api.tavily.com/search', fetchOptions);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,20 @@
|
|||
const DALLE3 = require('../DALLE3');
|
||||
const { ProxyAgent } = require('undici');
|
||||
|
||||
const processFileURL = jest.fn();
|
||||
const proxyEnvKeys = [
|
||||
'PROXY',
|
||||
'proxy',
|
||||
'HTTP_PROXY',
|
||||
'HTTPS_PROXY',
|
||||
'NO_PROXY',
|
||||
'http_proxy',
|
||||
'https_proxy',
|
||||
'no_proxy',
|
||||
];
|
||||
|
||||
function clearProxyEnv() {
|
||||
proxyEnvKeys.forEach((key) => delete process.env[key]);
|
||||
}
|
||||
|
||||
describe('DALLE3 Proxy Configuration', () => {
|
||||
let originalEnv;
|
||||
|
|
@ -13,13 +26,14 @@ describe('DALLE3 Proxy Configuration', () => {
|
|||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
process.env = { ...originalEnv };
|
||||
clearProxyEnv();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
process.env = originalEnv;
|
||||
});
|
||||
|
||||
it('should configure ProxyAgent in fetchOptions.dispatcher when PROXY env is set', () => {
|
||||
it('should configure fetchOptions.dispatcher when proxy env is set', () => {
|
||||
// Set proxy environment variable
|
||||
process.env.PROXY = 'http://proxy.example.com:8080';
|
||||
process.env.DALLE_API_KEY = 'test-api-key';
|
||||
|
|
@ -34,12 +48,10 @@ describe('DALLE3 Proxy Configuration', () => {
|
|||
expect(dalleWithProxy.openai._options).toBeDefined();
|
||||
expect(dalleWithProxy.openai._options.fetchOptions).toBeDefined();
|
||||
expect(dalleWithProxy.openai._options.fetchOptions.dispatcher).toBeDefined();
|
||||
expect(dalleWithProxy.openai._options.fetchOptions.dispatcher).toBeInstanceOf(ProxyAgent);
|
||||
expect(dalleWithProxy.openai._options.fetchOptions.dispatcher).toBeDefined();
|
||||
});
|
||||
|
||||
it('should not configure ProxyAgent when PROXY env is not set', () => {
|
||||
// Ensure PROXY is not set
|
||||
delete process.env.PROXY;
|
||||
it('should not configure a dispatcher when proxy env is not set', () => {
|
||||
process.env.DALLE_API_KEY = 'test-api-key';
|
||||
|
||||
// Create instance
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
const { ProxyAgent } = require('undici');
|
||||
|
||||
/**
|
||||
* These tests verify the proxy wrapper behavior for GeminiImageGen.
|
||||
* Instead of loading the full module (which has many dependencies),
|
||||
|
|
@ -29,14 +27,14 @@ describe('GeminiImageGen Proxy Configuration', () => {
|
|||
* This is the same logic from GeminiImageGen.js lines 30-42.
|
||||
*/
|
||||
function applyProxyWrapper() {
|
||||
if (process.env.PROXY) {
|
||||
const proxyDispatcher = process.env.PROXY ? { type: 'proxy-dispatcher' } : undefined;
|
||||
if (proxyDispatcher) {
|
||||
const _originalFetch = globalThis.fetch;
|
||||
const proxyAgent = new ProxyAgent(process.env.PROXY);
|
||||
|
||||
globalThis.fetch = function (url, options = {}) {
|
||||
const urlString = url.toString();
|
||||
if (urlString.includes('googleapis.com')) {
|
||||
options = { ...options, dispatcher: proxyAgent };
|
||||
options = { ...options, dispatcher: proxyDispatcher };
|
||||
}
|
||||
return _originalFetch.call(this, url, options);
|
||||
};
|
||||
|
|
@ -78,7 +76,7 @@ describe('GeminiImageGen Proxy Configuration', () => {
|
|||
await globalThis.fetch('https://generativelanguage.googleapis.com/v1/models', {});
|
||||
|
||||
expect(capturedOptions).toBeDefined();
|
||||
expect(capturedOptions.dispatcher).toBeInstanceOf(ProxyAgent);
|
||||
expect(capturedOptions.dispatcher).toEqual({ type: 'proxy-dispatcher' });
|
||||
});
|
||||
|
||||
it('should not add dispatcher to non-googleapis.com URLs', async () => {
|
||||
|
|
@ -118,7 +116,7 @@ describe('GeminiImageGen Proxy Configuration', () => {
|
|||
});
|
||||
|
||||
expect(capturedOptions).toBeDefined();
|
||||
expect(capturedOptions.dispatcher).toBeInstanceOf(ProxyAgent);
|
||||
expect(capturedOptions.dispatcher).toEqual({ type: 'proxy-dispatcher' });
|
||||
expect(capturedOptions.headers).toEqual(customHeaders);
|
||||
expect(capturedOptions.method).toBe('POST');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
const { fetch, ProxyAgent } = require('undici');
|
||||
const { fetch } = require('undici');
|
||||
const TavilySearchResults = require('../TavilySearchResults');
|
||||
const { getEnvProxyDispatcher } = require('@librechat/api');
|
||||
|
||||
jest.mock('undici');
|
||||
jest.mock('@librechat/api', () => ({
|
||||
getEnvProxyDispatcher: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('TavilySearchResults', () => {
|
||||
let originalEnv;
|
||||
|
|
@ -46,32 +50,29 @@ describe('TavilySearchResults', () => {
|
|||
fetch.mockResolvedValue(mockResponse);
|
||||
});
|
||||
|
||||
it('should use ProxyAgent when PROXY env var is set', async () => {
|
||||
const proxyUrl = 'http://proxy.example.com:8080';
|
||||
process.env.PROXY = proxyUrl;
|
||||
|
||||
const mockProxyAgent = { type: 'proxy-agent' };
|
||||
ProxyAgent.mockImplementation(() => mockProxyAgent);
|
||||
it('should use a shared proxy dispatcher when configured', async () => {
|
||||
const mockProxyDispatcher = { type: 'proxy-dispatcher' };
|
||||
getEnvProxyDispatcher.mockReturnValue(mockProxyDispatcher);
|
||||
|
||||
const instance = new TavilySearchResults({ TAVILY_API_KEY: mockApiKey });
|
||||
await instance._call({ query: 'test query' });
|
||||
|
||||
expect(ProxyAgent).toHaveBeenCalledWith(proxyUrl);
|
||||
expect(getEnvProxyDispatcher).toHaveBeenCalled();
|
||||
expect(fetch).toHaveBeenCalledWith(
|
||||
'https://api.tavily.com/search',
|
||||
expect.objectContaining({
|
||||
dispatcher: mockProxyAgent,
|
||||
dispatcher: mockProxyDispatcher,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('should not use ProxyAgent when PROXY env var is not set', async () => {
|
||||
delete process.env.PROXY;
|
||||
it('should not attach a dispatcher when no proxy is configured', async () => {
|
||||
getEnvProxyDispatcher.mockReturnValue(undefined);
|
||||
|
||||
const instance = new TavilySearchResults({ TAVILY_API_KEY: mockApiKey });
|
||||
await instance._call({ query: 'test query' });
|
||||
|
||||
expect(ProxyAgent).not.toHaveBeenCalled();
|
||||
expect(getEnvProxyDispatcher).toHaveBeenCalled();
|
||||
expect(fetch).toHaveBeenCalledWith(
|
||||
'https://api.tavily.com/search',
|
||||
expect.not.objectContaining({
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
const OpenAI = require('openai');
|
||||
const { ProxyAgent } = require('undici');
|
||||
const { isUserProvided, checkUserKeyExpiry } = require('@librechat/api');
|
||||
const { isUserProvided, checkUserKeyExpiry, getProxyDispatcher } = require('@librechat/api');
|
||||
const { ErrorTypes, EModelEndpoint } = require('librechat-data-provider');
|
||||
const { getUserKeyValues, getUserKeyExpiry } = require('~/models');
|
||||
|
||||
|
|
@ -45,10 +44,10 @@ const initializeClient = async ({ req, res, version }) => {
|
|||
opts.baseURL = baseURL;
|
||||
}
|
||||
|
||||
if (PROXY) {
|
||||
const proxyAgent = new ProxyAgent(PROXY);
|
||||
const proxyDispatcher = getProxyDispatcher(PROXY);
|
||||
if (proxyDispatcher) {
|
||||
opts.fetchOptions = {
|
||||
dispatcher: proxyAgent,
|
||||
dispatcher: proxyDispatcher,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
const OpenAI = require('openai');
|
||||
const { ProxyAgent } = require('undici');
|
||||
const {
|
||||
isUserProvided,
|
||||
resolveHeaders,
|
||||
constructAzureURL,
|
||||
checkUserKeyExpiry,
|
||||
getProxyDispatcher,
|
||||
} = require('@librechat/api');
|
||||
const { ErrorTypes, EModelEndpoint, mapModelToAzureConfig } = require('librechat-data-provider');
|
||||
const { getUserKeyValues, getUserKeyExpiry } = require('~/models');
|
||||
|
|
@ -157,10 +157,10 @@ const initializeClient = async ({ req, res, version, endpointOption, initAppClie
|
|||
opts.baseURL = baseURL;
|
||||
}
|
||||
|
||||
if (PROXY) {
|
||||
const proxyAgent = new ProxyAgent(PROXY);
|
||||
const proxyDispatcher = getProxyDispatcher(PROXY);
|
||||
if (proxyDispatcher) {
|
||||
opts.fetchOptions = {
|
||||
dispatcher: proxyAgent,
|
||||
dispatcher: proxyDispatcher,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@ const fs = require('fs').promises;
|
|||
const FormData = require('form-data');
|
||||
const { Readable } = require('stream');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const { HttpsProxyAgent } = require('https-proxy-agent');
|
||||
const { genAzureEndpoint, logAxiosError } = require('@librechat/api');
|
||||
const { genAzureEndpoint, logAxiosError, applyAxiosProxyConfig } = require('@librechat/api');
|
||||
const { extractEnvVariable, STTProviders } = require('librechat-data-provider');
|
||||
const { getAppConfig } = require('~/server/services/Config');
|
||||
|
||||
|
|
@ -303,9 +302,7 @@ class STTService {
|
|||
|
||||
const options = { headers };
|
||||
|
||||
if (process.env.PROXY) {
|
||||
options.httpsAgent = new HttpsProxyAgent(process.env.PROXY);
|
||||
}
|
||||
applyAxiosProxyConfig(options, url);
|
||||
|
||||
try {
|
||||
const response = await axios.post(url, data, options);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
const axios = require('axios');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const { HttpsProxyAgent } = require('https-proxy-agent');
|
||||
const { genAzureEndpoint, logAxiosError } = require('@librechat/api');
|
||||
const { genAzureEndpoint, logAxiosError, applyAxiosProxyConfig } = require('@librechat/api');
|
||||
const { extractEnvVariable, TTSProviders } = require('librechat-data-provider');
|
||||
const { getRandomVoiceId, createChunkProcessor, splitTextIntoChunks } = require('./streamAudio');
|
||||
const { getAppConfig } = require('~/server/services/Config');
|
||||
|
|
@ -267,9 +266,7 @@ class TTSService {
|
|||
|
||||
const options = { headers, responseType: stream ? 'stream' : 'arraybuffer' };
|
||||
|
||||
if (process.env.PROXY) {
|
||||
options.httpsAgent = new HttpsProxyAgent(process.env.PROXY);
|
||||
}
|
||||
applyAxiosProxyConfig(options, url);
|
||||
|
||||
try {
|
||||
return await axios.post(url, data, options);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
const cookies = require('cookie');
|
||||
const jwksRsa = require('jwks-rsa');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const { HttpsProxyAgent } = require('https-proxy-agent');
|
||||
const { SystemRoles } = require('librechat-data-provider');
|
||||
const { Strategy: JwtStrategy, ExtractJwt } = require('passport-jwt');
|
||||
const {
|
||||
|
|
@ -10,6 +9,7 @@ const {
|
|||
getOpenIdEmail,
|
||||
getOpenIdIssuer,
|
||||
normalizeOpenIdIssuer,
|
||||
getHttpsProxyAgent,
|
||||
math,
|
||||
} = require('@librechat/api');
|
||||
const { updateUser, findUser } = require('~/models');
|
||||
|
|
@ -73,8 +73,9 @@ const openIdJwtLogin = (openIdConfig) => {
|
|||
jwksUri: openIdConfig.serverMetadata().jwks_uri,
|
||||
};
|
||||
|
||||
if (process.env.PROXY) {
|
||||
jwksRsaOptions.requestAgent = new HttpsProxyAgent(process.env.PROXY);
|
||||
const requestAgent = getHttpsProxyAgent(jwksRsaOptions.jwksUri);
|
||||
if (requestAgent) {
|
||||
jwksRsaOptions.requestAgent = requestAgent;
|
||||
}
|
||||
|
||||
return new JwtStrategy(
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ jest.mock('@librechat/api', () => ({
|
|||
getOpenIdEmail: jest.requireActual('@librechat/api').getOpenIdEmail,
|
||||
getOpenIdIssuer: jest.fn(() => 'https://issuer.example.com'),
|
||||
normalizeOpenIdIssuer: jest.requireActual('@librechat/api').normalizeOpenIdIssuer,
|
||||
getHttpsProxyAgent: jest.fn(() => undefined),
|
||||
math: jest.fn((val, fallback) => fallback),
|
||||
}));
|
||||
jest.mock('~/models', () => ({
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ async function customFetch(url, options) {
|
|||
let fetchOptions = options;
|
||||
const dispatcher = getOpenIdProxyDispatcher();
|
||||
if (dispatcher) {
|
||||
logger.info(`[openidStrategy] proxy agent configured: ${process.env.PROXY}`);
|
||||
logger.info('[openidStrategy] proxy dispatcher configured');
|
||||
fetchOptions = {
|
||||
...options,
|
||||
dispatcher,
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ jest.mock('@librechat/api', () => ({
|
|||
},
|
||||
},
|
||||
extractBaseURL: jest.fn((url) => url),
|
||||
getProxyDispatcher: jest.fn(() => undefined),
|
||||
applyAxiosProxyConfig: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('~/server/services/Files/strategies', () => ({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue