diff --git a/modules/workflow_serial.py b/modules/workflow_serial.py index 6143e4c..59bacd1 100644 --- a/modules/workflow_serial.py +++ b/modules/workflow_serial.py @@ -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)) # ── 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 if "HTTP_CODE:" in raw: try: @@ -168,21 +170,43 @@ def _serial_redfish_request(ser: SerialPort, password: str, method: str, except ValueError: 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 = {} - json_start = raw.find("{") - json_end = raw.rfind("}") + 1 - if json_start >= 0 and json_end > json_start: - try: - data = json.loads(raw[json_start:json_end]) - except json.JSONDecodeError: - pass + json_end = search_area.rfind("}") + 1 + if json_end > 0: + json_start = -1 + for nl in ("\r\n", "\n"): + pos = search_area.rfind(nl + "{") + if pos >= 0: + 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 ────────────────────────────────────────────────────── if http_code >= 400: msg = (data.get("error", {}).get("message", "") 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: return True, data