1 |
|
2 | var util = require("../lib/util")
|
3 | , log = require("../lib/log")("app")
|
4 |
|
5 |
|
6 | module.exports = listen
|
7 |
|
8 |
|
9 | function listen(port) {
|
10 | var exiting
|
11 | , app = this
|
12 | , options = app.options
|
13 |
|
14 | process.on("uncaughtException", function(e) {
|
15 | ;(options.errorLog || log.error)(
|
16 | "\nUNCAUGHT EXCEPTION!\n" +
|
17 | (e.stack || (e.name || "Error") + ": " + (e.message || e))
|
18 | )
|
19 | ;(options.exit || exit).call(app, 1)
|
20 | })
|
21 |
|
22 | process.on("SIGINT", function() {
|
23 | if (exiting) {
|
24 | log.info("Killing from SIGINT (got Ctrl-C twice)")
|
25 | return process.exit()
|
26 | }
|
27 | exiting = true
|
28 | log.info("Gracefully shutting down from SIGINT (Ctrl-C)")
|
29 | ;(options.exit || exit).call(app, 0)
|
30 | })
|
31 |
|
32 | process.on("SIGTERM", function() {
|
33 | log.info("Gracefully shutting down from SIGTERM (kill)")
|
34 | ;(options.exit || exit).call(app, 0)
|
35 | })
|
36 |
|
37 | process.on("SIGHUP", function() {
|
38 | log.info("Reloading configuration from SIGHUP")
|
39 | app.listen(port, true)
|
40 | })
|
41 |
|
42 | app.listen = options.listen || _listen
|
43 |
|
44 | app.listen(port)
|
45 |
|
46 | return app
|
47 | }
|
48 |
|
49 | function _listen(port) {
|
50 | var app = this
|
51 | , options = app.options
|
52 | , httpPort = process.env.PORT || port || 8080
|
53 | , httpsPort = process.env.HTTPS_PORT || 8443
|
54 | , secure = options.https || options.http2
|
55 | , msg = "Listening"
|
56 | , listenCount = 0
|
57 |
|
58 | if (app.httpServer) app.httpServer.close()
|
59 | if (app.httpsServer) app.httpsServer.close()
|
60 | app.httpServer = app.httpsServer = null
|
61 |
|
62 | app.httpServer = require("http")
|
63 | .createServer(secure && options.forceHttps ? forceHttps : this)
|
64 | .listen(httpPort, addMsg("http"))
|
65 | .on("connection", setNoDelay)
|
66 | .on("close", logClose("http"))
|
67 |
|
68 | if (secure) {
|
69 | app.httpsServer = (
|
70 | options.http2 ?
|
71 | require("http2").createSecureServer(secure, this) :
|
72 | require("https").createServer(secure, this)
|
73 | )
|
74 | .listen(httpsPort, options.http2 ? addMsg("http2") : addMsg("https"))
|
75 | .on("connection", setNoDelay)
|
76 | .on("close", logClose(options.http2 ? "http2" : "https"))
|
77 |
|
78 | if (secure.sessionReuse) {
|
79 | var sessionStore = {}
|
80 | , timeout = secure.sessionTimeout || 300
|
81 |
|
82 | app.httpsServer
|
83 | .on("newSession", function(id, data, cb) {
|
84 | sessionStore[id] = data
|
85 | cb()
|
86 | })
|
87 | .on("resumeSession", function(id, cb) {
|
88 | cb(null, sessionStore[id] || null)
|
89 | })
|
90 | }
|
91 | }
|
92 |
|
93 | function addMsg(proto) {
|
94 | listenCount++
|
95 | return function() {
|
96 | var addr = this.address()
|
97 | msg += " " + proto + " at " + addr.address + ":" + addr.port
|
98 | if (!--listenCount) {
|
99 | log.info(msg)
|
100 | }
|
101 | }
|
102 | }
|
103 | function logClose(proto) {
|
104 | return function() {
|
105 | log.info("Stop listening " + proto)
|
106 | }
|
107 | }
|
108 | }
|
109 |
|
110 | function exit(code) {
|
111 | var app = this
|
112 | , softKill = util.wait(function() {
|
113 | log.info("Everything closed cleanly")
|
114 | process.exit(code)
|
115 | }, 1)
|
116 |
|
117 | app.emit("beforeExit", softKill)
|
118 |
|
119 | try {
|
120 | if (app.httpServer) app.httpServer.close().unref()
|
121 | if (app.httpsServer) app.httpsServer.close().unref()
|
122 | } catch(e) {}
|
123 |
|
124 | setTimeout(function() {
|
125 | log.warn("Kill (timeout)")
|
126 | process.exit(code)
|
127 | }, 5000).unref()
|
128 |
|
129 | softKill()
|
130 | }
|
131 |
|
132 | function setNoDelay(socket) {
|
133 | socket.setNoDelay(true)
|
134 | }
|
135 |
|
136 | function forceHttps(req, res) {
|
137 | var port = process.env.HTTPS_PORT || 8443
|
138 | , host = (req.headers.host || "localhost").split(":")[0]
|
139 | , url = "https://" + (port == 443 ? host : host + ":" + port) + req.url
|
140 |
|
141 | res.writeHead(301, {"Content-Type": "text/html", "Location": url})
|
142 | res.end('Redirecting to <a href="' + url + '">' + url + '</a>')
|
143 | }
|
144 |
|
145 |
|