Files
gods-eye-view/server/providers/regional/http.js
Bilawal Sidhuandsendmebits 7fa0cfbb26 feat(search): Nominatim as the last-resort geocoder (#573)
Supersedes #350 by @sendmebits, ported onto the current component layout with fixes from review.

Verified before merge: format, package boundaries, unit suite, build, and the browser tracking suite; a browser harness for the change where one applies; adversarial review applied.

Co-authored-by: sendmebits <[email protected]>
2026-09-14 21:22:08 -05:00

57 lines
1.9 KiB
JavaScript

import {
readResponseJsonCapped,
readResponseTextCapped,
} from '../common/http.js';
const REGIONAL_MAX_RESPONSE_BYTES = 2 * 1024 * 1024;
/**
* One bounded upstream read for the regional providers.
*
* The deadline covers the BODY, not just the headers. `return`ing the reader's
* promise from inside a try/finally leaves the try block the moment the promise
* exists, so the abort timer used to be cleared before a single byte of body had
* arrived — an upstream that answered its headers and then stalled had no
* deadline at all. Awaiting inside the try keeps the timer alive until the body
* is in hand, and the same signal is handed to the reader so an abort stops the
* read rather than just the connect.
*
* `redirect` is stated rather than inherited: feeds that legitimately redirect
* (news RSS) follow, and a fixed API endpoint can be given 'error' so a
* redirect cannot steer the proxy at a destination this code never named.
*
* @param {string} url
* @param {{headers?: object, timeoutMs?: number, maxBytes?: number, redirect?: 'follow'|'error'|'manual'}} [options]
*/
async function fetchRegional(url, read, options = {}) {
const {
headers = {},
timeoutMs = 9000,
maxBytes = REGIONAL_MAX_RESPONSE_BYTES,
redirect = 'follow',
} = options;
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), timeoutMs);
try {
const response = await fetch(url, {
signal: controller.signal,
headers,
redirect,
});
if (!response.ok) throw new Error(`Upstream returned ${response.status}`);
return await read(response, maxBytes, controller.signal);
} finally {
clearTimeout(timeout);
}
}
function fetchRegionalJson(url, options = {}) {
return fetchRegional(url, readResponseJsonCapped, options);
}
function fetchRegionalText(url, options = {}) {
return fetchRegional(url, readResponseTextCapped, options);
}
export { fetchRegionalJson, fetchRegionalText };