From a86721752a77529b4ebe631311bd4f31c64a5e48 Mon Sep 17 00:00:00 2001 From: ClaudiaFang Date: Mon, 13 Jul 2026 13:46:38 +0000 Subject: [PATCH] fix: surface a clear error when requestUrl() itself rejects with HTML content MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit parseJson() already handles the case where a response resolves normally but its .json getter throws on an HTML body (e.g. a login/SSO redirect or proxy error page). But some Obsidian versions eagerly parse the response body as JSON inside requestUrl() itself, so the same failure can instead reject the whole call with a raw SyntaxError — landing in safeRequest's outer catch, before there's even a response object to inspect. That catch just rethrew the error verbatim, surfacing the literal "Unexpected token '<', \"): void; + /** + * Detects V8's JSON.parse error for a response starting with '<' (an HTML + * page), across its known message phrasings, e.g.: + * "Unexpected token '<', " { }); }); + describe('safeRequest when requestUrl() itself throws a JSON-parse-of-HTML error', () => { + // Some Obsidian versions eagerly parse the response body as JSON inside + // requestUrl() itself, so a proxy/login HTML page can make the whole + // call reject with a raw SyntaxError — before `throw: false` or our own + // status/content-type checks ever get a response object to inspect. + it('wraps the raw "Unexpected token \'<\'... is not valid JSON" rejection with a clear message', async () => { + vi.mocked(requestUrl).mockRejectedValue( + new SyntaxError('Unexpected token \'<\', " { + vi.mocked(requestUrl).mockRejectedValue(new SyntaxError('Unexpected token < in JSON at position 0')); + await expect(service.listFiles('main')).rejects.toThrow(/received an HTML page/); + }); + + it('does not misclassify an unrelated JSON syntax error as an HTML response', async () => { + vi.mocked(requestUrl).mockRejectedValue(new SyntaxError('Unexpected end of JSON input')); + await expect(service.listFiles('main')).rejects.toThrow('Unexpected end of JSON input'); + }); + }); + describe('parseJson with non-JSON (HTML) responses', () => { // Simulates Obsidian's real RequestUrlResponse.json getter, which throws // SyntaxError when the body is not valid JSON (e.g. an HTML page).