opencode/packages/core/src/tool/http-body.ts
2026-06-21 15:37:25 -04:00

30 lines
1.3 KiB
TypeScript

import { Effect, Stream } from "effect"
import { HttpClientResponse } from "effect/unstable/http"
export const collectBoundedResponseBody = (
response: HttpClientResponse.HttpClientResponse,
maximumBytes: number,
tooLarge: () => Error,
) =>
Effect.gen(function* () {
const contentLength = response.headers["content-length"]
const parsedSize = contentLength ? Number.parseInt(contentLength, 10) : undefined
const declaredSize =
parsedSize !== undefined && Number.isSafeInteger(parsedSize) && parsedSize >= 0 ? parsedSize : undefined
if (declaredSize !== undefined && declaredSize > maximumBytes) return yield* Effect.fail(tooLarge())
let body = Buffer.allocUnsafe(Math.min(maximumBytes, declaredSize || 64 * 1024))
let size = 0
yield* Stream.runForEach(response.stream, (chunk) => {
if (chunk.byteLength === 0) return Effect.void
if (size + chunk.byteLength > maximumBytes) return Effect.fail(tooLarge())
if (size + chunk.byteLength > body.byteLength) {
const grown = Buffer.allocUnsafe(Math.min(maximumBytes, Math.max(size + chunk.byteLength, body.byteLength * 2)))
body.copy(grown, 0, 0, size)
body = grown
}
body.set(chunk, size)
size += chunk.byteLength
return Effect.void
})
return body.subarray(0, size)
})