Skip to content
This repository was archived by the owner on Jul 6, 2025. It is now read-only.

Commit 9596ac9

Browse files
authored
Merge pull request #35 from shinspiegel/json-body
feat: add new method on Request class
2 parents 52ed72c + e24ca71 commit 9596ac9

File tree

2 files changed

+70
-1
lines changed

2 files changed

+70
-1
lines changed

api.ts

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { compress as brotli } from 'https://deno.land/x/[email protected]/mod.ts'
2+
import { FormDataReader } from 'https://deno.land/x/[email protected]/multipart.ts'
23
import { gzipEncode } from 'https://deno.land/x/[email protected]/mod.ts'
34
import log from './log.ts'
45
import { ServerRequest } from './std.ts'
5-
import type { APIRequest } from './types.ts'
6+
import type { APIRequest, FormDataBody } from './types.ts'
67

78
export class Request extends ServerRequest implements APIRequest {
89
#pathname: string
@@ -84,6 +85,51 @@ export class Request extends ServerRequest implements APIRequest {
8485
await this.send(JSON.stringify(data, replacer, space), 'application/json; charset=utf-8')
8586
}
8687

88+
async decodeBody(type: "text"): Promise<string>
89+
async decodeBody(type: "json"): Promise<any>
90+
async decodeBody(type: "form-data"): Promise<FormDataBody>
91+
async decodeBody(type: string): Promise<any> {
92+
if (type === "text") {
93+
try {
94+
const buff: Uint8Array = await Deno.readAll(this.body);
95+
const encoded = new TextDecoder("utf-8").decode(buff);
96+
return encoded;
97+
} catch (err) {
98+
console.error("Failed to parse the request body.", err);
99+
}
100+
}
101+
102+
if (type === "json") {
103+
try {
104+
const buff: Uint8Array = await Deno.readAll(this.body);
105+
const encoded = new TextDecoder("utf-8").decode(buff);
106+
const json = JSON.parse(encoded);
107+
return json;
108+
} catch (err) {
109+
console.error("Failed to parse the request body.", err);
110+
}
111+
}
112+
113+
if (type === "form-data") {
114+
try {
115+
const boundary = this.headers.get("content-type");
116+
117+
if (!boundary) throw new Error("Failed to get the content-type")
118+
119+
const reader = new FormDataReader(boundary, this.body);
120+
const { fields, files } = await reader.read({ maxSize: 1024 * 1024 * 10 });
121+
122+
return {
123+
get: (key: string) => fields[key],
124+
getFile: (key: string) => files?.find(i => i.name === key)
125+
}
126+
127+
} catch (err) {
128+
console.error("Failed to parse the request form-data", err)
129+
}
130+
}
131+
}
132+
87133
async send(data: string | Uint8Array | ArrayBuffer, contentType?: string): Promise<void> {
88134
if (this.#resp.done) {
89135
log.warn('ServerRequest: repeat respond calls')

types.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ export interface APIRequest extends ServerRequest {
9393
send(data: string | Uint8Array | ArrayBuffer, contentType?: string): Promise<void>
9494
/** `json` replies to the request with a json content */
9595
json(data: any): Promise<void>
96+
/** `decodeBody` will return a string, a form-data or any json object */
97+
decodeBody(type: "text"): Promise<string>
98+
decodeBody(type: "json"): Promise<any>
99+
decodeBody(type: "form-data"): Promise<FormDataBody>
96100
}
97101

98102
/**
@@ -105,3 +109,22 @@ export interface RouterURL {
105109
readonly params: Record<string, string>
106110
readonly query: URLSearchParams
107111
}
112+
113+
/**
114+
* The form data body
115+
*/
116+
export interface FormDataBody {
117+
get(key: string): string
118+
getFile(key: string): FormFile
119+
}
120+
121+
/**
122+
* The form file data
123+
*/
124+
export interface FormFile {
125+
name: string
126+
content: Uint8Array
127+
contentType: string
128+
filename: string
129+
originalName: string
130+
}

0 commit comments

Comments
 (0)