2
2
* Module dependencies.
3
3
*/
4
4
5
- var debug = require ( 'debug' ) ( 'koa-send' ) ;
6
- var resolvePath = require ( 'resolve-path' ) ;
7
- var assert = require ( 'assert' ) ;
8
- var path = require ( 'path' ) ;
9
- var normalize = path . normalize ;
10
- var basename = path . basename ;
11
- var extname = path . extname ;
12
- var resolve = path . resolve ;
13
- var parse = path . parse ;
14
- var sep = path . sep ;
15
- var fs = require ( 'mz/fs' ) ;
16
- var co = require ( 'co' ) ;
5
+ const debug = require ( 'debug' ) ( 'koa-send' ) ;
6
+ const resolvePath = require ( 'resolve-path' ) ;
7
+ const assert = require ( 'assert' ) ;
8
+ const fs = require ( 'mz/fs' ) ;
9
+
10
+ const {
11
+ normalize,
12
+ basename,
13
+ extname,
14
+ resolve,
15
+ parse,
16
+ sep
17
+ } = require ( 'path' ) ;
17
18
18
19
/**
19
20
* Expose `send()`.
@@ -32,100 +33,97 @@ module.exports = send;
32
33
* @api public
33
34
*/
34
35
35
- function send ( ctx , path , opts ) {
36
- return co ( function * ( ) {
37
-
38
- assert ( ctx , 'koa context required' ) ;
39
- assert ( path , 'pathname required' ) ;
40
- opts = opts || { } ;
41
-
42
- // options
43
- debug ( 'send "%s" %j' , path , opts ) ;
44
- var root = opts . root ? normalize ( resolve ( opts . root ) ) : '' ;
45
- var trailingSlash = '/' == path [ path . length - 1 ] ;
46
- path = path . substr ( parse ( path ) . root . length ) ;
47
- var index = opts . index ;
48
- var maxage = opts . maxage || opts . maxAge || 0 ;
49
- var hidden = opts . hidden || false ;
50
- var format = opts . format === false ? false : true ;
51
- var extensions = Array . isArray ( opts . extensions ) ? opts . extensions : false ;
52
- var gzip = opts . gzip === false ? false : true ;
53
- var setHeaders = opts . setHeaders ;
54
-
55
- if ( setHeaders && typeof setHeaders !== 'function' ) {
56
- throw new TypeError ( 'option setHeaders must be function' )
57
- }
36
+ async function send ( ctx , path , opts = { } ) {
37
+ assert ( ctx , 'koa context required' ) ;
38
+ assert ( path , 'pathname required' ) ;
39
+
40
+ // options
41
+ debug ( 'send "%s" %j' , path , opts ) ;
42
+ const root = opts . root ? normalize ( resolve ( opts . root ) ) : '' ;
43
+ const trailingSlash = '/' == path [ path . length - 1 ] ;
44
+ path = path . substr ( parse ( path ) . root . length ) ;
45
+ const index = opts . index ;
46
+ const maxage = opts . maxage || opts . maxAge || 0 ;
47
+ const hidden = opts . hidden || false ;
48
+ const format = opts . format === false ? false : true ;
49
+ const extensions = Array . isArray ( opts . extensions ) ? opts . extensions : false ;
50
+ const gzip = opts . gzip === false ? false : true ;
51
+ const setHeaders = opts . setHeaders ;
52
+
53
+ if ( setHeaders && typeof setHeaders !== 'function' ) {
54
+ throw new TypeError ( 'option setHeaders must be function' )
55
+ }
58
56
59
- var encoding = ctx . acceptsEncodings ( 'gzip' , 'deflate' , 'identity' ) ;
57
+ const encoding = ctx . acceptsEncodings ( 'gzip' , 'deflate' , 'identity' ) ;
60
58
61
- // normalize path
62
- path = decode ( path ) ;
59
+ // normalize path
60
+ path = decode ( path ) ;
63
61
64
- if ( - 1 == path ) return ctx . throw ( 'failed to decode' , 400 ) ;
62
+ if ( - 1 == path ) return ctx . throw ( 'failed to decode' , 400 ) ;
65
63
66
- // index file support
67
- if ( index && trailingSlash ) path += index ;
64
+ // index file support
65
+ if ( index && trailingSlash ) path += index ;
68
66
69
- path = resolvePath ( root , path ) ;
67
+ path = resolvePath ( root , path ) ;
70
68
71
- // hidden file support, ignore
72
- if ( ! hidden && isHidden ( root , path ) ) return ;
69
+ // hidden file support, ignore
70
+ if ( ! hidden && isHidden ( root , path ) ) return ;
73
71
74
- // serve gzipped file when possible
75
- if ( encoding === 'gzip' && gzip && ( yield fs . exists ( path + '.gz' ) ) ) {
76
- path = path + '.gz' ;
77
- ctx . set ( 'Content-Encoding' , 'gzip' ) ;
78
- ctx . res . removeHeader ( 'Content-Length' ) ;
79
- }
72
+ // serve gzipped file when possible
73
+ if ( encoding === 'gzip' && gzip && ( await fs . exists ( path + '.gz' ) ) ) {
74
+ path = path + '.gz' ;
75
+ ctx . set ( 'Content-Encoding' , 'gzip' ) ;
76
+ ctx . res . removeHeader ( 'Content-Length' ) ;
77
+ }
80
78
81
- if ( extensions && ! / \. .* $ / . exec ( path ) ) {
82
- var list = [ ] . concat ( extensions ) ;
83
- for ( var i = 0 ; i < list . length ; i ++ ) {
84
- var ext = list [ i ] ;
85
- if ( typeof ext !== 'string' ) {
86
- throw new TypeError ( 'option extensions must be array of strings or false' ) ;
87
- }
88
- if ( ! / ^ \. / . exec ( ext ) ) ext = '.' + ext ;
89
- if ( yield fs . exists ( path + ext ) ) {
90
- path = path + ext ;
91
- break ;
92
- }
79
+ if ( extensions && ! / \. .* $ / . exec ( path ) ) {
80
+ const list = [ ] . concat ( extensions ) ;
81
+ for ( let i = 0 ; i < list . length ; i ++ ) {
82
+ let ext = list [ i ] ;
83
+ if ( typeof ext !== 'string' ) {
84
+ throw new TypeError ( 'option extensions must be array of strings or false' ) ;
85
+ }
86
+ if ( ! / ^ \. / . exec ( ext ) ) ext = '.' + ext ;
87
+ if ( await fs . exists ( path + ext ) ) {
88
+ path = path + ext ;
89
+ break ;
93
90
}
94
91
}
92
+ }
95
93
96
- // stat
97
- try {
98
- var stats = yield fs . stat ( path ) ;
99
-
100
- // Format the path to serve static file servers
101
- // and not require a trailing slash for directories,
102
- // so that you can do both `/directory` and `/directory/`
103
- if ( stats . isDirectory ( ) ) {
104
- if ( format && index ) {
105
- path += '/' + index ;
106
- stats = yield fs . stat ( path ) ;
107
- } else {
108
- return ;
109
- }
94
+ // stat
95
+ let stats
96
+ try {
97
+ stats = await fs . stat ( path ) ;
98
+
99
+ // Format the path to serve static file servers
100
+ // and not require a trailing slash for directories,
101
+ // so that you can do both `/directory` and `/directory/`
102
+ if ( stats . isDirectory ( ) ) {
103
+ if ( format && index ) {
104
+ path += '/' + index ;
105
+ stats = await fs . stat ( path ) ;
106
+ } else {
107
+ return ;
110
108
}
111
- } catch ( err ) {
112
- var notfound = [ 'ENOENT' , 'ENAMETOOLONG' , 'ENOTDIR' ] ;
113
- if ( ~ notfound . indexOf ( err . code ) ) return ;
114
- err . status = 500 ;
115
- throw err ;
116
109
}
110
+ } catch ( err ) {
111
+ const notfound = [ 'ENOENT' , 'ENAMETOOLONG' , 'ENOTDIR' ] ;
112
+ if ( ~ notfound . indexOf ( err . code ) ) return ;
113
+ err . status = 500 ;
114
+ throw err ;
115
+ }
117
116
118
- if ( setHeaders ) setHeaders ( ctx . res , path , stats ) ;
117
+ if ( setHeaders ) setHeaders ( ctx . res , path , stats ) ;
119
118
120
- // stream
121
- ctx . set ( 'Content-Length' , stats . size ) ;
122
- if ( ! ctx . response . get ( 'Last-Modified' ) ) ctx . set ( 'Last-Modified' , stats . mtime . toUTCString ( ) ) ;
123
- if ( ! ctx . response . get ( 'Cache-Control' ) ) ctx . set ( 'Cache-Control' , 'max-age=' + ( maxage / 1000 | 0 ) ) ;
124
- ctx . type = type ( path ) ;
125
- ctx . body = fs . createReadStream ( path ) ;
119
+ // stream
120
+ ctx . set ( 'Content-Length' , stats . size ) ;
121
+ if ( ! ctx . response . get ( 'Last-Modified' ) ) ctx . set ( 'Last-Modified' , stats . mtime . toUTCString ( ) ) ;
122
+ if ( ! ctx . response . get ( 'Cache-Control' ) ) ctx . set ( 'Cache-Control' , 'max-age=' + ( maxage / 1000 | 0 ) ) ;
123
+ ctx . type = type ( path ) ;
124
+ ctx . body = fs . createReadStream ( path ) ;
126
125
127
- return path ;
128
- } ) ;
126
+ return path ;
129
127
}
130
128
131
129
/**
@@ -134,7 +132,7 @@ function send(ctx, path, opts) {
134
132
135
133
function isHidden ( root , path ) {
136
134
path = path . substr ( root . length ) . split ( sep ) ;
137
- for ( var i = 0 ; i < path . length ; i ++ ) {
135
+ for ( let i = 0 ; i < path . length ; i ++ ) {
138
136
if ( path [ i ] [ 0 ] === '.' ) return true ;
139
137
}
140
138
return false ;
0 commit comments