fix: resolve plex user mismatch due to caching issues (#1242)

* fix: resolve plex user mismatch due to caching issues

This commit addresses an issue where cached responses for PlexTV API
requests could return incorrect user data when multiple users were logged in.
This was caused by a shared cache key that did not account for differences
in auth tokens, i.e `X-Plex-Token`. The `serializeCacheKey` method should
now include headers in the cache key generation to ensure unique cache keys.
This should fix the plex user mismatch that occurred due to the same
cache key being used without accounting for the difference in auth
token.

fix #1227

* fix: adds the default params and optional params, add the headers in all methods

* refactor: apply review commits and rename params to options in cachekey
This commit is contained in:
Fallenbagel
2025-01-12 09:51:41 +08:00
committed by GitHub
parent 7d08f58c76
commit 131a5a2b0b

View File

@@ -69,10 +69,13 @@ class ExternalAPI {
ttl?: number, ttl?: number,
config?: RequestInit config?: RequestInit
): Promise<T> { ): Promise<T> {
const headers = { ...this.defaultHeaders, ...config?.headers };
const cacheKey = this.serializeCacheKey(endpoint, { const cacheKey = this.serializeCacheKey(endpoint, {
...this.params, ...this.params,
...params, ...params,
headers,
}); });
const cachedItem = this.cache?.get<T>(cacheKey); const cachedItem = this.cache?.get<T>(cacheKey);
if (cachedItem) { if (cachedItem) {
return cachedItem; return cachedItem;
@@ -81,10 +84,7 @@ class ExternalAPI {
const url = this.formatUrl(endpoint, params); const url = this.formatUrl(endpoint, params);
const response = await this.fetch(url, { const response = await this.fetch(url, {
...config, ...config,
headers: { headers,
...this.defaultHeaders,
...config?.headers,
},
}); });
if (!response.ok) { if (!response.ok) {
const text = await response.text(); const text = await response.text();
@@ -111,10 +111,13 @@ class ExternalAPI {
ttl?: number, ttl?: number,
config?: RequestInit config?: RequestInit
): Promise<T> { ): Promise<T> {
const headers = { ...this.defaultHeaders, ...config?.headers };
const cacheKey = this.serializeCacheKey(endpoint, { const cacheKey = this.serializeCacheKey(endpoint, {
config: { ...this.params, ...params }, config: { ...this.params, ...params },
headers,
data, data,
}); });
const cachedItem = this.cache?.get<T>(cacheKey); const cachedItem = this.cache?.get<T>(cacheKey);
if (cachedItem) { if (cachedItem) {
return cachedItem; return cachedItem;
@@ -124,10 +127,7 @@ class ExternalAPI {
const response = await this.fetch(url, { const response = await this.fetch(url, {
method: 'POST', method: 'POST',
...config, ...config,
headers: { headers,
...this.defaultHeaders,
...config?.headers,
},
body: data ? JSON.stringify(data) : undefined, body: data ? JSON.stringify(data) : undefined,
}); });
if (!response.ok) { if (!response.ok) {
@@ -155,10 +155,13 @@ class ExternalAPI {
ttl?: number, ttl?: number,
config?: RequestInit config?: RequestInit
): Promise<T> { ): Promise<T> {
const headers = { ...this.defaultHeaders, ...config?.headers };
const cacheKey = this.serializeCacheKey(endpoint, { const cacheKey = this.serializeCacheKey(endpoint, {
config: { ...this.params, ...params }, config: { ...this.params, ...params },
data, data,
headers,
}); });
const cachedItem = this.cache?.get<T>(cacheKey); const cachedItem = this.cache?.get<T>(cacheKey);
if (cachedItem) { if (cachedItem) {
return cachedItem; return cachedItem;
@@ -168,10 +171,7 @@ class ExternalAPI {
const response = await this.fetch(url, { const response = await this.fetch(url, {
method: 'PUT', method: 'PUT',
...config, ...config,
headers: { headers,
...this.defaultHeaders,
...config?.headers,
},
body: JSON.stringify(data), body: JSON.stringify(data),
}); });
if (!response.ok) { if (!response.ok) {
@@ -227,9 +227,11 @@ class ExternalAPI {
config?: RequestInit, config?: RequestInit,
overwriteBaseUrl?: string overwriteBaseUrl?: string
): Promise<T> { ): Promise<T> {
const headers = { ...this.defaultHeaders, ...config?.headers };
const cacheKey = this.serializeCacheKey(endpoint, { const cacheKey = this.serializeCacheKey(endpoint, {
...this.params, ...this.params,
...params, ...params,
headers,
}); });
const cachedItem = this.cache?.get<T>(cacheKey); const cachedItem = this.cache?.get<T>(cacheKey);
@@ -244,10 +246,7 @@ class ExternalAPI {
const url = this.formatUrl(endpoint, params, overwriteBaseUrl); const url = this.formatUrl(endpoint, params, overwriteBaseUrl);
this.fetch(url, { this.fetch(url, {
...config, ...config,
headers: { headers,
...this.defaultHeaders,
...config?.headers,
},
}).then(async (response) => { }).then(async (response) => {
if (!response.ok) { if (!response.ok) {
const text = await response.text(); const text = await response.text();
@@ -270,10 +269,7 @@ class ExternalAPI {
const url = this.formatUrl(endpoint, params, overwriteBaseUrl); const url = this.formatUrl(endpoint, params, overwriteBaseUrl);
const response = await this.fetch(url, { const response = await this.fetch(url, {
...config, ...config,
headers: { headers,
...this.defaultHeaders,
...config?.headers,
},
}); });
if (!response.ok) { if (!response.ok) {
const text = await response.text(); const text = await response.text();
@@ -293,10 +289,10 @@ class ExternalAPI {
return data; return data;
} }
protected removeCache(endpoint: string, params?: Record<string, string>) { protected removeCache(endpoint: string, options?: Record<string, string>) {
const cacheKey = this.serializeCacheKey(endpoint, { const cacheKey = this.serializeCacheKey(endpoint, {
...this.params, ...this.params,
...params, ...options,
}); });
this.cache?.del(cacheKey); this.cache?.del(cacheKey);
} }
@@ -325,13 +321,13 @@ class ExternalAPI {
private serializeCacheKey( private serializeCacheKey(
endpoint: string, endpoint: string,
params?: Record<string, unknown> options?: Record<string, unknown>
) { ) {
if (!params) { if (!options) {
return `${this.baseUrl}${endpoint}`; return `${this.baseUrl}${endpoint}`;
} }
return `${this.baseUrl}${endpoint}${JSON.stringify(params)}`; return `${this.baseUrl}${endpoint}${JSON.stringify(options)}`;
} }
private async getDataFromResponse(response: Response) { private async getDataFromResponse(response: Response) {