Deno: Request Body can be cumbersome

Created on 22 May 2020  路  6Comments  路  Source: denoland/deno

Could I suggest a convenience method for reading all the data out of a request body? If the request is a chunky request or does not contain content-length you have to write this code which seems to be better a utility. Here is an example.

import {
    serve
} from "https://deno.land/std/http/server.ts";

import { getEnv } from "./env.ts";
import { config } from "https://deno.land/x/dotenv/mod.ts";

const c = config({
    export: true
});

const s = serve({
    port: 8002
});

for await (const req of s) {
    const body = await readRequestBody(req);
    ...
}
const scratchBuffer = new Uint8Array(16 * 1024);
export async function readRequestBody(req: ServerRequest) {
    const contentLength = req.headers.get("Content-length");
    let bufLength = 0;
    if (contentLength) {
        if (!isNaN(+contentLength)) {
            bufLength = +contentLength;
        }
    }

    let ptr = 0;
    let readAmount: number | null = 0;
    let outData: Uint8Array = new Uint8Array(bufLength);

    do {
        readAmount = await req.body.read(scratchBuffer);
        if (readAmount) {
            if (readAmount + ptr > outData.length) {
                const nextOutData = new Uint8Array(readAmount + ptr);
                nextOutData.set(outData.subarray(0, ptr), 0);
                outData = nextOutData;
            }

            outData.set(scratchBuffer.subarray(0, readAmount), ptr);
            ptr += readAmount;
        }
    } while(readAmount);

    return outData;
}

Am I missing some util, or is this the prescribed way? Could we make a util if the latter is correct?

Most helpful comment

await Deno.readAll(req.body)

All 6 comments

await Deno.readAll(req.body)

FeelsGoodMan

This issue should be closed. But I'd just like to point out two things:

  1. This is not documented anywhere (at least so far as Google can find)
  2. This is inconsistent with pretty much every other HTTP framework I know of. In most systems, req.body is pretty consistent behavior.
    Now I know it being inconsistent does not mean it's bad. Every service does things a bit differently, and Deno has opinionated designs (which make it great in the first place), so sometimes you just gotta learn the 馃 way of doing it. But I think generally it is more intuitive to have req.body be the whole body, and have another member to get it as a reader.

At the very least, instead of not giving you the code, the docs for req.body should mention the Deno.readAll method.

It is a fair point that the docs don't make that clear. I believe mostly because Deno.readAll came after the implementation and no one bothered to update the JSDocs, but @cknight has raised #5771 to update that.

std/http isn't a framework, it is still fairly low level implementation of HTTP 1.1 on top of Deno's IO interfaces. Be it HTTP, raw sockets, files, stdin/stdout, etc. they all work of of the Deno.Reader and Deno.Writer interfaces. If you want a framework, there are several to choose from. oak for example has the sort of behaviour you might expect from other HTTP server frameworks for body: https://github.com/oakserver/oak#request

That makes sense. Thank you 馃檪

@vegerot 馃 is a better emoji for Deno.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ry picture ry  路  3Comments

CruxCv picture CruxCv  路  3Comments

watilde picture watilde  路  3Comments

benjamingr picture benjamingr  路  3Comments

zugende picture zugende  路  3Comments