-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
158 lines (134 loc) · 4.24 KB
/
index.js
File metadata and controls
158 lines (134 loc) · 4.24 KB
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import https from 'node:https'
import http from 'node:http'
import { inspect } from 'node:util'
import { EventEmitter } from 'node:events'
import { readFileSync } from 'node:fs'
import express from 'express'
import morgan from 'morgan'
import responseTime from 'response-time'
import cookieParser from 'cookie-parser'
import compression from 'compression'
import flash from 'connect-flash'
import cors from 'cors'
import hpp from 'hpp'
import helmet from 'helmet'
import helmetCsp from 'helmet-csp'
import { log, warn, error, Verbose } from './services.js'
import conf, { revealConf } from './conf.js'
import auth from './middleware/auth.js'
import restAPI from './rest-api.js'
import routes from './routes/index.js'
import session from './middleware/session.js'
import { sendError } from './middleware/errors.js'
// Connect to MongoDB through Mongoose driver
import './mongo.js'
// Connect to ArangoDB
import './arango.js'
const verbose = Verbose('sd:index'); verbose('')
process.env.NODE_TLS_REJECT_UNAUTHORIZED = conf.node.tlsRejectUnauthorized
warn('Set NODE_TLS_REJECT_UNAUTHORIZED:',
process.env.NODE_TLS_REJECT_UNAUTHORIZED)
EventEmitter.defaultMaxListeners = conf.node.defaultMaxListeners
warn('Set EventEmitter.defaultMaxListeners:', EventEmitter.defaultMaxListeners)
log('public conf:', inspect(revealConf(), { colors: true, depth: null }))
// Create express application
export const app = express()
// Server
export let server
if (conf.ssl.enable) {
server = https.createServer({
key: readFileSync(conf.ssl.keyFile),
cert: readFileSync(conf.ssl.certFile)
}, app)
} else {
server = http.createServer(app)
}
// Express middleware configuration
app.use(compression()) // gzip compression
app.use(cookieParser()) // for parsing cookie
app.use(express.json({ limit: '100kb' })) // for parsing application/json
app.use(express.urlencoded({ extended: true, limit: '100kb' })) // for parsing application/x-www-form-urlencoded
app.use(express.text({ limit: '100kb' }))
app.use(express.raw({ limit: '100kb' }))
process.env.NODE_ENV !== 'test' && app.use(morgan('tiny')) // for logging HTTP-requests
app.use(flash()) // to support passport.js errors through flash
// Security
if (conf.security.hpp) {
app.use(hpp()) // Prevent HTTP Parameter Pollution
}
if (conf.security.helmet) {
app.use(helmet()) // Use appropriate security headers
}
if (conf.security.csp) {
app.use(helmetCsp({
directives: {
defaultSrc: ["'self'"], // default value for all directives that are absent
scriptSrc: ["'self'"], // helps prevent XSS attacks
objectSrc: ["'self'"],
imgSrc: ["'self'"],
styleSrc: ["'self'"],
frameAncestors: ["'none'"], // helps prevent Clickjacking attacks
upgradeInsecureRequests: [],
},
reportOnly: false,
})) // Content Security Policy
}
if (conf.security.trustProxy) {
// HTTP(s) headers
app.set('trust proxy', 1) // trust 1st proxy
}
if (!conf.security.powered) {
app.disable('x-powered-by') // that's more secure
}
if (conf.cors.enabled) {
app.use(cors({
origin: (origin, callback) => {
if (!origin || conf.cors.whitelist.includes(origin)) {
return callback(null, true)
}
},
credentials: true,
methods: ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE'],
}))
}
app.use(responseTime()) // X-Response-Time header
// Session
app.use(session)
// Authentication
auth(app)
// Routes
app.use('/', routes)
// API
restAPI(app)
// Errors
app.use(sendError)
process.stdin.resume()
process.on('warning', (warning) => {
warn('warning:', warning)
})
process.on('unhandledRejection', (reason, promise) => {
error('Unhandled Rejection at:', promise, 'reason:', reason)
})
process.on('uncaughtException', (err) => {
error('uncaughtException:', err)
})
process.on('beforeExit', (code) => {
log('Process beforeExit event with code: ', code)
})
process.on('exit', (code) => {
log(`Exit with code: ${code}`)
})
const handleSignal = async (signal) => {
log(`Received ${signal}`)
process.exit()
}
process.on('SIGINT', handleSignal)
process.on('SIGTERM', handleSignal)
// Start!
server.listen(conf.port, () => {
log('Selfdev-API server is listening on port', conf.port)
verbose(' ')
verbose(` http${conf.ssl.enable ? 's' : ''}://localhost:${conf.port}`)
verbose(' ')
})
export default app