diff options
Diffstat (limited to 'std/mime')
-rw-r--r-- | std/mime/mod.ts | 2 | ||||
-rw-r--r-- | std/mime/multipart.ts | 609 | ||||
-rw-r--r-- | std/mime/multipart_test.ts | 293 | ||||
-rw-r--r-- | std/mime/test.ts | 2 | ||||
-rw-r--r-- | std/mime/testdata/sample.txt | 35 |
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--
|