@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/src/server.mjs CHANGED
@@ -1,141 +1,141 @@
1
- import log from './log.mjs'
2
- import { getNodeModuleRoutes } from './nodeModuleHandler.mjs'
3
- import uws from 'uWebSockets.js'
4
- import { createHandler, createNotFoundHandler } from './handler.mjs'
5
- import { findRoutes } from './routes.mjs'
6
- import path from 'path'
7
- import fs from 'fs'
8
-
9
- const state = {
10
- routes: {},
11
- initialized: false
12
- }
13
- const appMethods = {
14
- GET: 'get',
15
- POST: 'post',
16
- PUT: 'put',
17
- PATCH: 'patch',
18
- DELETE: 'del',
19
- OPTIONS: 'options',
20
- HEAD: 'head',
21
- CONNECT: 'connect',
22
- TRACE: 'trace',
23
- WEBSOCKET: 'ws'
24
- }
25
- const optionsHandler = (config, middleware, methods) => {
26
- return createHandler(() => ( {
27
- headers: {
28
- allow: methods
29
- },
30
- statusCode: 204
31
- } ),
32
- middleware,
33
- [],
34
- config
35
- )
36
- }
37
-
38
- const startHttpRedirect = (host, port) => {
39
- // redirect http to https
40
- uws.App().any('/*',
41
- (req, res) => {
42
- try {
43
- res.writeHead(301, { Location: `https://${req.headers.get('host')}:${port}${req.url}` })
44
- res.end()
45
- } catch (e) {
46
- log.error(`Failed to handle http request on port ${port}`, req.url, e)
47
- }
48
- }
49
- ).listen(host || '0.0.0.0', port, (token) => {
50
- if (token) {
51
- log.gne(`Http redirect server initialized at ${new Date().toISOString()} and listening on port ${port}`)
52
- } else {
53
- throw new Error(`Failed to start server on port ${port}`)
54
- }
55
- })
56
- }
57
-
58
- const getHttpsApp = (key, cert) => {
59
- const keyPath = path.resolve(key)
60
- const certPath = path.resolve(cert)
61
- if (!fs.existsSync(keyPath)) throw new Error(`Can't find https key file: ${keyPath}`)
62
- if (!fs.existsSync(certPath)) throw new Error(`Can't find https cert file: ${keyPath}`)
63
- return uws.App({
64
- key_file_name: keyPath,
65
- cert_file_name: certPath
66
- })
67
- }
68
-
69
- export async function startServer (config) {
70
- if (!state.initialized) {
71
- state.initialized = true
72
- const routes = [...getNodeModuleRoutes(config), ...( await findRoutes(config) )]
73
- let app, port
74
- if (config.httpsKeyFile) {
75
- app = getHttpsApp(config.secure)
76
- port = config.secure.port || 14420
77
- startHttpRedirect(config.host, config.port || 10420)
78
- } else {
79
- app = uws.App()
80
- port = config.port || 10420
81
- }
82
-
83
- for (const route of routes) {
84
- if (config.printRoutes) {
85
- log.info('Configured Route: ', route)
86
- }
87
- const routePattern = `^${route.urlPath.replace(/:[^/]+/g, '[^/]+').replace(/\*/g, '.*')}$`
88
- if (config.notFoundRoute && config.notFoundRoute.match(routePattern)) {
89
- config.notFoundRouteHandler = route
90
- route.statusCodeOverride = 404
91
- }
92
- if (config.defaultRoute && config.defaultRoute.match(routePattern)) {
93
- config.defaultRouteHandler = route
94
- }
95
- let hadSlash = false
96
- if (route.urlPath.endsWith('/') && route.urlPath.length > 1) {
97
- hadSlash = true
98
- route.urlPath = route.urlPath.substring(0, route.urlPath.length - 1)
99
- }
100
- for (const method in route.handlers) {
101
- let theHandler = null
102
- if (method === 'WEBSOCKET') {
103
- theHandler = route.handlers[method]
104
- } else {
105
- theHandler = createHandler(route.handlers[method], route.middleware, route.pathParameters, config)
106
- }
107
- app[appMethods[method]](route.urlPath, theHandler)
108
- if (hadSlash && config.serveRoutesWithSlash) {
109
- app[appMethods[method]](route.urlPath + '/', theHandler)
110
- }
111
- if (route.urlPath.endsWith('/*')) {
112
- app[appMethods[method]](route.urlPath.substr(0, route.urlPath.length - 2), theHandler)
113
- }
114
- }
115
- if (config.autoOptions && !route.handlers.OPTIONS) {
116
- const theHandler = optionsHandler(config, route.middleware, Object.keys(route.handlers).join(', '))
117
- app.options(route.urlPath, theHandler)
118
- if (hadSlash && config.serveRoutesWithSlash) {
119
- app.options(route.urlPath + '/', theHandler)
120
- }
121
- }
122
- }
123
-
124
- if (config.notFoundRoute && !config.notFoundRouteHandler) {
125
- log.warn('No route matched not found route: ' + config.notFoundRoute)
126
- }
127
- if (config.defaultRoute && !config.defaultRouteHandler) {
128
- log.warn('No route matched default route: ' + config.notFoundRoute)
129
- }
130
-
131
- app.any('/*', createNotFoundHandler(config))
132
- app.listen(config.host || '::', config.port, (token) => {
133
- if (token) {
134
- log.gne(`Server initialized at ${new Date().toISOString()} and listening on port ${port}`)
135
- } else {
136
- throw new Error(`Failed to start server on port ${port}`)
137
- }
138
- })
139
- return app
140
- }
141
- }
1
+ import log from './log.mjs'
2
+ import { getNodeModuleRoutes } from './nodeModuleHandler.mjs'
3
+ import uws from 'uWebSockets.js'
4
+ import { createHandler, createNotFoundHandler } from './handler.mjs'
5
+ import { findRoutes } from './routes.mjs'
6
+ import path from 'path'
7
+ import fs from 'fs'
8
+
9
+ const state = {
10
+ routes: {},
11
+ initialized: false
12
+ }
13
+ const appMethods = {
14
+ GET: 'get',
15
+ POST: 'post',
16
+ PUT: 'put',
17
+ PATCH: 'patch',
18
+ DELETE: 'del',
19
+ OPTIONS: 'options',
20
+ HEAD: 'head',
21
+ CONNECT: 'connect',
22
+ TRACE: 'trace',
23
+ WEBSOCKET: 'ws'
24
+ }
25
+ const optionsHandler = (config, middleware, methods) => {
26
+ return createHandler(() => ({
27
+ headers: {
28
+ allow: methods
29
+ },
30
+ statusCode: 204
31
+ }),
32
+ middleware,
33
+ [],
34
+ config
35
+ )
36
+ }
37
+
38
+ const startHttpRedirect = (host, port) => {
39
+ // redirect http to https
40
+ uws.App().any('/*',
41
+ (req, res) => {
42
+ try {
43
+ res.writeHead(301, { Location: `https://${req.headers.get('host')}:${port}${req.url}` })
44
+ res.end()
45
+ } catch (e) {
46
+ log.error(`Failed to handle http request on port ${port}`, req.url, e)
47
+ }
48
+ }
49
+ ).listen(host || '0.0.0.0', port, (token) => {
50
+ if (token) {
51
+ log.gne(`Http redirect server initialized at ${new Date().toISOString()} and listening on port ${port}`)
52
+ } else {
53
+ throw new Error(`Failed to start server on port ${port}`)
54
+ }
55
+ })
56
+ }
57
+
58
+ const getHttpsApp = (key, cert) => {
59
+ const keyPath = path.resolve(key)
60
+ const certPath = path.resolve(cert)
61
+ if (!fs.existsSync(keyPath)) throw new Error(`Can't find https key file: ${keyPath}`)
62
+ if (!fs.existsSync(certPath)) throw new Error(`Can't find https cert file: ${keyPath}`)
63
+ return uws.App({
64
+ key_file_name: keyPath,
65
+ cert_file_name: certPath
66
+ })
67
+ }
68
+
69
+ export async function startServer (config) {
70
+ if (!state.initialized) {
71
+ state.initialized = true
72
+ const routes = [...getNodeModuleRoutes(config), ...(await findRoutes(config))]
73
+ let app, port
74
+ if (config.httpsKeyFile) {
75
+ app = getHttpsApp(config.secure)
76
+ port = config.secure.port || 14420
77
+ startHttpRedirect(config.host, config.port || 10420)
78
+ } else {
79
+ app = uws.App()
80
+ port = config.port || 10420
81
+ }
82
+
83
+ for (const route of routes) {
84
+ if (config.printRoutes) {
85
+ log.info('Configured Route: ', route)
86
+ }
87
+ const routePattern = `^${route.urlPath.replace(/:[^/]+/g, '[^/]+').replace(/\*/g, '.*')}$`
88
+ if (config.notFoundRoute && config.notFoundRoute.match(routePattern)) {
89
+ config.notFoundRouteHandler = route
90
+ route.statusCodeOverride = 404
91
+ }
92
+ if (config.defaultRoute && config.defaultRoute.match(routePattern)) {
93
+ config.defaultRouteHandler = route
94
+ }
95
+ let hadSlash = false
96
+ if (route.urlPath.endsWith('/') && route.urlPath.length > 1) {
97
+ hadSlash = true
98
+ route.urlPath = route.urlPath.substring(0, route.urlPath.length - 1)
99
+ }
100
+ for (const method in route.handlers) {
101
+ let theHandler = null
102
+ if (method === 'WEBSOCKET') {
103
+ theHandler = route.handlers[method]
104
+ } else {
105
+ theHandler = createHandler(route.handlers[method], route.middleware, route.pathParameters, config)
106
+ }
107
+ app[appMethods[method]](route.urlPath, theHandler)
108
+ if (hadSlash && config.serveRoutesWithSlash) {
109
+ app[appMethods[method]](route.urlPath + '/', theHandler)
110
+ }
111
+ if (route.urlPath.endsWith('/*')) {
112
+ app[appMethods[method]](route.urlPath.substr(0, route.urlPath.length - 2), theHandler)
113
+ }
114
+ }
115
+ if (config.autoOptions && !route.handlers.OPTIONS) {
116
+ const theHandler = optionsHandler(config, route.middleware, Object.keys(route.handlers).join(', '))
117
+ app.options(route.urlPath, theHandler)
118
+ if (hadSlash && config.serveRoutesWithSlash) {
119
+ app.options(route.urlPath + '/', theHandler)
120
+ }
121
+ }
122
+ }
123
+
124
+ if (config.notFoundRoute && !config.notFoundRouteHandler) {
125
+ log.warn('No route matched not found route: ' + config.notFoundRoute)
126
+ }
127
+ if (config.defaultRoute && !config.defaultRouteHandler) {
128
+ log.warn('No route matched default route: ' + config.notFoundRoute)
129
+ }
130
+
131
+ app.any('/*', createNotFoundHandler(config))
132
+ app.listen(config.host || '::', config.port, (token) => {
133
+ if (token) {
134
+ log.gne(`Server initialized at ${new Date().toISOString()} and listening on port ${port}`)
135
+ } else {
136
+ throw new Error(`Failed to start server on port ${port}`)
137
+ }
138
+ })
139
+ return app
140
+ }
141
+ }
@@ -1,100 +1,100 @@
1
- import { initContentHandlers } from './content.mjs'
2
- import { validateMiddleware } from './middleware.mjs'
3
- import log from './log.mjs'
4
-
5
- const defaultHeaders = {
6
- acceptsDefault: '*/*',
7
- defaultContentType: '*/*'
8
- }
9
- // this is mainly for performance reasons
10
- const nonsense = [
11
- 'I\'m toasted',
12
- 'that hurt',
13
- 'your interwebs!',
14
- 'I see a light...',
15
- 'totally zooted',
16
- 'misplaced my bits',
17
- 'maybe reboot?',
18
- 'what was I doing again?',
19
- 'my cabbages!!!',
20
- 'Leeerrroooyyy Jeeenkins',
21
- 'at least I have chicken'
22
- ]
23
-
24
- export const randomNonsense = () => `[OH NO, ${nonsense[Math.floor(Math.random() * nonsense.length)]}]`
25
-
26
- export async function initConfig (userConfig) {
27
- const config = Object.assign({}, userConfig)
28
-
29
- if (!('decodePathParameters' in config)) {
30
- config.decodePathParameters = false
31
- }
32
-
33
- if (!('decodeQueryParams' in config)) {
34
- config.decodeQueryParams = false
35
- }
36
-
37
- if (!('extendIncomingMessage' in config)) {
38
- config.extendIncomingMessage = false
39
- }
40
-
41
- if (!('parseCookie' in config)) {
42
- config.parseCookie = false
43
- }
44
-
45
- if (!('writeDateHeader' in config)) {
46
- config.writeDateHeader = false
47
- }
48
-
49
- config.acceptsDefault = config.acceptsDefault || defaultHeaders.acceptsDefault
50
- config.defaultContentType = config.defaultContentType || defaultHeaders.defaultContentType
51
-
52
- config.contentHandlers = initContentHandlers(config.contentHandlers || {})
53
- config.resolveWithoutExtension = config.resolveWithoutExtension || []
54
- if (!Array.isArray(config.resolveWithoutExtension)) {
55
- config.resolveWithoutExtension = [config.resolveWithoutExtension]
56
- }
57
-
58
- if (config.resolveWithoutExtension.indexOf('.htm') === -1) {
59
- config.resolveWithoutExtension.push('.htm')
60
- }
61
- if (config.resolveWithoutExtension.indexOf('.html') === -1) {
62
- config.resolveWithoutExtension.push('.html')
63
- }
64
-
65
- if (config.middleware) {
66
- validateMiddleware(config.middleware)
67
- }
68
-
69
- if (!('logAccess' in config)) {
70
- config.logAccess = false
71
- }
72
- if ('logLevel' in config) {
73
- log.setLogLevel(config.logLevel)
74
- }
75
- if (!('ignoreFilesMatching' in config)) {
76
- config.ignoreFilesMatching = []
77
- } else if (!Array.isArray(config.ignoreFilesMatching)) {
78
- config.ignoreFilesMatching = [config.ignoreFilesMatching]
79
- }
80
- if (!('allowTestFileRoutes' in config)) {
81
- config.allowTestFileRoutes = false
82
- }
83
- config.port = config.port || 10420
84
- if (!config.httpPort) {
85
- config.httpPort = config.port - 1
86
- }
87
-
88
- if (!('autoOptions' in config)) {
89
- config.autoOptions = false
90
- }
91
-
92
- if (config.logger) {
93
- log.setLogger(config.logger)
94
- }
95
-
96
- if ((config.httpsKeyFile && !config.httpsCertFile) || (!config.httpsKeyFile && config.httpsCertFile)) {
97
- throw new Error('You must provide both httpsKeyFile and httpsCertFile')
98
- }
99
- return config
100
- }
1
+ import { initContentHandlers } from './content.mjs'
2
+ import { validateMiddleware } from './middleware.mjs'
3
+ import log from './log.mjs'
4
+
5
+ const defaultHeaders = {
6
+ acceptsDefault: '*/*',
7
+ defaultContentType: '*/*'
8
+ }
9
+ // this is mainly for performance reasons
10
+ const nonsense = [
11
+ 'I\'m toasted',
12
+ 'that hurt',
13
+ 'your interwebs!',
14
+ 'I see a light...',
15
+ 'totally zooted',
16
+ 'misplaced my bits',
17
+ 'maybe reboot?',
18
+ 'what was I doing again?',
19
+ 'my cabbages!!!',
20
+ 'Leeerrroooyyy Jeeenkins',
21
+ 'at least I have chicken'
22
+ ]
23
+
24
+ export const randomNonsense = () => `[OH NO, ${nonsense[Math.floor(Math.random() * nonsense.length)]}]`
25
+
26
+ export async function initConfig (userConfig) {
27
+ const config = Object.assign({}, userConfig)
28
+
29
+ if (!('decodePathParameters' in config)) {
30
+ config.decodePathParameters = false
31
+ }
32
+
33
+ if (!('decodeQueryParams' in config)) {
34
+ config.decodeQueryParams = false
35
+ }
36
+
37
+ if (!('extendIncomingMessage' in config)) {
38
+ config.extendIncomingMessage = false
39
+ }
40
+
41
+ if (!('parseCookie' in config)) {
42
+ config.parseCookie = false
43
+ }
44
+
45
+ if (!('writeDateHeader' in config)) {
46
+ config.writeDateHeader = false
47
+ }
48
+
49
+ config.acceptsDefault = config.acceptsDefault || defaultHeaders.acceptsDefault
50
+ config.defaultContentType = config.defaultContentType || defaultHeaders.defaultContentType
51
+
52
+ config.contentHandlers = initContentHandlers(config.contentHandlers || {})
53
+ config.resolveWithoutExtension = config.resolveWithoutExtension || []
54
+ if (!Array.isArray(config.resolveWithoutExtension)) {
55
+ config.resolveWithoutExtension = [config.resolveWithoutExtension]
56
+ }
57
+
58
+ if (config.resolveWithoutExtension.indexOf('.htm') === -1) {
59
+ config.resolveWithoutExtension.push('.htm')
60
+ }
61
+ if (config.resolveWithoutExtension.indexOf('.html') === -1) {
62
+ config.resolveWithoutExtension.push('.html')
63
+ }
64
+
65
+ if (config.middleware) {
66
+ validateMiddleware(config.middleware)
67
+ }
68
+
69
+ if (!('logAccess' in config)) {
70
+ config.logAccess = false
71
+ }
72
+ if ('logLevel' in config) {
73
+ log.setLogLevel(config.logLevel)
74
+ }
75
+ if (!('ignoreFilesMatching' in config)) {
76
+ config.ignoreFilesMatching = []
77
+ } else if (!Array.isArray(config.ignoreFilesMatching)) {
78
+ config.ignoreFilesMatching = [config.ignoreFilesMatching]
79
+ }
80
+ if (!('allowTestFileRoutes' in config)) {
81
+ config.allowTestFileRoutes = false
82
+ }
83
+ config.port = config.port || 10420
84
+ if (!config.httpPort) {
85
+ config.httpPort = config.port - 1
86
+ }
87
+
88
+ if (!('autoOptions' in config)) {
89
+ config.autoOptions = false
90
+ }
91
+
92
+ if (config.logger) {
93
+ log.setLogger(config.logger)
94
+ }
95
+
96
+ if ((config.httpsKeyFile && !config.httpsCertFile) || (!config.httpsKeyFile && config.httpsCertFile)) {
97
+ throw new Error('You must provide both httpsKeyFile and httpsCertFile')
98
+ }
99
+ return config
100
+ }
package/src/start.mjs CHANGED
@@ -1,25 +1,25 @@
1
- import { initConfig, randomNonsense } from './serverConfig.mjs'
2
- import log from './log.mjs'
3
- import { startServer } from './server.mjs'
4
-
5
- export default async function (config) {
6
- if (!config || !config.routeDir) {
7
- throw new Error('You must supply a config object with at least a routeDir property. routeDir should be a full path.')
8
- }
9
- process
10
- .on('unhandledRejection', (reason, p) => {
11
- log.error(randomNonsense(), reason, 'Unhandled Rejection at Promise', p)
12
- })
13
- .on('uncaughtException', (err, origin) => {
14
- log.error(randomNonsense(), `Caught unhandled exception: ${err}\n` +
15
- `Exception origin: ${origin}`)
16
- })
17
-
18
- log.gne('Starting Spliffy!')
19
- const configWithDefaults = await initConfig(config)
20
- return startServer(configWithDefaults).catch(e => {
21
- log.error(randomNonsense(), 'Exception during startup:', e)
22
- // Spliffy threw an exception, or a route handler failed to load.
23
- process.exit(420)
24
- })
25
- }
1
+ import { initConfig, randomNonsense } from './serverConfig.mjs'
2
+ import log from './log.mjs'
3
+ import { startServer } from './server.mjs'
4
+
5
+ export default async function (config) {
6
+ if (!config || !config.routeDir) {
7
+ throw new Error('You must supply a config object with at least a routeDir property. routeDir should be a full path.')
8
+ }
9
+ process
10
+ .on('unhandledRejection', (reason, p) => {
11
+ log.error(randomNonsense(), reason, 'Unhandled Rejection at Promise', p)
12
+ })
13
+ .on('uncaughtException', (err, origin) => {
14
+ log.error(randomNonsense(), `Caught unhandled exception: ${err}\n` +
15
+ `Exception origin: ${origin}`)
16
+ })
17
+
18
+ log.gne('Starting Spliffy!')
19
+ const configWithDefaults = await initConfig(config)
20
+ return startServer(configWithDefaults).catch(e => {
21
+ log.error(randomNonsense(), 'Exception during startup:', e)
22
+ // Spliffy threw an exception, or a route handler failed to load.
23
+ process.exit(420)
24
+ })
25
+ }