fix(playback): escape commas in mpv http header fields (#1321)

This commit is contained in:
wretchwatson authored and GitHub committed 2026-08-01 15:17:48 +02:00
1 parent b14ce2452b
commit 814161274b
3 files changed
+54

No files matched your search

@@ -0,0 +1,10 @@
---
type: fix
area: playback
---
Stalker live TV plays again in the embedded MPV player. The MAG250 user agent
contains a comma (`KHTML, like Gecko`), which MPV splits in its comma-separated
`--http-header-fields` list, truncating `X-User-Agent` so strict portals reject
the stream with HTTP 400. Commas and backslashes in header values are now
escaped on the Windows/Linux and macOS embedded-MPV paths.
@@ -766,6 +766,19 @@ void onRenderContextUpdate(void* context)
}
}
void replaceAllInPlace(std::string& value, const std::string& from, const std::string& to)
{
if (from.empty()) {
return;
}
size_t position = 0;
while ((position = value.find(from, position)) != std::string::npos) {
value.replace(position, from.length(), to);
position += to.length();
}
}
std::string joinHeaderFields(const Napi::Object& headers)
{
const Napi::Array propertyNames = headers.GetPropertyNames();
@@ -789,6 +802,15 @@ std::string joinHeaderFields(const Napi::Object& headers)
continue;
}
// mpv's `--http-header-fields` option is a comma-separated list
// (OPT_STRINGLIST). Header values that themselves contain commas
// (e.g. the Stalker MAG250 user agent "...(KHTML, like Gecko) MAG250")
// must be escaped so mpv does not split them into bogus fields and
// the server rejects the request with HTTP 400. mpv strips the
// backslash and keeps the comma inside the header value.
replaceAllInPlace(value, "\\", "\\\\");
replaceAllInPlace(value, ",", "\\,");
fields.push_back(key + ": " + value);
}
@@ -289,6 +289,19 @@ std::string normalizeEnvValue(const char* value)
return result;
}
void replaceAllInPlace(std::string& value, const std::string& from, const std::string& to)
{
if (from.empty()) {
return;
}
size_t position = 0;
while ((position = value.find(from, position)) != std::string::npos) {
value.replace(position, from.length(), to);
position += to.length();
}
}
std::string joinHeaderFields(const Napi::Object& headers)
{
const Napi::Array propertyNames = headers.GetPropertyNames();
@@ -312,6 +325,15 @@ std::string joinHeaderFields(const Napi::Object& headers)
continue;
}
// mpv's `--http-header-fields` option is a comma-separated list
// (OPT_STRINGLIST). Header values that themselves contain commas
// (e.g. the Stalker MAG250 user agent "...(KHTML, like Gecko) MAG250")
// must be escaped so mpv does not split them into bogus fields and
// the server rejects the request with HTTP 400. mpv strips the
// backslash and keeps the comma inside the header value.
replaceAllInPlace(value, "\\", "\\\\");
replaceAllInPlace(value, ",", "\\,");
fields.push_back(key + ": " + value);
}