Expand ecash explorer capabilities
Add Fedimint discovery, dual SQLite/Postgres storage, richer review handling, and generated social imagery.
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Read a response body up to `maxBytes`, or refuse it.
|
||||
*
|
||||
* `res.arrayBuffer()` and `res.json()` buffer however much the server sends before any
|
||||
* size check can run, and a mint is an untrusted server: the abort timer bounds how
|
||||
* *long* a read may take, this bounds how *large* it may get, and both are needed. The
|
||||
* Content-Length header is checked first as a courtesy — a chunked or lying response
|
||||
* still hits the streaming cap.
|
||||
*
|
||||
* Returns null when the body is over the limit or unreadable. The caller treats that
|
||||
* exactly like a failed fetch.
|
||||
*/
|
||||
export async function readBodyBounded(res: Response, maxBytes: number): Promise<Buffer | null> {
|
||||
const declared = Number(res.headers.get('content-length') ?? '');
|
||||
if (Number.isFinite(declared) && declared > maxBytes) return null;
|
||||
|
||||
const reader = res.body?.getReader();
|
||||
if (!reader) return null;
|
||||
|
||||
const chunks: Uint8Array[] = [];
|
||||
let size = 0;
|
||||
try {
|
||||
for (;;) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) break;
|
||||
size += value.byteLength;
|
||||
if (size > maxBytes) {
|
||||
await reader.cancel().catch(() => undefined);
|
||||
return null;
|
||||
}
|
||||
chunks.push(value);
|
||||
}
|
||||
} catch {
|
||||
// Aborted by the caller's timer, or the connection died mid-body.
|
||||
return null;
|
||||
}
|
||||
|
||||
return Buffer.concat(chunks);
|
||||
}
|
||||
Reference in New Issue
Block a user