1+ import { compress as brotli } from 'https://deno.land/x/[email protected] /mod.ts' 12import { gzipEncode } from 'https://deno.land/x/[email protected] /mod.ts' 23import 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 >
1012 #resp = {
1113 status : 200 ,
1214 headers : new Headers ( {
@@ -16,65 +18,41 @@ export class Request implements APIRequest {
1618 done : false
1719 }
1820
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
6644 }
6745
68- async finalize ( ) {
69- return this . #req . finalize ( )
46+ get pathname ( ) : string {
47+ return this . #pathname
7048 }
7149
72- get url ( ) : APIRequestURL {
73- return this . #url
50+ get params ( ) : Record < string , string > {
51+ return this . #params
7452 }
7553
76- get headers ( ) : Headers {
77- return this . #req . headers
54+ get query ( ) : URLSearchParams {
55+ return this . #query
7856 }
7957
8058 get cookies ( ) : ReadonlyMap < string , string > {
@@ -102,11 +80,11 @@ export class Request implements APIRequest {
10280 return this
10381 }
10482
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 ' )
10785 }
10886
109- async send ( data : string | Uint8Array | ArrayBuffer , contentType ?: string ) {
87+ async send ( data : string | Uint8Array | ArrayBuffer , contentType ?: string ) : Promise < void > {
11088 if ( this . #resp. done ) {
11189 log . warn ( 'ServerRequest: repeat respond calls' )
11290 return
@@ -125,41 +103,36 @@ export class Request implements APIRequest {
125103 this . #resp. headers . set ( 'Content-Type' , contentType )
126104 } else if ( this . #resp. headers . has ( 'Content-Type' ) ) {
127105 contentType = this . #resp. headers . get ( 'Content-Type' ) !
106+ } else if ( typeof data === 'string' && data . length > 0 ) {
107+ contentType = 'text/plain; charset=utf-8'
128108 }
129109 let isText = false
130110 if ( contentType ) {
131111 if ( contentType . startsWith ( 'text/' ) ) {
132112 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 ) ) {
134114 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 ) ) {
136116 isText = true
137117 }
138118 }
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+ }
143129 }
144130 this . #resp. headers . set ( 'Date' , ( new Date ) . toUTCString ( ) )
145131 this . #resp. done = true
146- return this . #req . respond ( {
132+ await this . respond ( {
147133 status : this . #resp. status ,
148134 headers : this . #resp. headers ,
149135 body
150136 } ) . catch ( err => log . warn ( 'ServerRequest.respond:' , err . message ) )
151137 }
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- }
165138}
0 commit comments