Fix Xbox proxy: Filter REQUEST body instead of response

BREAKING FIX: DeviceProfile is sent FROM client TO server in request body,
not returned in response. This was the bug preventing the filter from working.

Changes:
- Filter DeviceProfile in POST request body before sending to Jellyfin
- Add extensive debug logging to track filtering process
- Remove unnecessary response filtering (DeviceProfile not in response)
- Simplify response handling (always stream)

Now logs:
- 'Xbox PlaybackInfo request detected' when Xbox client detected
- 'Filtering Xbox DeviceProfile in REQUEST' when filtering
- 'No DeviceProfile found' if profile missing (debug info)
This commit is contained in:
mani
2026-01-09 00:15:08 +01:00
parent 485b809a63
commit c9ffefed70

View File

@@ -73,43 +73,41 @@ def proxy(path):
headers['X-Forwarded-Host'] = request.host
headers['X-Real-IP'] = request.remote_addr
# Get request body
request_data = request.get_data()
# Filter REQUEST body for Xbox PlaybackInfo (DeviceProfile is sent TO server)
if is_xbox and is_playback_info:
logger.info(f"Xbox PlaybackInfo request detected: {path}, User-Agent: {user_agent}")
if request_data:
try:
data = json.loads(request_data)
if "DeviceProfile" in data:
logger.info(f"Filtering Xbox DeviceProfile in REQUEST")
original_profile = data["DeviceProfile"]
filtered_profile = filter_codecs(data["DeviceProfile"])
data["DeviceProfile"] = filtered_profile
request_data = json.dumps(data).encode('utf-8')
headers['Content-Length'] = str(len(request_data))
logger.info("DeviceProfile filtered successfully in REQUEST")
else:
logger.warning("No DeviceProfile found in REQUEST body")
except Exception as e:
logger.error(f"Error filtering request: {e}", exc_info=True)
else:
logger.warning("No request body found for PlaybackInfo")
resp = requests.request(
method=request.method,
url=url,
headers=headers,
data=request.get_data(),
data=request_data,
cookies=request.cookies,
allow_redirects=False,
stream=True # Support large file streaming
)
# Filter response for Xbox PlaybackInfo requests
if is_xbox and is_playback_info and resp.status_code == 200:
try:
# Read full response for JSON manipulation
data = resp.json()
# Filter DeviceProfile in request body (if sent back)
if "DeviceProfile" in data:
logger.info(f"Filtering Xbox DeviceProfile for User-Agent: {user_agent}")
data["DeviceProfile"] = filter_codecs(data["DeviceProfile"])
# Filter MediaSources DirectPlayProfiles (generated server-side)
if "MediaSources" in data:
for source in data["MediaSources"]:
if "TranscodingUrl" in source:
# Already filtered by Jellyfin
pass
response_data = json.dumps(data)
response = Response(response_data, status=resp.status_code)
response.headers['Content-Type'] = 'application/json'
except Exception as e:
logger.error(f"Error filtering response: {e}")
# Fallback to streaming response
response = Response(resp.iter_content(chunk_size=8192), status=resp.status_code)
else:
# Stream response for large files (videos, etc.)
# Stream all responses (no need to filter response, DeviceProfile only in request)
response = Response(resp.iter_content(chunk_size=8192), status=resp.status_code)
# Copy headers from Jellyfin response