From 4bb7e315221d524a079c1a3d4cd9ec31357e5018 Mon Sep 17 00:00:00 2001 From: Shin Date: Mon, 16 Nov 2020 18:20:46 -0300 Subject: [PATCH 1/6] feat: add new method on Request class --- api.ts | 7 +++++++ types.ts | 2 ++ 2 files changed, 9 insertions(+) diff --git a/api.ts b/api.ts index a8fe29102..d34b2b635 100644 --- a/api.ts +++ b/api.ts @@ -84,6 +84,13 @@ export class Request extends ServerRequest implements APIRequest { await this.send(JSON.stringify(data, replacer, space), 'application/json; charset=utf-8') } + async jsonBody(): Promise { + const buff: Uint8Array = await Deno.readAll(this.body); + const encoded = new TextDecoder("utf-8").decode(buff); + const json = JSON.parse(encoded); + return json; + } + async send(data: string | Uint8Array | ArrayBuffer, contentType?: string): Promise { if (this.#resp.done) { log.warn('ServerRequest: repeat respond calls') diff --git a/types.ts b/types.ts index ce4289cbe..a44490963 100644 --- a/types.ts +++ b/types.ts @@ -93,6 +93,8 @@ export interface APIRequest extends ServerRequest { send(data: string | Uint8Array | ArrayBuffer, contentType?: string): Promise /** `json` replies to the request with a json content */ json(data: any): Promise + /** `jsonBody` will return the request body in a JSON format */ + jsonBody(): Promise } /** From ae843c7fa46d9f864003f60b9508c5c72409164d Mon Sep 17 00:00:00 2001 From: Shin Date: Mon, 16 Nov 2020 18:44:56 -0300 Subject: [PATCH 2/6] feat: added try/block catch --- api.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/api.ts b/api.ts index d34b2b635..0786c976d 100644 --- a/api.ts +++ b/api.ts @@ -85,10 +85,15 @@ export class Request extends ServerRequest implements APIRequest { } async jsonBody(): Promise { - const buff: Uint8Array = await Deno.readAll(this.body); - const encoded = new TextDecoder("utf-8").decode(buff); - const json = JSON.parse(encoded); - return json; + try { + const buff: Uint8Array = await Deno.readAll(this.body); + const encoded = new TextDecoder("utf-8").decode(buff); + const json = JSON.parse(encoded); + return json; + } catch (err) { + console.error("Failed to parse the request body.", err); + return null; + } } async send(data: string | Uint8Array | ArrayBuffer, contentType?: string): Promise { From 41dd2c1ca99d9fb2aad212596e1037eba309b93a Mon Sep 17 00:00:00 2001 From: Shin Date: Tue, 17 Nov 2020 22:00:44 -0300 Subject: [PATCH 3/6] feat: rename function to decodeBody, implemented string and json decoding --- api.ts | 35 +++++++++++++++++++++++++---------- types.ts | 24 ++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/api.ts b/api.ts index 0786c976d..8fe551ec5 100644 --- a/api.ts +++ b/api.ts @@ -2,7 +2,7 @@ import { compress as brotli } from 'https://deno.land/x/brotli@v0.1.4/mod.ts' import { gzipEncode } from 'https://deno.land/x/wasm_gzip@v1.0.0/mod.ts' import log from './log.ts' import { ServerRequest } from './std.ts' -import type { APIRequest } from './types.ts' +import type { APIRequest, FormDataBody } from './types.ts' export class Request extends ServerRequest implements APIRequest { #pathname: string @@ -84,15 +84,30 @@ export class Request extends ServerRequest implements APIRequest { await this.send(JSON.stringify(data, replacer, space), 'application/json; charset=utf-8') } - async jsonBody(): Promise { - try { - const buff: Uint8Array = await Deno.readAll(this.body); - const encoded = new TextDecoder("utf-8").decode(buff); - const json = JSON.parse(encoded); - return json; - } catch (err) { - console.error("Failed to parse the request body.", err); - return null; + async decodeBody(type: "text" | "json" | "form-data"): Promise { + if (type === "text") { + try { + const buff: Uint8Array = await Deno.readAll(this.body); + const encoded = new TextDecoder("utf-8").decode(buff); + return encoded; + } catch (err) { + console.error("Failed to parse the request body.", err); + } + } + + if (type === "json") { + try { + const buff: Uint8Array = await Deno.readAll(this.body); + const encoded = new TextDecoder("utf-8").decode(buff); + const json = JSON.parse(encoded); + return json; + } catch (err) { + console.error("Failed to parse the request body.", err); + } + } + + if (type === "form-data") { + // TODO } } diff --git a/types.ts b/types.ts index a44490963..a907a9c69 100644 --- a/types.ts +++ b/types.ts @@ -93,8 +93,10 @@ export interface APIRequest extends ServerRequest { send(data: string | Uint8Array | ArrayBuffer, contentType?: string): Promise /** `json` replies to the request with a json content */ json(data: any): Promise - /** `jsonBody` will return the request body in a JSON format */ - jsonBody(): Promise + /** `decodeBody` will return a string, a form-data or any json object */ + decodeBody(type: "text"): Promise + decodeBody(type: "json"): Promise + decodeBody(type: "form-data"): Promise } /** @@ -107,3 +109,21 @@ export interface RouterURL { readonly params: Record readonly query: URLSearchParams } + +/** + * The form data body + */ +export interface FormDataBody { + get(key: string): string + getFile(key: string): FormFile +} + +/** + * The form file data + */ +export interface FormFile { + filename: string + contentType: string + content: Uint8Array + size: number +} \ No newline at end of file From bb5774ec37f665f7fedd1a47762ba886923a2f32 Mon Sep 17 00:00:00 2001 From: Shin Date: Sun, 22 Nov 2020 13:52:47 -0300 Subject: [PATCH 4/6] feat: added formdata from OAK's multipart file --- api.ts | 23 +++++++++++++++++++++-- std.ts | 1 + 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/api.ts b/api.ts index 8fe551ec5..ee3037e9a 100644 --- a/api.ts +++ b/api.ts @@ -1,4 +1,5 @@ import { compress as brotli } from 'https://deno.land/x/brotli@v0.1.4/mod.ts' +import { FormDataReader } from 'https://deno.land/x/oak@v6.3.2/multipart.ts' import { gzipEncode } from 'https://deno.land/x/wasm_gzip@v1.0.0/mod.ts' import log from './log.ts' import { ServerRequest } from './std.ts' @@ -84,7 +85,9 @@ export class Request extends ServerRequest implements APIRequest { await this.send(JSON.stringify(data, replacer, space), 'application/json; charset=utf-8') } - async decodeBody(type: "text" | "json" | "form-data"): Promise { + async decodeBody(type: "text"): Promise + async decodeBody(type: "json"): Promise + async decodeBody(type: "form-data"): Promise { if (type === "text") { try { const buff: Uint8Array = await Deno.readAll(this.body); @@ -107,7 +110,23 @@ export class Request extends ServerRequest implements APIRequest { } if (type === "form-data") { - // TODO + try { + const boundary = this.headers.get("content-type"); + + if (!boundary) throw new Error("Failed to get the content-type") + + const reader = new FormDataReader(boundary, this.body); + const { fields, files } = await reader.read({ maxSize: 1024 * 1024 * 10 }); + + return { + get: (key: string) => fields[key], + getFile: (key: string) => files?.find(i => i.name === key) + } + + } catch (err) { + console.error("Failed to parse the request form-data", err) + } + } } diff --git a/std.ts b/std.ts index 5e8a02462..aed52fe2c 100644 --- a/std.ts +++ b/std.ts @@ -8,4 +8,5 @@ export type { Response } from 'https://deno.land/std@0.76.0/http/server.ts' export { fromStreamReader } from 'https://deno.land/std@0.76.0/io/mod.ts' export * as path from 'https://deno.land/std@0.76.0/path/mod.ts' export * as ws from 'https://deno.land/std@0.76.0/ws/mod.ts' +export * as multipart from 'https://deno.land/std@0.78.0/mime/multipart.ts' From a152ae76091bb56c156ba36b2852a4aa3ed31a08 Mon Sep 17 00:00:00 2001 From: Shin Date: Sun, 22 Nov 2020 14:15:07 -0300 Subject: [PATCH 5/6] feat: update types to include values from oak multipart --- types.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/types.ts b/types.ts index a907a9c69..4a69c7d32 100644 --- a/types.ts +++ b/types.ts @@ -122,8 +122,9 @@ export interface FormDataBody { * The form file data */ export interface FormFile { - filename: string - contentType: string + name: string content: Uint8Array - size: number + contentType: string + filename: string + originalName: string } \ No newline at end of file From e24ca711041bf9f844837450b9964e3d528a9f49 Mon Sep 17 00:00:00 2001 From: Shin Date: Mon, 23 Nov 2020 20:47:03 -0300 Subject: [PATCH 6/6] feat: fixed overload function on decodeBody --- api.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api.ts b/api.ts index ee3037e9a..c984934ab 100644 --- a/api.ts +++ b/api.ts @@ -87,7 +87,8 @@ export class Request extends ServerRequest implements APIRequest { async decodeBody(type: "text"): Promise async decodeBody(type: "json"): Promise - async decodeBody(type: "form-data"): Promise { + async decodeBody(type: "form-data"): Promise + async decodeBody(type: string): Promise { if (type === "text") { try { const buff: Uint8Array = await Deno.readAll(this.body); @@ -126,7 +127,6 @@ export class Request extends ServerRequest implements APIRequest { } catch (err) { console.error("Failed to parse the request form-data", err) } - } }