1
+ import { compress as brotli } from 'https://deno.land/x/[email protected] /mod.ts'
1
2
import { gzipEncode } from 'https://deno.land/x/[email protected] /mod.ts'
2
3
import log from './log.ts'
3
- import type { ServerRequest } from './std.ts'
4
- import type { APIRequest , APIRequestURL , Response } from './types.ts'
5
-
6
- export class Request implements APIRequest {
7
- #req: ServerRequest
8
- #url: APIRequestURL
9
- #cookies: ReadonlyMap < string , string > = new Map ( )
4
+ import { ServerRequest } from './std.ts'
5
+ import type { APIRequest } from './types.ts'
6
+
7
+ export class Request extends ServerRequest implements APIRequest {
8
+ #pathname: string
9
+ #params: Record < string , string >
10
+ #query: URLSearchParams
11
+ #cookies: ReadonlyMap < string , string >
10
12
#resp = {
11
13
status : 200 ,
12
14
headers : new Headers ( {
@@ -16,65 +18,41 @@ export class Request implements APIRequest {
16
18
done : false
17
19
}
18
20
19
- constructor ( req : ServerRequest , url : APIRequestURL ) {
20
- this . #req = req
21
- this . #url = url
22
- }
23
-
24
- get method ( ) : string {
25
- return this . #req. method
26
- }
27
-
28
- get proto ( ) {
29
- return this . #req. proto
30
- }
31
-
32
- get protoMinor ( ) {
33
- return this . #req. protoMinor
34
- }
35
-
36
- get protoMajor ( ) {
37
- return this . #req. protoMajor
38
- }
39
-
40
- get conn ( ) {
41
- return this . #req. conn
42
- }
43
-
44
- get r ( ) {
45
- return this . #req. r
46
- }
47
-
48
- get w ( ) {
49
- return this . #req. w
50
- }
51
-
52
- get done ( ) {
53
- return this . #req. done
54
- }
55
-
56
- get contentLength ( ) {
57
- return this . #req. contentLength
58
- }
59
-
60
- get body ( ) {
61
- return this . #req. body
62
- }
63
-
64
- async respond ( r : Response ) {
65
- return this . #req. respond ( r )
21
+ constructor ( req : ServerRequest , pathname : string , params : Record < string , string > , query : URLSearchParams ) {
22
+ super ( )
23
+ this . conn = req . conn
24
+ this . r = req . r
25
+ this . w = req . w
26
+ this . method = req . method
27
+ this . url = req . url
28
+ this . proto = req . proto
29
+ this . protoMinor = req . protoMinor
30
+ this . protoMajor = req . protoMajor
31
+ this . headers = req . headers
32
+ this . done = req . done
33
+ this . #pathname = pathname
34
+ this . #params = params
35
+ this . #query = query
36
+ const cookies = new Map ( )
37
+ this . headers . get ( 'cookie' ) ?. split ( ';' ) . forEach ( cookie => {
38
+ const p = cookie . trim ( ) . split ( '=' )
39
+ if ( p . length >= 2 ) {
40
+ cookies . set ( p . shift ( ) ! . trim ( ) , decodeURI ( p . join ( '=' ) ) )
41
+ }
42
+ } )
43
+ this . #cookies = cookies
66
44
}
67
45
68
- async finalize ( ) {
69
- return this . #req . finalize ( )
46
+ get pathname ( ) : string {
47
+ return this . #pathname
70
48
}
71
49
72
- get url ( ) : APIRequestURL {
73
- return this . #url
50
+ get params ( ) : Record < string , string > {
51
+ return this . #params
74
52
}
75
53
76
- get headers ( ) : Headers {
77
- return this . #req . headers
54
+ get query ( ) : URLSearchParams {
55
+ return this . #query
78
56
}
79
57
80
58
get cookies ( ) : ReadonlyMap < string , string > {
@@ -102,11 +80,11 @@ export class Request implements APIRequest {
102
80
return this
103
81
}
104
82
105
- json ( data : any , replacer ?: ( this : any , key : string , value : any ) => any , space ?: string | number ) {
106
- return this . send ( JSON . stringify ( data , replacer , space ) , 'application/json' )
83
+ async json ( data : any , replacer ?: ( this : any , key : string , value : any ) => any , space ?: string | number ) : Promise < void > {
84
+ await this . send ( JSON . stringify ( data , replacer , space ) , 'application/json; charset=utf-8 ' )
107
85
}
108
86
109
- async send ( data : string | Uint8Array | ArrayBuffer , contentType ?: string ) {
87
+ async send ( data : string | Uint8Array | ArrayBuffer , contentType ?: string ) : Promise < void > {
110
88
if ( this . #resp. done ) {
111
89
log . warn ( 'ServerRequest: repeat respond calls' )
112
90
return
@@ -125,41 +103,36 @@ export class Request implements APIRequest {
125
103
this . #resp. headers . set ( 'Content-Type' , contentType )
126
104
} else if ( this . #resp. headers . has ( 'Content-Type' ) ) {
127
105
contentType = this . #resp. headers . get ( 'Content-Type' ) !
106
+ } else if ( typeof data === 'string' && data . length > 0 ) {
107
+ contentType = 'text/plain; charset=utf-8'
128
108
}
129
109
let isText = false
130
110
if ( contentType ) {
131
111
if ( contentType . startsWith ( 'text/' ) ) {
132
112
isText = true
133
- } else if ( / ^ a p p l i c a t i o n \/ ( j a v a s c r i p t | t y p e c r i p t | j s o n | x m l ) / . test ( contentType ) ) {
113
+ } else if ( / ^ a p p l i c a t i o n \/ ( j a v a s c r i p t | t y p e c r i p t | j s o n | x m l ) / i . test ( contentType ) ) {
134
114
isText = true
135
- } else if ( / ^ i m a g e \/ s v g + x m l / . test ( contentType ) ) {
115
+ } else if ( / ^ i m a g e \/ s v g + x m l / i . test ( contentType ) ) {
136
116
isText = true
137
117
}
138
118
}
139
- if ( isText && body . length > 1024 && this . #req. headers . get ( 'accept-encoding' ) ?. includes ( 'gzip' ) ) {
140
- this . #resp. headers . set ( 'Vary' , 'Origin' )
141
- this . #resp. headers . set ( 'Content-Encoding' , 'gzip' )
142
- body = gzipEncode ( body )
119
+ if ( isText && body . length > 1024 ) {
120
+ if ( this . headers . get ( 'accept-encoding' ) ?. includes ( 'br' ) ) {
121
+ this . #resp. headers . set ( 'Vary' , 'Origin' )
122
+ this . #resp. headers . set ( 'Content-Encoding' , 'br' )
123
+ body = brotli ( body )
124
+ } else if ( this . headers . get ( 'accept-encoding' ) ?. includes ( 'gzip' ) ) {
125
+ this . #resp. headers . set ( 'Vary' , 'Origin' )
126
+ this . #resp. headers . set ( 'Content-Encoding' , 'gzip' )
127
+ body = gzipEncode ( body )
128
+ }
143
129
}
144
130
this . #resp. headers . set ( 'Date' , ( new Date ) . toUTCString ( ) )
145
131
this . #resp. done = true
146
- return this . #req . respond ( {
132
+ await this . respond ( {
147
133
status : this . #resp. status ,
148
134
headers : this . #resp. headers ,
149
135
body
150
136
} ) . catch ( err => log . warn ( 'ServerRequest.respond:' , err . message ) )
151
137
}
152
-
153
- async end ( status : number ) {
154
- if ( this . #resp. done ) {
155
- log . warn ( 'ServerRequest: repeat respond calls' )
156
- return
157
- }
158
- this . #resp. headers . set ( 'Date' , ( new Date ) . toUTCString ( ) )
159
- this . #resp. done = true
160
- return this . #req. respond ( {
161
- status,
162
- headers : this . #resp. headers ,
163
- } ) . catch ( err => log . warn ( 'ServerRequest.respond:' , err . message ) )
164
- }
165
138
}
0 commit comments