Skip to content

Commit d2b0080

Browse files
committed
move app.js to lib/
update
1 parent 532febd commit d2b0080

File tree

11 files changed

+362
-338
lines changed

11 files changed

+362
-338
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,4 @@ public/uploads/*
3232
.vscode/settings.json
3333

3434
/dist
35+
lib/**/*.js

app.js

Lines changed: 1 addition & 329 deletions
Original file line numberDiff line numberDiff line change
@@ -1,331 +1,3 @@
11
'use strict'
2-
// app
3-
// external modules
4-
var express = require('express')
52

6-
var ejs = require('ejs')
7-
var passport = require('passport')
8-
var methodOverride = require('method-override')
9-
var cookieParser = require('cookie-parser')
10-
var session = require('express-session')
11-
var SequelizeStore = require('connect-session-sequelize')(session.Store)
12-
var fs = require('fs')
13-
var path = require('path')
14-
15-
var morgan = require('morgan')
16-
var passportSocketIo = require('passport.socketio')
17-
var helmet = require('helmet')
18-
var i18n = require('i18n')
19-
var flash = require('connect-flash')
20-
var apiMetrics = require('prometheus-api-metrics')
21-
22-
// core
23-
var config = require('./dist/config')
24-
var logger = require('./dist/logger')
25-
var response = require('./dist/response')
26-
var models = require('./dist/models')
27-
var csp = require('./dist/csp')
28-
const { Environment } = require('./dist/config/enum')
29-
30-
const { versionCheckMiddleware, checkVersion } = require('./dist/web/middleware/checkVersion')
31-
32-
function createHttpServer () {
33-
if (config.useSSL) {
34-
const ca = (function () {
35-
let i, len
36-
const results = []
37-
for (i = 0, len = config.sslCAPath.length; i < len; i++) {
38-
results.push(fs.readFileSync(config.sslCAPath[i], 'utf8'))
39-
}
40-
return results
41-
})()
42-
const options = {
43-
key: fs.readFileSync(config.sslKeyPath, 'utf8'),
44-
cert: fs.readFileSync(config.sslCertPath, 'utf8'),
45-
ca: ca,
46-
dhparam: fs.readFileSync(config.dhParamPath, 'utf8'),
47-
requestCert: false,
48-
rejectUnauthorized: false
49-
}
50-
return require('https').createServer(options, app)
51-
} else {
52-
return require('http').createServer(app)
53-
}
54-
}
55-
56-
// server setup
57-
var app = express()
58-
var server = createHttpServer()
59-
60-
// API and process monitoring with Prometheus for Node.js micro-service
61-
app.use(apiMetrics({
62-
metricsPath: '/metrics/router',
63-
excludeRoutes: ['/metrics/codimd']
64-
}))
65-
66-
// logger
67-
app.use(morgan('combined', {
68-
stream: logger.stream
69-
}))
70-
71-
// socket io
72-
var io = require('socket.io')(server)
73-
io.engine.ws = new (require('ws').Server)({
74-
noServer: true,
75-
perMessageDeflate: false
76-
})
77-
78-
// others
79-
var realtime = require('./dist/realtime/realtime.js')
80-
81-
// assign socket io to realtime
82-
realtime.io = io
83-
84-
// methodOverride
85-
app.use(methodOverride('_method'))
86-
87-
// session store
88-
var sessionStore = new SequelizeStore({
89-
db: models.sequelize
90-
})
91-
92-
// use hsts to tell https users stick to this
93-
if (config.hsts.enable) {
94-
app.use(helmet.hsts({
95-
maxAge: config.hsts.maxAgeSeconds,
96-
includeSubdomains: config.hsts.includeSubdomains,
97-
preload: config.hsts.preload
98-
}))
99-
} else if (config.useSSL) {
100-
logger.info('Consider enabling HSTS for extra security:')
101-
logger.info('https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security')
102-
}
103-
104-
// Add referrer policy to improve privacy
105-
app.use(
106-
helmet.referrerPolicy({
107-
policy: 'same-origin'
108-
})
109-
)
110-
111-
// Generate a random nonce per request, for CSP with inline scripts
112-
app.use(csp.addNonceToLocals)
113-
114-
// use Content-Security-Policy to limit XSS, dangerous plugins, etc.
115-
// https://helmetjs.github.io/docs/csp/
116-
if (config.csp.enable) {
117-
app.use(helmet.contentSecurityPolicy({
118-
directives: csp.computeDirectives()
119-
}))
120-
} else {
121-
logger.info('Content-Security-Policy is disabled. This may be a security risk.')
122-
}
123-
124-
i18n.configure({
125-
locales: ['en', 'zh-CN', 'zh-TW', 'fr', 'de', 'ja', 'es', 'ca', 'el', 'pt', 'it', 'tr', 'ru', 'nl', 'hr', 'pl', 'uk', 'hi', 'sv', 'eo', 'da', 'ko', 'id', 'sr'],
126-
cookie: 'locale',
127-
directory: path.join(__dirname, '/locales'),
128-
updateFiles: config.updateI18nFiles
129-
})
130-
131-
app.use(cookieParser())
132-
133-
app.use(i18n.init)
134-
135-
// routes without sessions
136-
// static files
137-
app.use('/', express.static(path.join(__dirname, '/public'), { maxAge: config.staticCacheTime, index: false }))
138-
app.use('/docs', express.static(path.resolve(__dirname, config.docsPath), { maxAge: config.staticCacheTime }))
139-
app.use('/uploads', express.static(path.resolve(__dirname, config.uploadsPath), { maxAge: config.staticCacheTime }))
140-
app.use('/default.md', express.static(path.resolve(__dirname, config.defaultNotePath), { maxAge: config.staticCacheTime }))
141-
app.use(require('./dist/metrics').router)
142-
143-
// session
144-
app.use(session({
145-
name: config.sessionName,
146-
secret: config.sessionSecret,
147-
resave: false, // don't save session if unmodified
148-
saveUninitialized: true, // always create session to ensure the origin
149-
rolling: true, // reset maxAge on every response
150-
cookie: {
151-
maxAge: config.sessionLife
152-
},
153-
store: sessionStore
154-
}))
155-
156-
// session resumption
157-
var tlsSessionStore = {}
158-
server.on('newSession', function (id, data, cb) {
159-
tlsSessionStore[id.toString('hex')] = data
160-
cb()
161-
})
162-
server.on('resumeSession', function (id, cb) {
163-
cb(null, tlsSessionStore[id.toString('hex')] || null)
164-
})
165-
166-
// middleware which blocks requests when we're too busy
167-
app.use(require('./dist/middleware/tooBusy'))
168-
169-
app.use(flash())
170-
171-
// passport
172-
app.use(passport.initialize())
173-
app.use(passport.session())
174-
175-
// check uri is valid before going further
176-
app.use(require('./dist/middleware/checkURIValid'))
177-
// redirect url without trailing slashes
178-
app.use(require('./dist/middleware/redirectWithoutTrailingSlashes'))
179-
app.use(require('./dist/middleware/codiMDVersion'))
180-
181-
if (config.autoVersionCheck && process.env.NODE_ENV === Environment.production) {
182-
checkVersion(app)
183-
app.use(versionCheckMiddleware)
184-
}
185-
186-
// routes need sessions
187-
// template files
188-
app.set('views', config.viewPath)
189-
// set render engine
190-
app.engine('ejs', ejs.renderFile)
191-
// set view engine
192-
app.set('view engine', 'ejs')
193-
// set generally available variables for all views
194-
app.locals.useCDN = config.useCDN
195-
app.locals.serverURL = config.serverURL
196-
app.locals.sourceURL = config.sourceURL
197-
app.locals.privacyPolicyURL = config.privacyPolicyURL
198-
app.locals.allowAnonymous = config.allowAnonymous
199-
app.locals.allowAnonymousEdits = config.allowAnonymousEdits
200-
app.locals.permission = config.permission
201-
app.locals.allowPDFExport = config.allowPDFExport
202-
app.locals.authProviders = {
203-
facebook: config.isFacebookEnable,
204-
twitter: config.isTwitterEnable,
205-
github: config.isGitHubEnable,
206-
bitbucket: config.isBitbucketEnable,
207-
gitlab: config.isGitLabEnable,
208-
mattermost: config.isMattermostEnable,
209-
dropbox: config.isDropboxEnable,
210-
google: config.isGoogleEnable,
211-
ldap: config.isLDAPEnable,
212-
ldapProviderName: config.ldap.providerName,
213-
saml: config.isSAMLEnable,
214-
oauth2: config.isOAuth2Enable,
215-
oauth2ProviderName: config.oauth2.providerName,
216-
openID: config.isOpenIDEnable,
217-
email: config.isEmailEnable,
218-
allowEmailRegister: config.allowEmailRegister
219-
}
220-
app.locals.versionInfo = {
221-
latest: true,
222-
versionItem: null
223-
}
224-
225-
// Export/Import menu items
226-
app.locals.enableDropBoxSave = config.isDropboxEnable
227-
app.locals.enableGitHubGist = config.isGitHubEnable
228-
app.locals.enableGitlabSnippets = config.isGitlabSnippetsEnable
229-
230-
app.use(require('./dist/routes').router)
231-
232-
// response not found if no any route matxches
233-
app.get('*', function (req, res) {
234-
response.errorNotFound(req, res)
235-
})
236-
237-
// socket.io secure
238-
io.use(realtime.secure)
239-
// socket.io auth
240-
io.use(passportSocketIo.authorize({
241-
cookieParser: cookieParser,
242-
key: config.sessionName,
243-
secret: config.sessionSecret,
244-
store: sessionStore,
245-
success: realtime.onAuthorizeSuccess,
246-
fail: realtime.onAuthorizeFail
247-
}))
248-
// socket.io heartbeat
249-
io.set('heartbeat interval', config.heartbeatInterval)
250-
io.set('heartbeat timeout', config.heartbeatTimeout)
251-
// socket.io connection
252-
io.sockets.on('connection', realtime.connection)
253-
254-
// listen
255-
function startListen () {
256-
var address
257-
var listenCallback = function () {
258-
var schema = config.useSSL ? 'HTTPS' : 'HTTP'
259-
logger.info('%s Server listening at %s', schema, address)
260-
realtime.maintenance = false
261-
}
262-
263-
// use unix domain socket if 'path' is specified
264-
if (config.path) {
265-
address = config.path
266-
server.listen(config.path, listenCallback)
267-
} else {
268-
address = config.host + ':' + config.port
269-
server.listen(config.port, config.host, listenCallback)
270-
}
271-
}
272-
273-
// sync db then start listen
274-
models.sequelize.sync().then(function () {
275-
// check if realtime is ready
276-
if (realtime.isReady()) {
277-
models.Revision.checkAllNotesRevision(function (err, notes) {
278-
if (err) throw new Error(err)
279-
if (!notes || notes.length <= 0) return startListen()
280-
})
281-
} else {
282-
throw new Error('server still not ready after db synced')
283-
}
284-
}).catch(err => {
285-
logger.error('Can\'t sync database')
286-
logger.error(err.stack)
287-
logger.error('Process will exit now.')
288-
process.exit(1)
289-
})
290-
291-
// log uncaught exception
292-
process.on('uncaughtException', function (err) {
293-
logger.error('An uncaught exception has occured.')
294-
logger.error(err)
295-
console.error(err)
296-
logger.error('Process will exit now.')
297-
process.exit(1)
298-
})
299-
300-
// install exit handler
301-
function handleTermSignals () {
302-
logger.info('CodiMD has been killed by signal, try to exit gracefully...')
303-
realtime.maintenance = true
304-
realtime.terminate()
305-
// disconnect all socket.io clients
306-
Object.keys(io.sockets.sockets).forEach(function (key) {
307-
var socket = io.sockets.sockets[key]
308-
// notify client server going into maintenance status
309-
socket.emit('maintenance')
310-
setTimeout(function () {
311-
socket.disconnect(true)
312-
}, 0)
313-
})
314-
var checkCleanTimer = setInterval(function () {
315-
if (realtime.isReady()) {
316-
models.Revision.checkAllNotesRevision(function (err, notes) {
317-
if (err) return logger.error(err)
318-
if (!notes || notes.length <= 0) {
319-
clearInterval(checkCleanTimer)
320-
return process.exit(0)
321-
}
322-
})
323-
}
324-
}, 100)
325-
setTimeout(() => {
326-
process.exit(1)
327-
}, 5000)
328-
}
329-
process.on('SIGINT', handleTermSignals)
330-
process.on('SIGTERM', handleTermSignals)
331-
process.on('SIGQUIT', handleTermSignals)
3+
require('./dist/app.js')

0 commit comments

Comments
 (0)