UNPKG

4.06 kBJavaScriptView Raw
1/**
2 * Module Dependencies
3 *
4 * @ignore
5 */
6var bodyParser = require('body-parser')
7var contentLength = require('express-content-length-validator')
8var cors = require('cors')
9var Dispatcher = require('structure-dispatcher').default
10var express = require('express')
11var helmet = require('helmet')
12var hpp = require('hpp')
13var logger = require('structure-logger')
14var path = require('path')
15var Router = require('structure-router')
16var serveStatic = require('serve-static')
17var WebsocketServer = require('structure-websocket-server')
18
19function removePoweredBy(req, res, next) {
20 res.removeHeader('X-Powered-By')
21 next()
22}
23
24/**
25 * Server Class
26 *
27 * @public
28 * @class Server
29 */
30class Server {
31
32 /**
33 * Server constructor
34 *
35 * @public
36 * @constructor
37 * @param {Object} options - Options
38 */
39 constructor(options = {}) {
40
41 var defaults = {
42 cursors: options.cursors || [],
43 db: true,
44 drain: true,
45 sockets: true
46 }
47
48 this.options = Object.assign({}, defaults, options)
49
50 this.server = express()
51
52 /*
53 TODO: Add whitelist
54 */
55 this.server.use(cors())
56
57 /*if(process.env.NODE_ENV != 'test') {
58 this.server.use(require('express-status-monitor')())
59 }*/
60 this.server.use(serveStatic(path.join(__dirname, '../public')))
61 this.server.use(bodyParser.urlencoded({extended: true}))
62 this.server.use(bodyParser.json({strict: false}))
63 //this.server.use(removePoweredBy)
64 this.server.use(helmet())
65 this.server.use(hpp())
66 this.server.use(contentLength.validateMax({max: process.env.MAX_CONTENT_LENGTH, status: 400, message: 'stop it!'}))
67
68 if(process.env.NODE_ENV != 'test') {
69 this.server.use(this.logRequestInfo)
70 }
71
72 this.router = options.router || new Router({
73 dispatcher: options.dispatcher || new Dispatcher(),
74 routes: options.routes
75 })
76
77 this.router.start(this.server)
78
79 /*if(process.env.LOG_LEVEL == 'debug') {
80 logger.debug('Routes list:')
81 this.debugRoutes()
82 }*/
83
84 }
85
86 closeCursors() {
87 var cursors = require('./cursors')
88
89 for(let i = 0, l = cursors.length; i < l; i++) {
90 var cursor = cursors[i]
91 cursor.close()
92 }
93
94 cursors = []
95
96 }
97
98 /**
99 * List of routes registered with Express including middleware routes
100 *
101 * @private
102 */
103 debugRoutes() {
104 var route, routes = []
105
106 this.server._router.stack.forEach(function(middleware) {
107 if(middleware.route) {
108 routes.push(middleware.route)
109 } else if(middleware.name === 'router') { // router middleware
110 middleware.handle.stack.forEach(function(handler) {
111 route = handler.route
112 route && routes.push(route)
113 })
114 }
115 })
116
117 routes.forEach( (route) => {
118
119 var method = Object.keys(route.methods)[0].toUpperCase()
120
121 console.error(`${method} ${route.path}`)
122
123 })
124
125 }
126
127 /**
128 * Log each HTTP request's method and url
129 *
130 * @private
131 * @param {Object} req - Express req
132 * @param {Object} res - Express res
133 * @param {Function} next - Express next
134 */
135 logRequestInfo(req, res, next) {
136
137 logger.info(req.method, req.originalUrl)
138 next()
139
140 }
141
142 /**
143 * Start the HTTP Server
144 *
145 * @public
146 */
147 start() {
148
149 this.server = this.server.listen(this.options.port || process.env.EXPRESS_PORT)
150
151 if(this.options.sockets) {
152 this.wss = new WebsocketServer(this.server)
153 }
154
155 if(this.options.db) {
156 this.cursors = []
157 }
158
159 logger.debug('Structure API started at:', `http://localhost:${process.env.EXPRESS_PORT}`)
160
161 }
162
163 /**
164 * Stop the HTTP Server
165 *
166 * @public
167 */
168 stop() {
169
170 if(this.options.db) {
171 var r = require('../lib/database/driver')
172 if(this.options.drain) r.getPoolMaster().drain()
173 this.closeCursors()
174 }
175
176 if(this.options.sockets) {
177 this.wss.stop()
178 }
179
180 this.server.close()
181
182 }
183
184 /**
185 * Add Express middleware to the Express server object
186 *
187 * @public
188 */
189 use() {
190
191 this.server.use.apply(this.server, arguments)
192
193 }
194
195}
196
197module.exports = Server