diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c74873..1879a0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ All notable changes to this project will be documented in this file. +## [Unreleased] + +### Fixed +- Improved REST response parsing for mobile platforms by handling `Content-Type` headers case-insensitively and falling back to JSON body parsing when the payload is JSON-like. This fixes `path` lookups such as `path: 0` failing on Android and iPad for endpoints that return JSON arrays. + ## [1.2.0] - 2026-05-02 ### Added diff --git a/src/queryEngine.ts b/src/queryEngine.ts index e23dada..4ee6413 100644 --- a/src/queryEngine.ts +++ b/src/queryEngine.ts @@ -23,6 +23,32 @@ export interface QueryResult { error?: string; } +function findHeaderValue(headers: Record, targetName: string): string | undefined { + const normalizedTarget = targetName.toLowerCase(); + + for (const [name, value] of Object.entries(headers || {})) { + if (name.toLowerCase() === normalizedTarget) { + return value; + } + } + + return undefined; +} + +function tryParseJsonText(text: string): any | undefined { + const trimmed = text.trim(); + + if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) { + return undefined; + } + + try { + return JSON.parse(trimmed); + } catch { + return undefined; + } +} + function formatRequestError(error: unknown): string { const message = error instanceof Error ? error.message : String(error); const normalized = message.toLowerCase(); @@ -291,14 +317,17 @@ async function executeRestQuery(params: QueryParams): Promise { const response = await requestUrl(requestParams); - // Parse response based on content type - const contentType = response.headers['content-type']; - - if (contentType && contentType.includes('application/json')) { + // Mobile builds may expose response headers with different casing, so + // treat Content-Type lookup as case-insensitive and fall back to parsing + // the body when JSON-looking payloads arrive without a usable header. + const contentType = findHeaderValue(response.headers || {}, 'content-type'); + + if (contentType && contentType.toLowerCase().includes('application/json')) { return response.json; - } else { - return response.text; } + + const parsedText = tryParseJsonText(response.text); + return parsedText !== undefined ? parsedText : response.text; } /**