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 { 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();
export class Response extends Body.Body implements domTypes.Response {
readonly type: ResponseType;
@ -45,7 +48,7 @@ export class Response extends Body.Body implements domTypes.Response {
}
// 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");
}
@ -288,11 +291,21 @@ export async function fetch(
}
}
let responseBody;
let responseInit: ResponseInit = {};
while (remRedirectCount) {
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> {
try {
const b = new Uint8Array(1024 * 32);
@ -314,6 +327,7 @@ export async function fetch(
close(fetchResponse.bodyRid);
},
});
}
responseInit = {
status: fetchResponse.status,
@ -329,10 +343,7 @@ export async function fetch(
const response = new Response(responseBody, responseInit);
if ([301, 302, 303, 307, 308].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);
if (REDIRECT_STATUS.includes(fetchResponse.status)) {
// We're in a redirect status
switch ((init && init.redirect) || "follow") {
case "error":

View file

@ -713,3 +713,41 @@ unitTest(
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):
# Simple echo server for request reflection
if "echo_server" in self.path:
status = int(self.headers.getheader('x-status', "200"))
self.protocol_version = 'HTTP/1.1'
self.send_response(200, 'OK')
self.send_response(status, 'OK')
if self.headers.has_key('content-type'):
self.send_header('content-type',
self.headers.getheader('content-type'))