forked from fastify/fastify-static
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
134 lines (110 loc) · 3.23 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
'use strict'
const path = require('path')
const statSync = require('fs').statSync
const { PassThrough } = require('readable-stream')
const send = require('send')
const fp = require('fastify-plugin')
function fastifyStatic (fastify, opts, next) {
const error = checkRootPathForErrors(opts.root)
if (error !== undefined) return next(error)
const setHeaders = opts.setHeaders
if (setHeaders !== undefined && typeof setHeaders !== 'function') {
return next(new TypeError('The `setHeaders` option must be a function'))
}
const sendOptions = {
root: opts.root,
acceptRanges: opts.acceptRanges,
cacheControl: opts.cacheControl,
dotfiles: opts.dotfiles,
etag: opts.etag,
extensions: opts.extensions,
immutable: opts.immutable,
index: opts.index,
lastModified: opts.lastModified,
maxAge: opts.maxAge
}
function pumpSendToReply (request, reply, pathname) {
const stream = send(request.raw, pathname, sendOptions)
var resolvedFilename
stream.on('file', function (file) {
resolvedFilename = file
})
const wrap = new PassThrough({
flush (cb) {
this.finished = true
if (reply.res.statusCode === 304) {
reply.send('')
}
cb()
}
})
wrap.getHeader = reply.getHeader.bind(reply)
wrap.setHeader = reply.header.bind(reply)
wrap.socket = request.raw.socket
wrap.finished = false
Object.defineProperty(wrap, 'filename', {
get () {
return resolvedFilename
}
})
Object.defineProperty(wrap, 'statusCode', {
get () {
return reply.res.statusCode
},
set (code) {
reply.code(code)
}
})
wrap.on('pipe', function () {
reply.send(wrap)
})
if (setHeaders !== undefined) {
stream.on('headers', setHeaders)
}
stream.on('error', function (err) {
if (err) {
reply.send(err)
}
})
// we cannot use pump, because send error
// handling is not compatible
stream.pipe(wrap)
}
if (opts.prefix === undefined) opts.prefix = '/'
const prefix = opts.prefix[opts.prefix.length - 1] === '/' ? opts.prefix : (opts.prefix + '/')
// Set the schema hide property if defined in opts or true by default
const schema = { schema: { hide: typeof opts.schemaHide !== 'undefined' ? opts.schemaHide : true } }
fastify.get(prefix + '*', schema, function (req, reply) {
pumpSendToReply(req, reply, '/' + req.params['*'])
})
if (opts.decorateReply !== false) {
fastify.decorateReply('sendFile', function (filePath) {
pumpSendToReply(this.request, this, filePath)
})
}
next()
}
function checkRootPathForErrors (rootPath) {
if (rootPath === undefined) {
return new Error('"root" option is required')
}
if (typeof rootPath !== 'string') {
return new Error('"root" option must be a string')
}
if (path.isAbsolute(rootPath) === false) {
return new Error('"root" option must be an absolute path')
}
var pathStat
try {
pathStat = statSync(rootPath)
} catch (e) {
return e
}
if (pathStat.isDirectory() === false) {
return new Error('"root" option must point to a directory')
}
}
module.exports = fp(fastifyStatic, {
fastify: '>= 1.2.0',
name: 'fastify-static'
})