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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user