Fix JSON parsing in _serial_redfish_request when terminal wraps long curl commands
The serial terminal echoes the curl command back before executing it.
The -w format string contains '%{http_code}' which includes a literal '{'.
When the terminal wraps long command lines (IOM2's path is ~70 chars),
that '{' can land at a line boundary, causing find("{") to pick up the
wrong position and produce garbled JSON/error output.
Fix: narrow the JSON search to the text before the HTTP_CODE: marker,
then use rfind("\n{") to find the last newline-prefixed '{'. The actual
curl response always starts on its own line, while the echoed '{http_code}'
is embedded mid-line in the command echo — so rfind("\n{") reliably skips it.
Also tighten the error snippet to use the same search_area bounds so the
displayed error shows actual response content rather than command echo text.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -161,6 +161,8 @@ def _serial_redfish_request(ser: SerialPort, password: str, method: str,
|
|||||||
raw = _ANSI_RE.sub("", ser.read_until_quiet(quiet_period=1.5, timeout=30.0))
|
raw = _ANSI_RE.sub("", ser.read_until_quiet(quiet_period=1.5, timeout=30.0))
|
||||||
|
|
||||||
# ── Parse HTTP status code ─────────────────────────────────────────────────
|
# ── Parse HTTP status code ─────────────────────────────────────────────────
|
||||||
|
# Use the LAST occurrence of HTTP_CODE: so the echoed curl -w argument
|
||||||
|
# (which also contains the literal text "HTTP_CODE:") doesn't interfere.
|
||||||
http_code = 0
|
http_code = 0
|
||||||
if "HTTP_CODE:" in raw:
|
if "HTTP_CODE:" in raw:
|
||||||
try:
|
try:
|
||||||
@@ -168,21 +170,43 @@ def _serial_redfish_request(ser: SerialPort, password: str, method: str,
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# ── Extract JSON body (outermost { ... }) ──────────────────────────────────
|
# ── Extract JSON body ──────────────────────────────────────────────────────
|
||||||
|
# The terminal echoes the curl command before executing it, and the
|
||||||
|
# -w format string contains '%{http_code}' which includes a literal '{'.
|
||||||
|
# When the terminal wraps long command lines, that '{' can land at a
|
||||||
|
# line boundary, causing find("{") to return the wrong position.
|
||||||
|
#
|
||||||
|
# Strategy: narrow the search to the text before HTTP_CODE: (the actual
|
||||||
|
# curl response body appears there), then find the LAST newline-prefixed
|
||||||
|
# '{' — because the JSON response always starts on its own line, while
|
||||||
|
# the echoed '{http_code}' is embedded mid-line in the curl command echo.
|
||||||
|
http_code_pos = raw.find("HTTP_CODE:")
|
||||||
|
search_area = raw[:http_code_pos].rstrip() if http_code_pos >= 0 else raw
|
||||||
|
|
||||||
data: dict = {}
|
data: dict = {}
|
||||||
json_start = raw.find("{")
|
json_end = search_area.rfind("}") + 1
|
||||||
json_end = raw.rfind("}") + 1
|
if json_end > 0:
|
||||||
if json_start >= 0 and json_end > json_start:
|
json_start = -1
|
||||||
try:
|
for nl in ("\r\n", "\n"):
|
||||||
data = json.loads(raw[json_start:json_end])
|
pos = search_area.rfind(nl + "{")
|
||||||
except json.JSONDecodeError:
|
if pos >= 0:
|
||||||
pass
|
json_start = pos + len(nl)
|
||||||
|
break
|
||||||
|
if json_start < 0:
|
||||||
|
json_start = search_area.find("{") # fallback if no newline found
|
||||||
|
|
||||||
|
if json_start >= 0:
|
||||||
|
try:
|
||||||
|
data = json.loads(search_area[json_start:json_end])
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
pass
|
||||||
|
|
||||||
# ── Determine success ──────────────────────────────────────────────────────
|
# ── Determine success ──────────────────────────────────────────────────────
|
||||||
if http_code >= 400:
|
if http_code >= 400:
|
||||||
msg = (data.get("error", {}).get("message", "")
|
msg = (data.get("error", {}).get("message", "")
|
||||||
if isinstance(data, dict) else "")
|
if isinstance(data, dict) else "")
|
||||||
return False, f"HTTP {http_code}: {msg or raw[json_start:json_start+120]}"
|
snippet = search_area[json_start:json_start + 120] if json_start >= 0 else search_area[-120:]
|
||||||
|
return False, f"HTTP {http_code}: {msg or snippet}"
|
||||||
|
|
||||||
if http_code >= 200 or data:
|
if http_code >= 200 or data:
|
||||||
return True, data
|
return True, data
|
||||||
|
|||||||
Reference in New Issue
Block a user