Compare commits

...

3 Commits

Author SHA1 Message Date
gauthier-th
dcea6e965d fix(proxy): initialize image proxies after the proxy is set up
The ImageProxy for TMDB and TheTVDB were initialized before the proxy settings were set up, so they
were ignoring the proxy settings.

fix #1787
2025-07-20 12:02:18 +02:00
Gauthier
75a7279ea2 fix(proxy): modify the registration of the axios interceptors (#1791)
The previous way of adding Axios interceptors added a new interceptor each time, causing lags after
a while because of all the duplicate interceptors added.

fix #1787
2025-07-20 11:33:16 +02:00
Ludovic Ortega
d53ffca5db chore(helm): bump jellyseerr to 2.7.1 (#1785)
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2025-07-15 22:06:29 +02:00
7 changed files with 45 additions and 26 deletions

View File

@@ -3,8 +3,8 @@ kubeVersion: ">=1.23.0-0"
name: jellyseerr-chart
description: Jellyseerr helm chart for Kubernetes
type: application
version: 2.6.0
appVersion: "2.7.0"
version: 2.6.1
appVersion: "2.7.1"
maintainers:
- name: Jellyseerr
url: https://github.com/Fallenbagel/jellyseerr

View File

@@ -1,6 +1,6 @@
# jellyseerr-chart
![Version: 2.6.0](https://img.shields.io/badge/Version-2.6.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2.7.0](https://img.shields.io/badge/AppVersion-2.7.0-informational?style=flat-square)
![Version: 2.6.1](https://img.shields.io/badge/Version-2.6.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2.7.1](https://img.shields.io/badge/AppVersion-2.7.1-informational?style=flat-square)
Jellyseerr helm chart for Kubernetes

View File

@@ -1,3 +1,4 @@
import { requestInterceptorFunction } from '@server/utils/customProxyAgent';
import type { AxiosInstance, AxiosRequestConfig } from 'axios';
import axios from 'axios';
import rateLimit from 'axios-rate-limit';
@@ -37,8 +38,7 @@ class ExternalAPI {
...options.headers,
},
});
this.axios.interceptors.request = axios.interceptors.request;
this.axios.interceptors.response = axios.interceptors.response;
this.axios.interceptors.request.use(requestInterceptorFunction);
if (options.rateLimit) {
this.axios = rateLimit(this.axios, {

View File

@@ -1,6 +1,7 @@
import type { User } from '@server/entity/User';
import type { TautulliSettings } from '@server/lib/settings';
import logger from '@server/logger';
import { requestInterceptorFunction } from '@server/utils/customProxyAgent';
import type { AxiosInstance } from 'axios';
import axios from 'axios';
import { uniqWith } from 'lodash';
@@ -123,8 +124,7 @@ class TautulliAPI {
}${settings.urlBase ?? ''}`,
params: { apikey: settings.apiKey },
});
this.axios.interceptors.request = axios.interceptors.request;
this.axios.interceptors.response = axios.interceptors.response;
this.axios.interceptors.request.use(requestInterceptorFunction);
}
public async getInfo(): Promise<TautulliInfo> {

View File

@@ -1,4 +1,5 @@
import logger from '@server/logger';
import { requestInterceptorFunction } from '@server/utils/customProxyAgent';
import axios from 'axios';
import rateLimit, { type rateLimitOptions } from 'axios-rate-limit';
import { createHash } from 'crypto';
@@ -150,8 +151,7 @@ class ImageProxy {
baseURL: baseUrl,
headers: options.headers,
});
this.axios.interceptors.request = axios.interceptors.request;
this.axios.interceptors.response = axios.interceptors.response;
this.axios.interceptors.request.use(requestInterceptorFunction);
if (options.rateLimitOptions) {
this.axios = rateLimit(this.axios, options.rateLimitOptions);

View File

@@ -4,27 +4,40 @@ import { Router } from 'express';
const router = Router();
const tmdbImageProxy = new ImageProxy('tmdb', 'https://image.tmdb.org', {
rateLimitOptions: {
maxRequests: 20,
maxRPS: 50,
},
});
const tvdbImageProxy = new ImageProxy('tvdb', 'https://artworks.thetvdb.com', {
rateLimitOptions: {
maxRequests: 20,
maxRPS: 50,
},
});
// Delay the initialization of ImageProxy instances until the proxy (if any) is properly configured
let _tmdbImageProxy: ImageProxy;
function initTmdbImageProxy() {
if (!_tmdbImageProxy) {
_tmdbImageProxy = new ImageProxy('tmdb', 'https://image.tmdb.org', {
rateLimitOptions: {
maxRequests: 20,
maxRPS: 50,
},
});
}
return _tmdbImageProxy;
}
let _tvdbImageProxy: ImageProxy;
function initTvdbImageProxy() {
if (!_tvdbImageProxy) {
_tvdbImageProxy = new ImageProxy('tvdb', 'https://artworks.thetvdb.com', {
rateLimitOptions: {
maxRequests: 20,
maxRPS: 50,
},
});
}
return _tvdbImageProxy;
}
router.get('/:type/*', async (req, res) => {
const imagePath = req.path.replace(/^\/\w+/, '');
try {
let imageData;
if (req.params.type === 'tmdb') {
imageData = await tmdbImageProxy.getImage(imagePath);
imageData = await initTmdbImageProxy().getImage(imagePath);
} else if (req.params.type === 'tvdb') {
imageData = await tvdbImageProxy.getImage(imagePath);
imageData = await initTvdbImageProxy().getImage(imagePath);
} else {
logger.error('Unsupported image type', {
imagePath,

View File

@@ -1,11 +1,15 @@
import type { ProxySettings } from '@server/lib/settings';
import logger from '@server/logger';
import axios from 'axios';
import axios, { type InternalAxiosRequestConfig } from 'axios';
import { HttpProxyAgent } from 'http-proxy-agent';
import { HttpsProxyAgent } from 'https-proxy-agent';
import type { Dispatcher } from 'undici';
import { Agent, ProxyAgent, setGlobalDispatcher } from 'undici';
export let requestInterceptorFunction: (
config: InternalAxiosRequestConfig
) => InternalAxiosRequestConfig;
export default async function createCustomProxyAgent(
proxySettings: ProxySettings
) {
@@ -73,7 +77,8 @@ export default async function createCustomProxyAgent(
axios.defaults.httpsAgent = new HttpsProxyAgent(proxyUrl, {
headers: token ? { 'proxy-authorization': token } : undefined,
});
axios.interceptors.request.use((config) => {
requestInterceptorFunction = (config) => {
const url = config.baseURL
? new URL(config.baseURL + (config.url || ''))
: config.url;
@@ -82,7 +87,8 @@ export default async function createCustomProxyAgent(
config.httpsAgent = false;
}
return config;
});
};
axios.interceptors.request.use(requestInterceptorFunction);
} catch (e) {
logger.error('Failed to connect to the proxy: ' + e.message, {
label: 'Proxy',