fix(cli/fetch): set null body for null-body status (#5980)

This commit is contained in:
Marcos Casagrande 2020-06-01 01:21:14 +02:00 committed by GitHub
parent 08552fc6b9
commit edeeedf401
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 76 additions and 26 deletions

View file

@ -12,6 +12,9 @@ import { DomFileImpl } from "./dom_file.ts";
import { getHeaderValueParams } from "./util.ts"; import { getHeaderValueParams } from "./util.ts";
import { ReadableStreamImpl } from "./streams/readable_stream.ts"; import { ReadableStreamImpl } from "./streams/readable_stream.ts";
const NULL_BODY_STATUS = [/* 101, */ 204, 205, 304];
const REDIRECT_STATUS = [301, 302, 303, 307, 308];
const responseData = new WeakMap(); const responseData = new WeakMap();
export class Response extends Body.Body implements domTypes.Response { export class Response extends Body.Body implements domTypes.Response {
readonly type: ResponseType; readonly type: ResponseType;
@ -45,7 +48,7 @@ export class Response extends Body.Body implements domTypes.Response {
} }
// null body status // null body status
if (body && [/* 101, */ 204, 205, 304].includes(status)) { if (body && NULL_BODY_STATUS.includes(status)) {
throw new TypeError("Response with null body status cannot have body"); throw new TypeError("Response with null body status cannot have body");
} }
@ -288,11 +291,21 @@ export async function fetch(
} }
} }
let responseBody;
let responseInit: ResponseInit = {}; let responseInit: ResponseInit = {};
while (remRedirectCount) { while (remRedirectCount) {
const fetchResponse = await sendFetchReq(url, method, headers, body); const fetchResponse = await sendFetchReq(url, method, headers, body);
const responseBody = new ReadableStreamImpl({ if (
NULL_BODY_STATUS.includes(fetchResponse.status) ||
REDIRECT_STATUS.includes(fetchResponse.status)
) {
// We won't use body of received response, so close it now
// otherwise it will be kept in resource table.
close(fetchResponse.bodyRid);
responseBody = null;
} else {
responseBody = new ReadableStreamImpl({
async pull(controller: ReadableStreamDefaultController): Promise<void> { async pull(controller: ReadableStreamDefaultController): Promise<void> {
try { try {
const b = new Uint8Array(1024 * 32); const b = new Uint8Array(1024 * 32);
@ -314,6 +327,7 @@ export async function fetch(
close(fetchResponse.bodyRid); close(fetchResponse.bodyRid);
}, },
}); });
}
responseInit = { responseInit = {
status: fetchResponse.status, status: fetchResponse.status,
@ -329,10 +343,7 @@ export async function fetch(
const response = new Response(responseBody, responseInit); const response = new Response(responseBody, responseInit);
if ([301, 302, 303, 307, 308].includes(fetchResponse.status)) { if (REDIRECT_STATUS.includes(fetchResponse.status)) {
// We won't use body of received response, so close it now
// otherwise it will be kept in resource table.
close(fetchResponse.bodyRid);
// We're in a redirect status // We're in a redirect status
switch ((init && init.redirect) || "follow") { switch ((init && init.redirect) || "follow") {
case "error": case "error":

View file

@ -713,3 +713,41 @@ unitTest(
await res.body.cancel(); await res.body.cancel();
} }
); );
unitTest(
{ perms: { net: true } },
async function fetchNullBodyStatus(): Promise<void> {
const nullBodyStatus = [204, 205, 304];
for (const status of nullBodyStatus) {
const headers = new Headers([["x-status", String(status)]]);
const res = await fetch("http://localhost:4545/cli/tests/echo_server", {
body: "deno",
method: "POST",
headers,
});
assertEquals(res.body, null);
assertEquals(res.status, status);
}
}
);
unitTest(
{ perms: { net: true } },
function fetchResponseConstructorNullBody(): void {
const nullBodyStatus = [204, 205, 304];
for (const status of nullBodyStatus) {
try {
new Response("deno", { status });
fail("Response with null body status cannot have body");
} catch (e) {
assert(e instanceof TypeError);
assertEquals(
e.message,
"Response with null body status cannot have body"
);
}
}
}
);

View file

@ -194,8 +194,9 @@ class ContentTypeHandler(QuietSimpleHTTPRequestHandler):
def do_POST(self): def do_POST(self):
# Simple echo server for request reflection # Simple echo server for request reflection
if "echo_server" in self.path: if "echo_server" in self.path:
status = int(self.headers.getheader('x-status', "200"))
self.protocol_version = 'HTTP/1.1' self.protocol_version = 'HTTP/1.1'
self.send_response(200, 'OK') self.send_response(status, 'OK')
if self.headers.has_key('content-type'): if self.headers.has_key('content-type'):
self.send_header('content-type', self.send_header('content-type',
self.headers.getheader('content-type')) self.headers.getheader('content-type'))