@srfnstack/spliffy 1.2.4 → 1.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.txt +20 -20
- package/README.md +43 -43
- package/package.json +47 -44
- package/src/content.mjs +97 -97
- package/src/decorator.mjs +209 -216
- package/src/handler.mjs +256 -254
- package/src/index.mjs +30 -30
- package/src/log.mjs +59 -59
- package/src/middleware.mjs +89 -89
- package/src/nodeModuleHandler.mjs +75 -75
- package/src/routes.mjs +205 -205
- package/src/server.mjs +141 -141
- package/src/serverConfig.mjs +100 -100
- package/src/start.mjs +25 -25
- package/src/staticHandler.mjs +74 -74
- package/src/url.mjs +24 -24
package/src/staticHandler.mjs
CHANGED
|
@@ -1,74 +1,74 @@
|
|
|
1
|
-
import fs from 'fs'
|
|
2
|
-
import etag from 'etag'
|
|
3
|
-
|
|
4
|
-
const readFile = async (fullPath) => await new Promise(
|
|
5
|
-
(resolve, reject) =>
|
|
6
|
-
fs.readFile(fullPath, (err, data) => {
|
|
7
|
-
if (err) reject(err)
|
|
8
|
-
else resolve(data)
|
|
9
|
-
}
|
|
10
|
-
)
|
|
11
|
-
)
|
|
12
|
-
|
|
13
|
-
const writeHeaders = (req, res, tag, stat, contentType, staticCacheControl) => {
|
|
14
|
-
if (req.headers['if-none-match'] === tag) {
|
|
15
|
-
res.statusCode = 304
|
|
16
|
-
return
|
|
17
|
-
}
|
|
18
|
-
res.writeHead(200, {
|
|
19
|
-
'Content-Type': contentType,
|
|
20
|
-
// content-length should not be included because transfer-encoding is chunked
|
|
21
|
-
// see https://datatracker.ietf.org/doc/html/rfc2616#section-4.4 sub section 3.
|
|
22
|
-
// Not all clients are compliant (node-fetch) and throw instead of ignoring the header as specified
|
|
23
|
-
'Cache-Control': staticCacheControl || 'max-age=600',
|
|
24
|
-
ETag: tag
|
|
25
|
-
})
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const readStat = async path => new Promise((resolve, reject) =>
|
|
29
|
-
fs.stat(path, (err, stats) =>
|
|
30
|
-
err ? reject(err) : resolve(stats)
|
|
31
|
-
))
|
|
32
|
-
|
|
33
|
-
export function createStaticHandler (fullPath, contentType, cacheStatic, staticCacheControl) {
|
|
34
|
-
const cache = {}
|
|
35
|
-
return {
|
|
36
|
-
GET: async ({ req, res }) => {
|
|
37
|
-
if (cacheStatic) {
|
|
38
|
-
if (!cache.exists || !cache.stat) {
|
|
39
|
-
cache.exists = fs.existsSync(fullPath)
|
|
40
|
-
if (cache.exists) {
|
|
41
|
-
cache.stat = await readStat(fullPath)
|
|
42
|
-
cache.content = await readFile(fullPath)
|
|
43
|
-
cache.etag = etag(cache.content)
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
if (!cache.exists) {
|
|
47
|
-
return {
|
|
48
|
-
statusCode: 404
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
writeHeaders(req, res, cache.etag, cache.stat, contentType, staticCacheControl)
|
|
52
|
-
if (res.statusCode === 304) {
|
|
53
|
-
return
|
|
54
|
-
}
|
|
55
|
-
return cache.content
|
|
56
|
-
} else {
|
|
57
|
-
if (!fs.existsSync(fullPath)) {
|
|
58
|
-
return {
|
|
59
|
-
statusCode: 404
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
const stat = await readStat(fullPath)
|
|
63
|
-
writeHeaders(req, res, etag(stat), stat, contentType, staticCacheControl)
|
|
64
|
-
if (res.statusCode === 304) {
|
|
65
|
-
return
|
|
66
|
-
}
|
|
67
|
-
if (stat.size === 0) {
|
|
68
|
-
return ''
|
|
69
|
-
}
|
|
70
|
-
return fs.createReadStream(fullPath)
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import etag from 'etag'
|
|
3
|
+
|
|
4
|
+
const readFile = async (fullPath) => await new Promise(
|
|
5
|
+
(resolve, reject) =>
|
|
6
|
+
fs.readFile(fullPath, (err, data) => {
|
|
7
|
+
if (err) reject(err)
|
|
8
|
+
else resolve(data)
|
|
9
|
+
}
|
|
10
|
+
)
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
const writeHeaders = (req, res, tag, stat, contentType, staticCacheControl) => {
|
|
14
|
+
if (req.headers['if-none-match'] === tag) {
|
|
15
|
+
res.statusCode = 304
|
|
16
|
+
return
|
|
17
|
+
}
|
|
18
|
+
res.writeHead(200, {
|
|
19
|
+
'Content-Type': contentType,
|
|
20
|
+
// content-length should not be included because transfer-encoding is chunked
|
|
21
|
+
// see https://datatracker.ietf.org/doc/html/rfc2616#section-4.4 sub section 3.
|
|
22
|
+
// Not all clients are compliant (node-fetch) and throw instead of ignoring the header as specified
|
|
23
|
+
'Cache-Control': staticCacheControl || 'max-age=600',
|
|
24
|
+
ETag: tag
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const readStat = async path => new Promise((resolve, reject) =>
|
|
29
|
+
fs.stat(path, (err, stats) =>
|
|
30
|
+
err ? reject(err) : resolve(stats)
|
|
31
|
+
))
|
|
32
|
+
|
|
33
|
+
export function createStaticHandler (fullPath, contentType, cacheStatic, staticCacheControl) {
|
|
34
|
+
const cache = {}
|
|
35
|
+
return {
|
|
36
|
+
GET: async ({ req, res }) => {
|
|
37
|
+
if (cacheStatic) {
|
|
38
|
+
if (!cache.exists || !cache.stat) {
|
|
39
|
+
cache.exists = fs.existsSync(fullPath)
|
|
40
|
+
if (cache.exists) {
|
|
41
|
+
cache.stat = await readStat(fullPath)
|
|
42
|
+
cache.content = await readFile(fullPath)
|
|
43
|
+
cache.etag = etag(cache.content)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (!cache.exists) {
|
|
47
|
+
return {
|
|
48
|
+
statusCode: 404
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
writeHeaders(req, res, cache.etag, cache.stat, contentType, staticCacheControl)
|
|
52
|
+
if (res.statusCode === 304) {
|
|
53
|
+
return
|
|
54
|
+
}
|
|
55
|
+
return cache.content
|
|
56
|
+
} else {
|
|
57
|
+
if (!fs.existsSync(fullPath)) {
|
|
58
|
+
return {
|
|
59
|
+
statusCode: 404
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const stat = await readStat(fullPath)
|
|
63
|
+
writeHeaders(req, res, etag(stat), stat, contentType, staticCacheControl)
|
|
64
|
+
if (res.statusCode === 304) {
|
|
65
|
+
return
|
|
66
|
+
}
|
|
67
|
+
if (stat.size === 0) {
|
|
68
|
+
return ''
|
|
69
|
+
}
|
|
70
|
+
return fs.createReadStream(fullPath)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
package/src/url.mjs
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
export function parseQuery (query, decodeQueryParams) {
|
|
2
|
-
const parsed = {}
|
|
3
|
-
if (query) {
|
|
4
|
-
if (decodeQueryParams) {
|
|
5
|
-
query = decodeURIComponent(query.replace(/\+/g, '%20'))
|
|
6
|
-
}
|
|
7
|
-
for (const param of query.split('&')) {
|
|
8
|
-
const eq = param.indexOf('=')
|
|
9
|
-
setMultiValueKey(parsed, param.substr(0, eq), param.substr(eq + 1))
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
return parsed
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function setMultiValueKey (obj, key, value) {
|
|
16
|
-
if (key in obj) {
|
|
17
|
-
if (!Array.isArray(obj[key])) {
|
|
18
|
-
obj[key] = [obj[key]]
|
|
19
|
-
}
|
|
20
|
-
obj[key].push(value)
|
|
21
|
-
} else {
|
|
22
|
-
obj[key] = value
|
|
23
|
-
}
|
|
24
|
-
}
|
|
1
|
+
export function parseQuery (query, decodeQueryParams) {
|
|
2
|
+
const parsed = {}
|
|
3
|
+
if (query) {
|
|
4
|
+
if (decodeQueryParams) {
|
|
5
|
+
query = decodeURIComponent(query.replace(/\+/g, '%20'))
|
|
6
|
+
}
|
|
7
|
+
for (const param of query.split('&')) {
|
|
8
|
+
const eq = param.indexOf('=')
|
|
9
|
+
setMultiValueKey(parsed, param.substr(0, eq), param.substr(eq + 1))
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return parsed
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function setMultiValueKey (obj, key, value) {
|
|
16
|
+
if (key in obj) {
|
|
17
|
+
if (!Array.isArray(obj[key])) {
|
|
18
|
+
obj[key] = [obj[key]]
|
|
19
|
+
}
|
|
20
|
+
obj[key].push(value)
|
|
21
|
+
} else {
|
|
22
|
+
obj[key] = value
|
|
23
|
+
}
|
|
24
|
+
}
|