summaryrefslogtreecommitdiff
path: root/std/mime
diff options
context:
space:
mode:
authorCasper Beyer <caspervonb@pm.me>2021-02-02 19:05:46 +0800
committerGitHub <noreply@github.com>2021-02-02 12:05:46 +0100
commit6abf126c2a7a451cded8c6b5e6ddf1b69c84055d (patch)
treefd94c013a19fcb38954844085821ec1601c20e18 /std/mime
parenta2b5d44f1aa9d64f448a2a3cc2001272e2f60b98 (diff)
chore: remove std directory (#9361)
This removes the std folder from the tree. Various parts of the tests are pretty tightly dependent on std (47 direct imports and 75 indirect imports, not counting the cli tests that use them as fixtures) so I've added std as a submodule for now.
Diffstat (limited to 'std/mime')
-rw-r--r--std/mime/mod.ts2
-rw-r--r--std/mime/multipart.ts609
-rw-r--r--std/mime/multipart_test.ts293
-rw-r--r--std/mime/test.ts2
-rw-r--r--std/mime/testdata/sample.txt35
5 files changed, 0 insertions, 941 deletions
diff --git a/std/mime/mod.ts b/std/mime/mod.ts
deleted file mode 100644
index e8bd8d646..000000000
--- a/std/mime/mod.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-export * from "./multipart.ts";
diff --git a/std/mime/multipart.ts b/std/mime/multipart.ts
deleted file mode 100644
index b0d03bbc6..000000000
--- a/std/mime/multipart.ts
+++ /dev/null
@@ -1,609 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-import { equals, indexOf, lastIndexOf, startsWith } from "../bytes/mod.ts";
-import { copyN } from "../io/ioutil.ts";
-import { MultiReader } from "../io/readers.ts";
-import { extname } from "../path/mod.ts";
-import { BufReader, BufWriter } from "../io/bufio.ts";
-import { encoder } from "../encoding/utf8.ts";
-import { assert } from "../_util/assert.ts";
-import { TextProtoReader } from "../textproto/mod.ts";
-import { hasOwnProperty } from "../_util/has_own_property.ts";
-
-/** FormFile object */
-export interface FormFile {
- /** filename */
- filename: string;
- /** content-type header value of file */
- type: string;
- /** byte size of file */
- size: number;
- /** in-memory content of file. Either content or tempfile is set */
- content?: Uint8Array;
- /** temporal file path.
- * Set if file size is bigger than specified max-memory size at reading form
- * */
- tempfile?: string;
-}
-
-/** Type guard for FormFile */
-// deno-lint-ignore no-explicit-any
-export function isFormFile(x: any): x is FormFile {
- return hasOwnProperty(x, "filename") && hasOwnProperty(x, "type");
-}
-
-function randomBoundary(): string {
- let boundary = "--------------------------";
- for (let i = 0; i < 24; i++) {
- boundary += Math.floor(Math.random() * 16).toString(16);
- }
- return boundary;
-}
-
-/**
- * Checks whether `buf` should be considered to match the boundary.
- *
- * The prefix is "--boundary" or "\r\n--boundary" or "\n--boundary", and the
- * caller has verified already that `hasPrefix(buf, prefix)` is true.
- *
- * `matchAfterPrefix()` returns `1` if the buffer does match the boundary,
- * meaning the prefix is followed by a dash, space, tab, cr, nl, or EOF.
- *
- * It returns `-1` if the buffer definitely does NOT match the boundary,
- * meaning the prefix is followed by some other character.
- * For example, "--foobar" does not match "--foo".
- *
- * It returns `0` more input needs to be read to make the decision,
- * meaning that `buf.length` and `prefix.length` are the same.
- */
-export function matchAfterPrefix(
- buf: Uint8Array,
- prefix: Uint8Array,
- eof: boolean,
-): -1 | 0 | 1 {
- if (buf.length === prefix.length) {
- return eof ? 1 : 0;
- }
- const c = buf[prefix.length];
- if (
- c === " ".charCodeAt(0) ||
- c === "\t".charCodeAt(0) ||
- c === "\r".charCodeAt(0) ||
- c === "\n".charCodeAt(0) ||
- c === "-".charCodeAt(0)
- ) {
- return 1;
- }
- return -1;
-}
-
-/**
- * Scans `buf` to identify how much of it can be safely returned as part of the
- * `PartReader` body.
- *
- * @param buf - The buffer to search for boundaries.
- * @param dashBoundary - Is "--boundary".
- * @param newLineDashBoundary - Is "\r\n--boundary" or "\n--boundary", depending
- * on what mode we are in. The comments below (and the name) assume
- * "\n--boundary", but either is accepted.
- * @param total - The number of bytes read out so far. If total == 0, then a
- * leading "--boundary" is recognized.
- * @param eof - Whether `buf` contains the final bytes in the stream before EOF.
- * If `eof` is false, more bytes are expected to follow.
- * @returns The number of data bytes from buf that can be returned as part of
- * the `PartReader` body.
- */
-export function scanUntilBoundary(
- buf: Uint8Array,
- dashBoundary: Uint8Array,
- newLineDashBoundary: Uint8Array,
- total: number,
- eof: boolean,
-): number | null {
- if (total === 0) {
- // At beginning of body, allow dashBoundary.
- if (startsWith(buf, dashBoundary)) {
- switch (matchAfterPrefix(buf, dashBoundary, eof)) {
- case -1:
- return dashBoundary.length;
- case 0:
- return 0;
- case 1:
- return null;
- }
- }
- if (startsWith(dashBoundary, buf)) {
- return 0;
- }
- }
-
- // Search for "\n--boundary".
- const i = indexOf(buf, newLineDashBoundary);
- if (i >= 0) {
- switch (matchAfterPrefix(buf.slice(i), newLineDashBoundary, eof)) {
- case -1:
- return i + newLineDashBoundary.length;
- case 0:
- return i;
- case 1:
- return i > 0 ? i : null;
- }
- }
- if (startsWith(newLineDashBoundary, buf)) {
- return 0;
- }
-
- // Otherwise, anything up to the final \n is not part of the boundary and so
- // must be part of the body. Also, if the section from the final \n onward is
- // not a prefix of the boundary, it too must be part of the body.
- const j = lastIndexOf(buf, newLineDashBoundary.slice(0, 1));
- if (j >= 0 && startsWith(newLineDashBoundary, buf.slice(j))) {
- return j;
- }
-
- return buf.length;
-}
-
-class PartReader implements Deno.Reader, Deno.Closer {
- n: number | null = 0;
- total = 0;
-
- constructor(private mr: MultipartReader, public readonly headers: Headers) {}
-
- async read(p: Uint8Array): Promise<number | null> {
- const br = this.mr.bufReader;
-
- // Read into buffer until we identify some data to return,
- // or we find a reason to stop (boundary or EOF).
- let peekLength = 1;
- while (this.n === 0) {
- peekLength = Math.max(peekLength, br.buffered());
- const peekBuf = await br.peek(peekLength);
- if (peekBuf === null) {
- throw new Deno.errors.UnexpectedEof();
- }
- const eof = peekBuf.length < peekLength;
- this.n = scanUntilBoundary(
- peekBuf,
- this.mr.dashBoundary,
- this.mr.newLineDashBoundary,
- this.total,
- eof,
- );
- if (this.n === 0) {
- // Force buffered I/O to read more into buffer.
- assert(eof === false);
- peekLength++;
- }
- }
-
- if (this.n === null) {
- return null;
- }
-
- const nread = Math.min(p.length, this.n);
- const buf = p.subarray(0, nread);
- const r = await br.readFull(buf);
- assert(r === buf);
- this.n -= nread;
- this.total += nread;
- return nread;
- }
-
- close(): void {}
-
- private contentDisposition!: string;
- private contentDispositionParams!: { [key: string]: string };
-
- private getContentDispositionParams(): { [key: string]: string } {
- if (this.contentDispositionParams) return this.contentDispositionParams;
- const cd = this.headers.get("content-disposition");
- const params: { [key: string]: string } = {};
- assert(cd != null, "content-disposition must be set");
- const comps = decodeURI(cd).split(";");
- this.contentDisposition = comps[0];
- comps
- .slice(1)
- .map((v: string): string => v.trim())
- .map((kv: string): void => {
- const [k, v] = kv.split("=");
- if (v) {
- const s = v.charAt(0);
- const e = v.charAt(v.length - 1);
- if ((s === e && s === '"') || s === "'") {
- params[k] = v.substr(1, v.length - 2);
- } else {
- params[k] = v;
- }
- }
- });
- return (this.contentDispositionParams = params);
- }
-
- get fileName(): string {
- return this.getContentDispositionParams()["filename"];
- }
-
- get formName(): string {
- const p = this.getContentDispositionParams();
- if (this.contentDisposition === "form-data") {
- return p["name"];
- }
- return "";
- }
-}
-
-function skipLWSPChar(u: Uint8Array): Uint8Array {
- const ret = new Uint8Array(u.length);
- const sp = " ".charCodeAt(0);
- const ht = "\t".charCodeAt(0);
- let j = 0;
- for (let i = 0; i < u.length; i++) {
- if (u[i] === sp || u[i] === ht) continue;
- ret[j++] = u[i];
- }
- return ret.slice(0, j);
-}
-
-export interface MultipartFormData {
- file(key: string): FormFile | FormFile[] | undefined;
- value(key: string): string | undefined;
- entries(): IterableIterator<
- [string, string | FormFile | FormFile[] | undefined]
- >;
- [Symbol.iterator](): IterableIterator<
- [string, string | FormFile | FormFile[] | undefined]
- >;
- /** Remove all tempfiles */
- removeAll(): Promise<void>;
-}
-
-/** Reader for parsing multipart/form-data */
-export class MultipartReader {
- readonly newLine = encoder.encode("\r\n");
- readonly newLineDashBoundary = encoder.encode(`\r\n--${this.boundary}`);
- readonly dashBoundaryDash = encoder.encode(`--${this.boundary}--`);
- readonly dashBoundary = encoder.encode(`--${this.boundary}`);
- readonly bufReader: BufReader;
-
- constructor(reader: Deno.Reader, private boundary: string) {
- this.bufReader = new BufReader(reader);
- }
-
- /** Read all form data from stream.
- * If total size of stored data in memory exceed maxMemory,
- * overflowed file data will be written to temporal files.
- * String field values are never written to files.
- * null value means parsing or writing to file was failed in some reason.
- * @param maxMemory maximum memory size to store file in memory. bytes. @default 10485760 (10MB)
- * */
- async readForm(maxMemory = 10 << 20): Promise<MultipartFormData> {
- const fileMap = new Map<string, FormFile | FormFile[]>();
- const valueMap = new Map<string, string>();
- let maxValueBytes = maxMemory + (10 << 20);
- const buf = new Deno.Buffer(new Uint8Array(maxValueBytes));
- for (;;) {
- const p = await this.nextPart();
- if (p === null) {
- break;
- }
- if (p.formName === "") {
- continue;
- }
- buf.reset();
- if (!p.fileName) {
- // value
- const n = await copyN(p, buf, maxValueBytes);
- maxValueBytes -= n;
- if (maxValueBytes < 0) {
- throw new RangeError("message too large");
- }
- const value = new TextDecoder().decode(buf.bytes());
- valueMap.set(p.formName, value);
- continue;
- }
- // file
- let formFile: FormFile | FormFile[] | undefined;
- const n = await copyN(p, buf, maxValueBytes);
- const contentType = p.headers.get("content-type");
- assert(contentType != null, "content-type must be set");
- if (n > maxMemory) {
- // too big, write to disk and flush buffer
- const ext = extname(p.fileName);
- const filepath = await Deno.makeTempFile({
- dir: ".",
- prefix: "multipart-",
- suffix: ext,
- });
-
- const file = await Deno.open(filepath, { write: true });
-
- try {
- const size = await Deno.copy(new MultiReader(buf, p), file);
-
- file.close();
- formFile = {
- filename: p.fileName,
- type: contentType,
- tempfile: filepath,
- size,
- };
- } catch (e) {
- await Deno.remove(filepath);
- throw e;
- }
- } else {
- formFile = {
- filename: p.fileName,
- type: contentType,
- content: buf.bytes(),
- size: buf.length,
- };
- maxMemory -= n;
- maxValueBytes -= n;
- }
- if (formFile) {
- const mapVal = fileMap.get(p.formName);
- if (mapVal !== undefined) {
- if (Array.isArray(mapVal)) {
- mapVal.push(formFile);
- } else {
- fileMap.set(p.formName, [mapVal, formFile]);
- }
- } else {
- fileMap.set(p.formName, formFile);
- }
- }
- }
- return multipartFormData(fileMap, valueMap);
- }
-
- private currentPart: PartReader | undefined;
- private partsRead = 0;
-
- private async nextPart(): Promise<PartReader | null> {
- if (this.currentPart) {
- this.currentPart.close();
- }
- if (equals(this.dashBoundary, encoder.encode("--"))) {
- throw new Error("boundary is empty");
- }
- let expectNewPart = false;
- for (;;) {
- const line = await this.bufReader.readSlice("\n".charCodeAt(0));
- if (line === null) {
- throw new Deno.errors.UnexpectedEof();
- }
- if (this.isBoundaryDelimiterLine(line)) {
- this.partsRead++;
- const r = new TextProtoReader(this.bufReader);
- const headers = await r.readMIMEHeader();
- if (headers === null) {
- throw new Deno.errors.UnexpectedEof();
- }
- const np = new PartReader(this, headers);
- this.currentPart = np;
- return np;
- }
- if (this.isFinalBoundary(line)) {
- return null;
- }
- if (expectNewPart) {
- throw new Error(`expecting a new Part; got line ${line}`);
- }
- if (this.partsRead === 0) {
- continue;
- }
- if (equals(line, this.newLine)) {
- expectNewPart = true;
- continue;
- }
- throw new Error(`unexpected line in nextPart(): ${line}`);
- }
- }
-
- private isFinalBoundary(line: Uint8Array): boolean {
- if (!startsWith(line, this.dashBoundaryDash)) {
- return false;
- }
- const rest = line.slice(this.dashBoundaryDash.length, line.length);
- return rest.length === 0 || equals(skipLWSPChar(rest), this.newLine);
- }
-
- private isBoundaryDelimiterLine(line: Uint8Array): boolean {
- if (!startsWith(line, this.dashBoundary)) {
- return false;
- }
- const rest = line.slice(this.dashBoundary.length);
- return equals(skipLWSPChar(rest), this.newLine);
- }
-}
-
-function multipartFormData(
- fileMap: Map<string, FormFile | FormFile[]>,
- valueMap: Map<string, string>,
-): MultipartFormData {
- function file(key: string): FormFile | FormFile[] | undefined {
- return fileMap.get(key);
- }
- function value(key: string): string | undefined {
- return valueMap.get(key);
- }
- function* entries(): IterableIterator<
- [string, string | FormFile | FormFile[] | undefined]
- > {
- yield* fileMap;
- yield* valueMap;
- }
- async function removeAll(): Promise<void> {
- const promises: Array<Promise<void>> = [];
- for (const val of fileMap.values()) {
- if (Array.isArray(val)) {
- for (const subVal of val) {
- if (!subVal.tempfile) continue;
- promises.push(Deno.remove(subVal.tempfile));
- }
- } else {
- if (!val.tempfile) continue;
- promises.push(Deno.remove(val.tempfile));
- }
- }
- await Promise.all(promises);
- }
- return {
- file,
- value,
- entries,
- removeAll,
- [Symbol.iterator](): IterableIterator<
- [string, string | FormFile | FormFile[] | undefined]
- > {
- return entries();
- },
- };
-}
-
-class PartWriter implements Deno.Writer {
- closed = false;
- private readonly partHeader: string;
- private headersWritten = false;
-
- constructor(
- private writer: Deno.Writer,
- readonly boundary: string,
- public headers: Headers,
- isFirstBoundary: boolean,
- ) {
- let buf = "";
- if (isFirstBoundary) {
- buf += `--${boundary}\r\n`;
- } else {
- buf += `\r\n--${boundary}\r\n`;
- }
- for (const [key, value] of headers.entries()) {
- buf += `${key}: ${value}\r\n`;
- }
- buf += `\r\n`;
- this.partHeader = buf;
- }
-
- close(): void {
- this.closed = true;
- }
-
- async write(p: Uint8Array): Promise<number> {
- if (this.closed) {
- throw new Error("part is closed");
- }
- if (!this.headersWritten) {
- await this.writer.write(encoder.encode(this.partHeader));
- this.headersWritten = true;
- }
- return this.writer.write(p);
- }
-}
-
-function checkBoundary(b: string): string {
- if (b.length < 1 || b.length > 70) {
- throw new Error(`invalid boundary length: ${b.length}`);
- }
- const end = b.length - 1;
- for (let i = 0; i < end; i++) {
- const c = b.charAt(i);
- if (!c.match(/[a-zA-Z0-9'()+_,\-./:=?]/) || (c === " " && i !== end)) {
- throw new Error("invalid boundary character: " + c);
- }
- }
- return b;
-}
-
-/** Writer for creating multipart/form-data */
-export class MultipartWriter {
- private readonly _boundary: string;
-
- get boundary(): string {
- return this._boundary;
- }
-
- private lastPart: PartWriter | undefined;
- private bufWriter: BufWriter;
- private isClosed = false;
-
- constructor(private readonly writer: Deno.Writer, boundary?: string) {
- if (boundary !== void 0) {
- this._boundary = checkBoundary(boundary);
- } else {
- this._boundary = randomBoundary();
- }
- this.bufWriter = new BufWriter(writer);
- }
-
- formDataContentType(): string {
- return `multipart/form-data; boundary=${this.boundary}`;
- }
-
- private createPart(headers: Headers): Deno.Writer {
- if (this.isClosed) {
- throw new Error("multipart: writer is closed");
- }
- if (this.lastPart) {
- this.lastPart.close();
- }
- const part = new PartWriter(
- this.writer,
- this.boundary,
- headers,
- !this.lastPart,
- );
- this.lastPart = part;
- return part;
- }
-
- createFormFile(field: string, filename: string): Deno.Writer {
- const h = new Headers();
- h.set(
- "Content-Disposition",
- `form-data; name="${field}"; filename="${filename}"`,
- );
- h.set("Content-Type", "application/octet-stream");
- return this.createPart(h);
- }
-
- createFormField(field: string): Deno.Writer {
- const h = new Headers();
- h.set("Content-Disposition", `form-data; name="${field}"`);
- h.set("Content-Type", "application/octet-stream");
- return this.createPart(h);
- }
-
- async writeField(field: string, value: string): Promise<void> {
- const f = await this.createFormField(field);
- await f.write(encoder.encode(value));
- }
-
- async writeFile(
- field: string,
- filename: string,
- file: Deno.Reader,
- ): Promise<void> {
- const f = await this.createFormFile(field, filename);
- await Deno.copy(file, f);
- }
-
- private flush(): Promise<void> {
- return this.bufWriter.flush();
- }
-
- /** Close writer. No additional data can be written to stream */
- async close(): Promise<void> {
- if (this.isClosed) {
- throw new Error("multipart: writer is closed");
- }
- if (this.lastPart) {
- this.lastPart.close();
- this.lastPart = void 0;
- }
- await this.writer.write(encoder.encode(`\r\n--${this.boundary}--\r\n`));
- await this.flush();
- this.isClosed = true;
- }
-}
diff --git a/std/mime/multipart_test.ts b/std/mime/multipart_test.ts
deleted file mode 100644
index eee3005f1..000000000
--- a/std/mime/multipart_test.ts
+++ /dev/null
@@ -1,293 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-import {
- assert,
- assertEquals,
- assertThrows,
- assertThrowsAsync,
-} from "../testing/asserts.ts";
-import * as path from "../path/mod.ts";
-import {
- isFormFile,
- matchAfterPrefix,
- MultipartReader,
- MultipartWriter,
- scanUntilBoundary,
-} from "./multipart.ts";
-import { StringWriter } from "../io/writers.ts";
-
-const e = new TextEncoder();
-const boundary = "--abcde";
-const dashBoundary = e.encode("--" + boundary);
-const nlDashBoundary = e.encode("\r\n--" + boundary);
-
-const moduleDir = path.dirname(path.fromFileUrl(import.meta.url));
-const testdataDir = path.resolve(moduleDir, "testdata");
-
-Deno.test("multipartScanUntilBoundary1", function (): void {
- const data = `--${boundary}`;
- const n = scanUntilBoundary(
- e.encode(data),
- dashBoundary,
- nlDashBoundary,
- 0,
- true,
- );
- assertEquals(n, null);
-});
-
-Deno.test("multipartScanUntilBoundary2", function (): void {
- const data = `foo\r\n--${boundary}`;
- const n = scanUntilBoundary(
- e.encode(data),
- dashBoundary,
- nlDashBoundary,
- 0,
- true,
- );
- assertEquals(n, 3);
-});
-
-Deno.test("multipartScanUntilBoundary3", function (): void {
- const data = `foobar`;
- const n = scanUntilBoundary(
- e.encode(data),
- dashBoundary,
- nlDashBoundary,
- 0,
- false,
- );
- assertEquals(n, data.length);
-});
-
-Deno.test("multipartScanUntilBoundary4", function (): void {
- const data = `foo\r\n--`;
- const n = scanUntilBoundary(
- e.encode(data),
- dashBoundary,
- nlDashBoundary,
- 0,
- false,
- );
- assertEquals(n, 3);
-});
-
-Deno.test("multipartMatchAfterPrefix1", function (): void {
- const data = `${boundary}\r`;
- const v = matchAfterPrefix(e.encode(data), e.encode(boundary), false);
- assertEquals(v, 1);
-});
-
-Deno.test("multipartMatchAfterPrefix2", function (): void {
- const data = `${boundary}hoge`;
- const v = matchAfterPrefix(e.encode(data), e.encode(boundary), false);
- assertEquals(v, -1);
-});
-
-Deno.test("multipartMatchAfterPrefix3", function (): void {
- const data = `${boundary}`;
- const v = matchAfterPrefix(e.encode(data), e.encode(boundary), false);
- assertEquals(v, 0);
-});
-
-Deno.test("multipartMultipartWriter", async function (): Promise<void> {
- const buf = new Deno.Buffer();
- const mw = new MultipartWriter(buf);
- await mw.writeField("foo", "foo");
- await mw.writeField("bar", "bar");
- const f = await Deno.open(path.join(testdataDir, "sample.txt"), {
- read: true,
- });
- await mw.writeFile("file", "sample.txt", f);
- await mw.close();
- f.close();
-});
-
-Deno.test("multipartMultipartWriter2", function (): void {
- const w = new StringWriter();
- assertThrows(
- (): MultipartWriter => new MultipartWriter(w, ""),
- Error,
- "invalid boundary length",
- );
- assertThrows(
- (): MultipartWriter =>
- new MultipartWriter(
- w,
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaaaa",
- ),
- Error,
- "invalid boundary length",
- );
- assertThrows(
- (): MultipartWriter => new MultipartWriter(w, "aaa aaa"),
- Error,
- "invalid boundary character",
- );
- assertThrows(
- (): MultipartWriter => new MultipartWriter(w, "boundary¥¥"),
- Error,
- "invalid boundary character",
- );
-});
-
-Deno.test("multipartMultipartWriter3", async function (): Promise<void> {
- const w = new StringWriter();
- const mw = new MultipartWriter(w);
- await mw.writeField("foo", "foo");
- await mw.close();
- await assertThrowsAsync(
- async (): Promise<void> => {
- await mw.close();
- },
- Error,
- "closed",
- );
- await assertThrowsAsync(
- async (): Promise<void> => {
- // deno-lint-ignore no-explicit-any
- await mw.writeFile("bar", "file", null as any);
- },
- Error,
- "closed",
- );
- await assertThrowsAsync(
- async (): Promise<void> => {
- await mw.writeField("bar", "bar");
- },
- Error,
- "closed",
- );
- assertThrows(
- (): void => {
- mw.createFormField("bar");
- },
- Error,
- "closed",
- );
- assertThrows(
- (): void => {
- mw.createFormFile("bar", "file");
- },
- Error,
- "closed",
- );
-});
-
-Deno.test({
- name: "[mime/multipart] readForm() basic",
- async fn() {
- const o = await Deno.open(path.join(testdataDir, "sample.txt"));
- const mr = new MultipartReader(
- o,
- "--------------------------434049563556637648550474",
- );
- const form = await mr.readForm();
- assertEquals(form.value("foo"), "foo");
- assertEquals(form.value("bar"), "bar");
- const file = form.file("file");
- assert(isFormFile(file));
- assert(file.content !== void 0);
- const file2 = form.file("file2");
- assert(isFormFile(file2));
- assert(file2.filename === "中文.json");
- assert(file2.content !== void 0);
- o.close();
- },
-});
-
-Deno.test({
- name:
- "[mime/multipart] readForm() should store big file completely in temp file",
- async fn() {
- const multipartFile = path.join(testdataDir, "form-data.dat");
- const sampleFile = await Deno.makeTempFile();
- const writer = await Deno.open(multipartFile, {
- write: true,
- create: true,
- });
-
- const size = 1 << 24; // 16mb
-
- await Deno.truncate(sampleFile, size);
- const bigFile = await Deno.open(sampleFile, { read: true });
-
- const mw = new MultipartWriter(writer);
- await mw.writeField("deno", "land");
- await mw.writeField("bar", "bar");
- await mw.writeFile("file", "sample.bin", bigFile);
-
- await mw.close();
- writer.close();
- bigFile.close();
-
- const o = await Deno.open(multipartFile);
- const mr = new MultipartReader(o, mw.boundary);
- // use low-memory to write "file" into temp file.
- const form = await mr.readForm(20);
- try {
- assertEquals(form.value("deno"), "land");
- assertEquals(form.value("bar"), "bar");
- let file = form.file("file");
- if (Array.isArray(file)) {
- file = file[0];
- }
- assert(file != null);
- assert(file.tempfile != null);
- assertEquals(file.size, size);
- assertEquals(file.type, "application/octet-stream");
- // TODO(bartlomieju): checksum of tmp & sampleFile
- } finally {
- await Deno.remove(multipartFile);
- await Deno.remove(sampleFile);
- await form.removeAll();
- o.close();
- }
- },
-});
-
-Deno.test({
- name: "[mime/multipart] removeAll() should remove all tempfiles",
- async fn() {
- const o = await Deno.open(path.join(testdataDir, "sample.txt"));
- const mr = new MultipartReader(
- o,
- "--------------------------434049563556637648550474",
- );
- const form = await mr.readForm(20);
- let file = form.file("file");
- if (Array.isArray(file)) {
- file = file[0];
- }
- assert(file != null);
- const { tempfile, content } = file;
- assert(tempfile != null);
- assert(content == null);
- const stat = await Deno.stat(tempfile);
- assertEquals(stat.size, file.size);
- await form.removeAll();
- await assertThrowsAsync(async () => {
- await Deno.stat(tempfile);
- }, Deno.errors.NotFound);
- o.close();
- },
-});
-
-Deno.test({
- name: "[mime/multipart] entries()",
- async fn() {
- const o = await Deno.open(path.join(testdataDir, "sample.txt"));
- const mr = new MultipartReader(
- o,
- "--------------------------434049563556637648550474",
- );
- const form = await mr.readForm();
- const map = new Map(form.entries());
- assertEquals(map.get("foo"), "foo");
- assertEquals(map.get("bar"), "bar");
- const file = map.get("file");
- assert(isFormFile(file));
- assertEquals(file.filename, "tsconfig.json");
- o.close();
- },
-});
diff --git a/std/mime/test.ts b/std/mime/test.ts
deleted file mode 100644
index 590417055..000000000
--- a/std/mime/test.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-import "./mod.ts";
diff --git a/std/mime/testdata/sample.txt b/std/mime/testdata/sample.txt
deleted file mode 100644
index 8c7a1c204..000000000
--- a/std/mime/testdata/sample.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-----------------------------434049563556637648550474
-content-disposition: form-data; name="foo"
-content-type: application/octet-stream
-
-foo
-----------------------------434049563556637648550474
-content-disposition: form-data; name="bar"
-content-type: application/octet-stream
-
-bar
-----------------------------434049563556637648550474
-content-disposition: form-data; name="file"; filename="tsconfig.json"
-content-type: application/octet-stream
-
-{
- "compilerOptions": {
- "target": "es2018",
- "baseUrl": ".",
- "paths": {
- "deno": ["./deno.d.ts"],
- "https://*": ["../../.deno/deps/https/*"],
- "http://*": ["../../.deno/deps/http/*"]
- }
- }
-}
-
-----------------------------434049563556637648550474
-content-disposition: form-data; name="file2"; filename="中文.json"
-content-type: application/octet-stream
-
-{
- "test": "filename"
-}
-
-----------------------------434049563556637648550474--