fix(web-backend): proxy through registered provider targets

This commit is contained in:
4gray committed 2026-05-15 18:39:03 +02:00
1 parent 7524f46f97
commit 6961ad8b65
4 files changed
+275 -93

No files matched your search

+90 -40
View File
@@ -5,7 +5,7 @@ import { SwUpdate } from '@angular/service-worker';
import { Store } from '@ngrx/store';
import { TranslateService } from '@ngx-translate/core';
import { PlaylistActions } from '@iptvnator/m3u-state';
import { catchError, firstValueFrom, throwError } from 'rxjs';
import { catchError, firstValueFrom, from, switchMap, throwError } from 'rxjs';
import { DataService } from '@iptvnator/services';
import {
ERROR,
@@ -49,6 +49,10 @@ interface ErrorStatus {
readonly status?: number;
}
interface ProviderTargetRegistration {
readonly targetId: string;
}
@Injectable({
providedIn: 'root',
})
@@ -59,6 +63,7 @@ export class PwaService extends DataService {
private readonly store = inject(Store);
private readonly swUpdate = inject(SwUpdate);
private readonly translateService = inject(TranslateService);
private readonly providerTargetIds = new Map<string, Promise<string>>();
private readonly silentXtreamActions = new Set<string>([
XtreamCodeActions.GetAccountInfo,
XtreamCodeActions.GetLiveCategories,
@@ -270,39 +275,49 @@ export class PwaService extends DataService {
},
}
: {};
const requestPayload = {
method: 'GET',
url: `${this.corsProxyUrl}/xtream`,
params: {
url: payload.url,
...payload.params,
},
...(payload.macAddress
? {
headers: {
Cookie: `mac=${payload.macAddress}`,
},
}
: {}),
};
const context = createPortalDebugRequestContext({
let context = createPortalDebugRequestContext({
provider: 'xtream',
operation: payload.params?.action ?? 'unknown',
transport: 'pwa-http',
request: requestPayload,
request: {
method: 'GET',
params: payload.params,
url: `${this.corsProxyUrl}/xtream`,
},
});
logPortalDebugRequest(context);
try {
const targetId = await this.getProviderTargetId(payload.url);
const requestParams = {
targetId,
...payload.params,
};
const requestPayload = {
method: 'GET',
params: requestParams,
url: `${this.corsProxyUrl}/xtream`,
...(payload.macAddress
? {
headers: {
Cookie: `mac=${payload.macAddress}`,
},
}
: {}),
};
context = createPortalDebugRequestContext({
provider: 'xtream',
operation: payload.params?.action ?? 'unknown',
transport: 'pwa-http',
request: requestPayload,
});
logPortalDebugRequest(context);
let result: PwaErrorResult | PwaXtreamResult;
const response = (await firstValueFrom(
this.http.get<PwaXtreamResponse>(
`${this.corsProxyUrl}/xtream`,
{
params: {
url: payload.url,
...payload.params,
},
params: requestParams,
...headers,
}
)
@@ -442,29 +457,38 @@ export class PwaService extends DataService {
params: Record<string, string>;
macAddress: string;
}) {
const params = new URLSearchParams({
url: payload.url,
...payload.params,
macAddress: payload.macAddress,
});
const requestUrl = `${this.corsProxyUrl}/stalker?${params.toString()}`;
const context = createPortalDebugRequestContext({
let context = createPortalDebugRequestContext({
provider: 'stalker',
operation: payload.params?.action ?? 'unknown',
transport: 'pwa-http',
request: {
method: 'GET',
url: requestUrl,
params: {
url: payload.url,
...payload.params,
macAddress: payload.macAddress,
},
params: payload.params,
url: `${this.corsProxyUrl}/stalker`,
},
});
logPortalDebugRequest(context);
try {
const targetId = await this.getProviderTargetId(payload.url);
const requestParams = {
targetId,
...payload.params,
macAddress: payload.macAddress,
};
const params = new URLSearchParams(requestParams);
const requestUrl = `${this.corsProxyUrl}/stalker?${params.toString()}`;
context = createPortalDebugRequestContext({
provider: 'stalker',
operation: payload.params?.action ?? 'unknown',
transport: 'pwa-http',
request: {
method: 'GET',
params: requestParams,
url: requestUrl,
},
});
logPortalDebugRequest(context);
// Make the fetch request
const response = await fetch(requestUrl);
@@ -497,9 +521,35 @@ export class PwaService extends DataService {
}
getPlaylistFromUrl(url: string) {
return this.http.get(`${this.corsProxyUrl}/parse`, {
params: { url },
});
return from(this.getProviderTargetId(url)).pipe(
switchMap((targetId) =>
this.http.get(`${this.corsProxyUrl}/parse`, {
params: { targetId },
})
)
);
}
private getProviderTargetId(url: string): Promise<string> {
const cachedTargetId = this.providerTargetIds.get(url);
if (cachedTargetId) {
return cachedTargetId;
}
const targetIdRequest = firstValueFrom(
this.http.post<ProviderTargetRegistration>(
`${this.corsProxyUrl}/provider-targets`,
{ url }
)
)
.then((response) => response.targetId)
.catch((error) => {
this.providerTargetIds.delete(url);
throw error;
});
this.providerTargetIds.set(url, targetIdRequest);
return targetIdRequest;
}
removeAllListeners(type: string): void {