-
Notifications
You must be signed in to change notification settings - Fork 29
/
index.js
177 lines (165 loc) · 5.34 KB
/
index.js
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
const fs = require('fs')
const http = require('http')
const https = require('https')
const path = require('path')
const Conf = require('conf')
const mkdirp = require('mkdirp')
const express = require('express')
const favicon = require('serve-favicon')
const bodyParser = require('body-parser')
const { EventEmitter } = require('events')
const DEFAULT = require('./config')
/**
* Start Server
*
* @param {string} [options] Server Options
* @param {string} [options.cache='~/mbtiles'] CACHE file path
* @param {string} [options.protocol='http'] URL Protocol
* @param {string} [options.domain='localhost'] URL Domain
* @param {number} [options.port=5000] URL Port
* @param {boolean} [options.watch=false] Watch files and restarts the server when detected
* @returns {EventEmitter} EventEmitter
* @example
* server({cache: '/Users/mac/mbtiles', port: 5000, verbose: true})
*/
module.exports = function (options = {}) {
const config = new Conf({ projectName: 'MBTiles Server' })
config.set('PROTOCOL', options.protocol || DEFAULT.PROTOCOL)
config.set('PORT', options.port || DEFAULT.PORT)
config.set('DOMAIN', options.domain || DEFAULT.DOMAIN)
const cache = options.cache || DEFAULT.CACHE
const sslkey = options.sslkey || (DEFAULT.SSL_KEY || path.join(cache, 'server.key'))
const sslcert = options.sslcert || (DEFAULT.SSL_CERT || path.join(cache, 'server.cert'))
config.set('CACHE', cache)
config.set('SSL_KEY', sslkey)
config.set('SSL_CERT', sslcert)
// Settings
const app = express()
app.use(bodyParser.json())
app.set('json spaces', 2)
app.use(bodyParser.urlencoded({ extended: true }))
app.set('trust proxy', true)
/**
* Server
*/
class Server extends EventEmitter {
/**
* Start Server
*
* @param {string} [options] Server Options
* @param {string} [options.cache=~/mbtiles] CACHE file path
* @param {string} [options.domain='localhost'] URL Domain
* @param {string} [options.port=5000] URL Port
* @returns {Promise<Object>} port
*/
start (options = {}) {
const protocol = options.protocol || DEFAULT.PROTOCOL
const port = options.port || DEFAULT.PORT
const domain = options.domain || DEFAULT.DOMAIN
const cache = options.cache || DEFAULT.CACHE
const sslkey = options.sslkey || (DEFAULT.SSL_KEY || path.join(cache, 'server.key'))
const sslcert = options.sslcert || (DEFAULT.SSL_CERT || path.join(cache, 'server.cert'))
const watch = options.watch
options = { protocol, port, domain, cache, watch, sslkey, sslcert }
// Save local settings
config.set('PROTOCOL', protocol)
config.set('PORT', port)
config.set('DOMAIN', domain)
config.set('CACHE', cache)
config.set('SSL_CERT', sslcert)
config.set('SSL_KEY', sslkey)
this.cache = cache
this.watch = watch
// Create folder
if (!fs.existsSync(cache)) mkdirp.sync(cache)
// Restart if file change detected
if (watch) {
fs.watchFile(cache, current => {
this.restart(options)
})
}
return new Promise((resolve, reject) => {
let server = null
if (protocol === 'http') {
server = http.createServer(app)
} else {
let options = {}
if (fs.existsSync(sslkey) && fs.existsSync(sslcert)) {
options = {
key: fs.readFileSync(sslkey, 'utf8'),
cert: fs.readFileSync(sslcert, 'utf8')
}
}
server = https.createServer(options, app)
}
this.server = server.listen(port, () => {
this.emit('start', options)
return resolve(options)
})
this.server.on('error', error => {
return reject(error)
})
})
}
/**
* Shutdown Server
*
* @returns {Promise<void>}
*/
close () {
return new Promise(resolve => {
if (!this.server) return resolve()
this.server.close(() => {
this.emit('end')
this.server = undefined
if (this.watch) fs.unwatchFile(this.cache)
return resolve()
})
})
}
/**
* Restart Server
*
* @param {string} [options] Server Options
* @param {string} [options.cache=~/mbtiles] CACHE file path
* @param {string} [options.protocol='http'] URL Protocol
* @param {string} [options.domain='localhost'] URL Domain
* @param {string} [options.port=5000] URL Port
* @returns {Promise<Object>} options
*/
restart (options = {}) {
return new Promise(resolve => {
this.close().then(() => {
this.start(options).then(options => {
return resolve(options)
})
})
})
}
}
const ee = new Server()
// Logging Middleware
app.use((req, res, next) => {
const log = {
body: req.body,
ip: req.headers['x-forwarded-for'] || req.connection.remoteAddress,
method: req.method,
url: req.originalUrl,
query: req.query,
params: req.params
}
ee.emit('log', log)
next()
})
// Register Routes
const routes = require('./routes')
app.use(favicon(path.join(__dirname, 'public', 'icon.ico')))
app.use(routes.permissions)
app.use('/', routes.api)
app.use('/', routes.mbtiles)
app.use('/', routes.wmts)
// Auto-start server
ee.start(options)
.catch(error => ee.emit('error', error))
return ee
}