Skip to content

Commit 22298cb

Browse files
committed
fix: tolerate HTTP-error polls in device flow (Meta answers pending as 400)
1 parent 1e66d4d commit 22298cb

1 file changed

Lines changed: 34 additions & 2 deletions

File tree

‎muse_code_login.py‎

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,38 @@ def _post_form(url, params):
5757
raise LoginError(f"request to {url} failed: {exc}")
5858

5959

60+
def _post_form_lenient(url, params):
61+
"""POST form params; return (body, status) without raising on HTTP errors.
62+
63+
The token endpoint answers pending/slow_down polls with HTTP errors as
64+
part of the normal flow: callers classify instead of catching.
65+
"""
66+
try:
67+
request = urllib.request.Request(
68+
url,
69+
data=urllib.parse.urlencode(params).encode(),
70+
headers={
71+
"Accept": "application/json",
72+
"Content-Type": "application/x-www-form-urlencoded",
73+
"x-api-version": API_VERSION,
74+
},
75+
method="POST",
76+
)
77+
with urllib.request.urlopen(request, timeout=REQUEST_TIMEOUT_SECS) as response:
78+
status = response.status
79+
try:
80+
return json.load(response), status
81+
except Exception:
82+
return None, status
83+
except urllib.error.HTTPError as exc:
84+
try:
85+
return json.loads(exc.read().decode("utf-8", "replace")), exc.code
86+
except Exception:
87+
return None, exc.code
88+
except Exception as exc:
89+
raise LoginError(f"request to {url} failed: {exc}")
90+
91+
6092
def _post_json(url, payload, bearer):
6193
"""POST a JSON payload with bearer auth; return the decoded body."""
6294
try:
@@ -102,7 +134,7 @@ def poll_token(device_code, interval_seconds, expires_in_seconds):
102134
deadline = time.time() + float(expires_in_seconds or 600)
103135
slow_downs = 0
104136
while time.time() < deadline:
105-
body, _ = _post_form(
137+
body, _ = _post_form_lenient(
106138
TOKEN_URL,
107139
{
108140
"grant_type": "urn:ietf:params:oauth:grant-type:device_code",
@@ -111,7 +143,7 @@ def poll_token(device_code, interval_seconds, expires_in_seconds):
111143
},
112144
)
113145
if not isinstance(body, dict):
114-
raise LoginError("token endpoint returned an unexpected response")
146+
body = {"error": "unreadable token response"}
115147
error = body.get("error")
116148
if not error:
117149
access = body.get("access_token")

0 commit comments

Comments
 (0)