/**
 * Lê o corpo de um pedido aos pedaços e para no limite. `null` = passou do limite.
 *
 * Ler tudo para medir depois deixaria qualquer um, sem chave nenhuma, fazer o
 * servidor guardar na memória um pedido de vários megas antes de recusá-lo.
 */
export async function lerCorpoComLimite(request: Request, maximo: number): Promise<string | null> {
  /* O tamanho declarado é conferido antes de ler; o que não declara (ou
     declara menos do que manda) é barrado durante a leitura. */
  if (Number(request.headers.get("content-length") || 0) > maximo) return null;
  if (!request.body) return "";
  const leitor = request.body.getReader();
  const pedacos: Uint8Array[] = [];
  let lidos = 0;
  for (;;) {
    const { done, value } = await leitor.read();
    if (done) break;
    lidos += value.byteLength;
    if (lidos > maximo) {
      await leitor.cancel().catch(() => undefined);
      return null;
    }
    pedacos.push(value);
  }
  return Buffer.concat(pedacos).toString("utf8");
}
