From cd67f7bdc8fbf1caef758113bab97cc6396321dc Mon Sep 17 00:00:00 2001 From: Kurt Mackey Date: Thu, 20 Aug 2020 11:47:58 -0400 Subject: [PATCH] fix: Create body stream from any valid bodySource (#7128) Fixes #6752 --- cli/rt/24_body.js | 69 ++++++++++++++++++++++--------------- cli/tests/unit/body_test.ts | 10 +++++- 2 files changed, 50 insertions(+), 29 deletions(-) diff --git a/cli/rt/24_body.js b/cli/rt/24_body.js index ebd0ddc6df..a3348907b9 100644 --- a/cli/rt/24_body.js +++ b/cli/rt/24_body.js @@ -66,6 +66,32 @@ return buffer.bytes().buffer; } + function bodyToArrayBuffer(bodySource) { + if (isTypedArray(bodySource)) { + return bodySource.buffer; + } else if (bodySource instanceof ArrayBuffer) { + return bodySource; + } else if (typeof bodySource === "string") { + const enc = new TextEncoder(); + return enc.encode(bodySource).buffer; + } else if (bodySource instanceof ReadableStream) { + throw new Error( + `Can't convert stream to ArrayBuffer (try bufferFromStream)`, + ); + } else if ( + bodySource instanceof FormData || + bodySource instanceof URLSearchParams + ) { + const enc = new TextEncoder(); + return enc.encode(bodySource.toString()).buffer; + } else if (!bodySource) { + return null; + } + throw new Error( + `Body type not implemented: ${bodySource.constructor.name}`, + ); + } + const BodyUsedError = "Failed to execute 'clone' on 'Body': body is already used"; @@ -86,18 +112,26 @@ return this._stream; } - if (this._bodySource instanceof ReadableStream) { + if (!this._bodySource) { + return null; + } else if (this._bodySource instanceof ReadableStream) { this._stream = this._bodySource; - } - if (typeof this._bodySource === "string") { - const bodySource = this._bodySource; + } else { + const buf = bodyToArrayBuffer(this._bodySource); + if (!(buf instanceof ArrayBuffer)) { + throw new Error( + `Expected ArrayBuffer from body`, + ); + } + this._stream = new ReadableStream({ start(controller) { - controller.enqueue(bodySource); + controller.enqueue(buf); controller.close(); }, }); } + return this._stream; } @@ -172,31 +206,10 @@ } arrayBuffer() { - if (isTypedArray(this._bodySource)) { - return Promise.resolve(this._bodySource.buffer); - } else if (this._bodySource instanceof ArrayBuffer) { - return Promise.resolve(this._bodySource); - } else if (typeof this._bodySource === "string") { - const enc = new TextEncoder(); - return Promise.resolve( - enc.encode(this._bodySource).buffer, - ); - } else if (this._bodySource instanceof ReadableStream) { + if (this._bodySource instanceof ReadableStream) { return bufferFromStream(this._bodySource.getReader(), this.#size); - } else if ( - this._bodySource instanceof FormData || - this._bodySource instanceof URLSearchParams - ) { - const enc = new TextEncoder(); - return Promise.resolve( - enc.encode(this._bodySource.toString()).buffer, - ); - } else if (!this._bodySource) { - return Promise.resolve(new ArrayBuffer(0)); } - throw new Error( - `Body type not yet implemented: ${this._bodySource.constructor.name}`, - ); + return bodyToArrayBuffer(this._bodySource); } } diff --git a/cli/tests/unit/body_test.ts b/cli/tests/unit/body_test.ts index b7393ad0d2..d9979e7035 100644 --- a/cli/tests/unit/body_test.ts +++ b/cli/tests/unit/body_test.ts @@ -1,5 +1,9 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -import { unitTest, assertEquals, assert } from "./test_util.ts"; +import { + unitTest, + assertEquals, + assert, +} from "./test_util.ts"; // just a hack to get a body object // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -39,6 +43,8 @@ unitTest( const response = await fetch( "http://localhost:4545/multipart_form_data.txt", ); + assert(response.body instanceof ReadableStream); + const text = await response.text(); const body = buildBody(text, response.headers); @@ -56,6 +62,8 @@ unitTest( const response = await fetch( "http://localhost:4545/cli/tests/subdir/form_urlencoded.txt", ); + assert(response.body instanceof ReadableStream); + const text = await response.text(); const body = buildBody(text, response.headers);