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