diff options
Diffstat (limited to 'cli/js/web')
-rw-r--r-- | cli/js/web/fetch.ts | 42 | ||||
-rw-r--r-- | cli/js/web/form_data.ts | 12 |
2 files changed, 50 insertions, 4 deletions
diff --git a/cli/js/web/fetch.ts b/cli/js/web/fetch.ts index acf0bad0f..7ab68d2e4 100644 --- a/cli/js/web/fetch.ts +++ b/cli/js/web/fetch.ts @@ -13,6 +13,7 @@ import { FormData } from "./form_data.ts"; import { URL } from "./url.ts"; import { URLSearchParams } from "./url_search_params.ts"; import { fetch as opFetch, FetchResponse } from "../ops/fetch.ts"; +import { DomFileImpl } from "./dom_file.ts"; function getHeaderValueParams(value: string): Map<string, string> { const params = new Map(); @@ -499,8 +500,47 @@ export async function fetch( } else if (init.body instanceof DenoBlob) { body = init.body[blobBytesSymbol]; contentType = init.body.type; + } else if (init.body instanceof FormData) { + let boundary = ""; + if (headers.has("content-type")) { + const params = getHeaderValueParams("content-type"); + if (params.has("boundary")) { + boundary = params.get("boundary")!; + } + } + if (!boundary) { + boundary = + "----------" + + Array.from(Array(32)) + .map(() => Math.random().toString(36)[2] || 0) + .join(""); + } + + let payload = ""; + for (const [fieldName, fieldValue] of init.body.entries()) { + let part = `\r\n--${boundary}\r\n`; + part += `Content-Disposition: form-data; name=\"${fieldName}\"`; + if (fieldValue instanceof DomFileImpl) { + part += `; filename=\"${fieldValue.name}\"`; + } + part += "\r\n"; + if (fieldValue instanceof DomFileImpl) { + part += `Content-Type: ${fieldValue.type || + "application/octet-stream"}\r\n`; + } + part += "\r\n"; + if (fieldValue instanceof DomFileImpl) { + part += new TextDecoder().decode(fieldValue[blobBytesSymbol]); + } else { + part += fieldValue; + } + payload += part; + } + payload += `\r\n--${boundary}--`; + body = new TextEncoder().encode(payload); + contentType = "multipart/form-data; boundary=" + boundary; } else { - // TODO: FormData, ReadableStream + // TODO: ReadableStream notImplemented(); } if (contentType && !headers.has("content-type")) { diff --git a/cli/js/web/form_data.ts b/cli/js/web/form_data.ts index 2c70d416f..f60a146d9 100644 --- a/cli/js/web/form_data.ts +++ b/cli/js/web/form_data.ts @@ -16,7 +16,9 @@ class FormDataBase { requiredArguments("FormData.append", arguments.length, 2); name = String(name); if (value instanceof blob.DenoBlob) { - const dfile = new domFile.DomFileImpl([value], filename || name); + const dfile = new domFile.DomFileImpl([value], filename || name, { + type: value.type + }); this[dataSymbol].push([name, dfile]); } else { this[dataSymbol].push([name, String(value)]); @@ -81,7 +83,9 @@ class FormDataBase { if (this[dataSymbol][i][0] === name) { if (!found) { if (value instanceof blob.DenoBlob) { - const dfile = new domFile.DomFileImpl([value], filename || name); + const dfile = new domFile.DomFileImpl([value], filename || name, { + type: value.type + }); this[dataSymbol][i][1] = dfile; } else { this[dataSymbol][i][1] = String(value); @@ -98,7 +102,9 @@ class FormDataBase { // Otherwise, append entry to the context object’s entry list. if (!found) { if (value instanceof blob.DenoBlob) { - const dfile = new domFile.DomFileImpl([value], filename || name); + const dfile = new domFile.DomFileImpl([value], filename || name, { + type: value.type + }); this[dataSymbol].push([name, dfile]); } else { this[dataSymbol].push([name, String(value)]); |