Files
iptvnator/libs/shared/interfaces/src/lib/stalker-request-url.util.ts
T
4grayandClaude Fable 5 65f81b7110 fix(pwa): bring the Stalker transport to parity with Electron (#1348)
* fix(pwa): bring the Stalker transport to parity with Electron

The self-hosted PWA's /stalker proxy now derives its portal requests from
the same shared identity and URL builders as the Electron main process:
MAG User-Agent/X-User-Agent, full STB cookie (mac + stb_lang + timezone +
serial-derived __cfduid), SN header, JsHttpRequest=1-xml defaulting, and
the sn-only-on-get_profile rule. macAddress/token/serialNumber are control
params consumed into headers and never echoed into the portal's query
string (handshake keeps its candidate token — protocol content). The
stalker-mock-server /stalker route mirrors the new contract through the
same shared builder.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test(stalker): forward the full identity header set in the mock /stalker mirror

Greptile review: the synthetic portal request kept only the cookie and
Authorization from the generated identity, so mock handlers could never
validate the SN/MAG-UA/Accept/Language/Connection headers the real proxy
sends. Forward the complete set, lowercased the way Express normalizes
incoming headers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-02 14:51:36 +02:00

44 lines
1.7 KiB
TypeScript

import { encodeStalkerCmdValue } from './stalker-cmd-encoding.util';
/**
* Builds the full Stalker portal request URL from an already-validated portal
* URL and the prepared request params. Shared by the Electron main process
* and the web-backend `/stalker` proxy so both transports emit the exact same
* wire format.
*
* The query string is assembled manually because the two parameter classes
* need different encodings:
*
* - `cmd` uses the minimal reference encoding (`encodeStalkerCmdValue`): a
* real MAG sends cmd unencoded and the portal decodes the query exactly
* once, so pre-encoded sequences (`%3A`) must pass through untouched while
* `&`/`#`/`;` are still escaped so a malicious portal cannot append query
* parameters through cmd.
* - every other param is fully `encodeURIComponent`-encoded.
*
* Any query string on the portal URL itself is intentionally dropped (the
* request params are the complete query), matching long-standing behavior.
*/
export function buildStalkerRequestUrl(
url: string,
requestParams: Record<string, string | number>
): string {
const urlObject = new URL(url);
const queryParts: string[] = [];
Object.entries(requestParams).forEach(([key, value]) => {
if (key === 'cmd') {
queryParts.push(`${key}=${encodeStalkerCmdValue(String(value))}`);
} else {
queryParts.push(`${key}=${encodeURIComponent(String(value))}`);
}
});
// Always add JsHttpRequest parameter if not present (required by Stalker API)
if (!requestParams['JsHttpRequest']) {
queryParts.push('JsHttpRequest=1-xml');
}
return `${urlObject.origin}${urlObject.pathname}?${queryParts.join('&')}`;
}