Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions body.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -467,3 +467,19 @@ Deno.test({
assert(timingSafeEqual(actual, expected));
},
});

Deno.test({
name: "body - empty",
async fn() {
const body = new Body(nativeToServer(
new Request(
"http://localhost/index.html",
{
method: "GET",
},
),
));
assert(!body.has);
assertEquals(await body.init(), null);
},
});
8 changes: 8 additions & 0 deletions body.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,14 @@ export class Body {
return this.#request?.bodyUsed ?? !!this.#used;
}

/** Return the body to be reused as BodyInit. */
async init(): Promise<BodyInit | null> {
if (!this.has) {
return null;
}
return await this.#memo ?? this.stream;
}

/** Reads a body to the end and resolves with the value as an
* {@linkcode ArrayBuffer} */
async arrayBuffer(): Promise<ArrayBuffer> {
Expand Down
25 changes: 25 additions & 0 deletions middleware/proxy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,3 +266,28 @@ Deno.test({
await mw(ctx, next);
},
});

Deno.test({
name: "proxy - consumed body",
async fn() {
async function fetch(request: Request): Promise<Response> {
const body = await request.text();
assertEquals(body, "hello world");
return new Response(body);
}

const mw = proxy("https://oakserver.github.io/", { fetch });
const stream = ReadableStream.from([
new TextEncoder().encode("hello world"),
]);
const ctx = createMockContext({
method: "POST",
path: "/oak/FAQ",
body: stream,
});
const next = createMockNext();

assertEquals(await ctx.request.body.text(), "hello world");
await mw(ctx, next);
},
});
15 changes: 1 addition & 14 deletions middleware/proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ async function createRequest<
}
url.search = ctx.request.url.search;

const body = getBodyInit(ctx);
const body = await ctx.request.body?.init() ?? null;
const headers = new Headers(ctx.request.headers);
if (optHeaders) {
if (typeof optHeaders === "function") {
Expand Down Expand Up @@ -195,19 +195,6 @@ async function createRequest<
return request;
}

function getBodyInit<
R extends string,
P extends RouteParams<R>,
S extends State,
>(
ctx: Context<S> | RouterContext<R, P, S>,
): BodyInit | null {
if (!ctx.request.hasBody) {
return null;
}
return ctx.request.body.stream;
}

function iterableHeaders(
headers: HeadersInit,
): IterableIterator<[string, string]> {
Expand Down
5 changes: 5 additions & 0 deletions testing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
type ErrorStatus,
SecureCookieMap,
} from "./deps.ts";
import { Body } from "./body.ts";
import type { RouteParams, RouterContext } from "./router.ts";
import type { Request } from "./request.ts";
import { Response } from "./response.ts";
Expand Down Expand Up @@ -67,6 +68,7 @@ export interface MockContextOptions<
path?: string;
state?: S;
headers?: [string, string][];
body?: ReadableStream;
}

/** Allows external parties to modify the context state. */
Expand All @@ -90,6 +92,7 @@ export function createMockContext<
state,
app = createMockApp(state),
headers: requestHeaders,
body = undefined,
}: MockContextOptions<R> = {},
): RouterContext<R, P, S> {
function createMockRequest(): Request {
Expand Down Expand Up @@ -120,6 +123,8 @@ export function createMockContext<
search: undefined,
searchParams: new URLSearchParams(),
url: new URL(path, "http://localhost/"),
hasBody: !!body,
body: body ? new Body({ headers, getBody: () => body }) : undefined,
} as any;
}

Expand Down