webpack-dev-server 1.15.1 → 1.16.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -16
- package/README.md +23 -0
- package/bin/webpack-dev-server.js +15 -0
- package/client/index.bundle.js +3 -3
- package/client/index.js +128 -96
- package/client/live.bundle.js +4 -4
- package/client/live.html +1 -1
- package/client/live.js +129 -128
- package/client/page.jade +7 -7
- package/client/socket.js +41 -0
- package/client/style.css +58 -58
- package/client/web_modules/jquery/index.js +1 -1
- package/client/web_modules/jquery/jquery-1.8.1.js +9301 -9301
- package/client/webpack.config.js +11 -11
- package/lib/Server.js +416 -409
- package/package.json +2 -2
- package/ssl/ca.crt +13 -13
- package/ssl/ca.csr +11 -11
- package/ssl/ca.key +15 -15
- package/ssl/server.crt +13 -13
- package/ssl/server.csr +11 -11
- package/ssl/server.key +15 -15
package/lib/Server.js
CHANGED
|
@@ -1,409 +1,416 @@
|
|
|
1
|
-
var fs = require("fs");
|
|
2
|
-
var path = require("path");
|
|
3
|
-
var webpackDevMiddleware = require("webpack-dev-middleware");
|
|
4
|
-
var express = require("express");
|
|
5
|
-
var compress = require("compression");
|
|
6
|
-
var sockjs = require("sockjs");
|
|
7
|
-
var StreamCache = require("stream-cache");
|
|
8
|
-
var http = require("http");
|
|
9
|
-
var https = require("https");
|
|
10
|
-
var httpProxyMiddleware = require("http-proxy-middleware");
|
|
11
|
-
var serveIndex = require("serve-index");
|
|
12
|
-
var historyApiFallback = require("connect-history-api-fallback");
|
|
13
|
-
|
|
14
|
-
function Server(compiler, options) {
|
|
15
|
-
// Default options
|
|
16
|
-
if(!options) options = {};
|
|
17
|
-
|
|
18
|
-
if(options.lazy && !options.filename) {
|
|
19
|
-
throw new Error("'filename' option must be set in lazy mode.");
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
this.hot = options.hot;
|
|
23
|
-
this.headers = options.headers;
|
|
24
|
-
this.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
compiler.plugin("
|
|
32
|
-
compiler.plugin("
|
|
33
|
-
|
|
34
|
-
this.
|
|
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
|
-
res.
|
|
73
|
-
|
|
74
|
-
var
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
res.write(
|
|
84
|
-
res.write(
|
|
85
|
-
res.write(
|
|
86
|
-
res.write(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
res.write(
|
|
91
|
-
res.write(
|
|
92
|
-
res.write(
|
|
93
|
-
res.write(
|
|
94
|
-
res.write(
|
|
95
|
-
res.write(
|
|
96
|
-
res.write(
|
|
97
|
-
res.write(
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
res.write(
|
|
102
|
-
res.write(
|
|
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
|
-
* proxy:
|
|
136
|
-
*
|
|
137
|
-
* }
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
proxyOptions
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
* proxy:
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
var
|
|
175
|
-
var
|
|
176
|
-
|
|
177
|
-
//
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
console.log('proxy
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
res.
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
conn
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
this.sockWrite(sockets, "ok");
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
if(
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
1
|
+
var fs = require("fs");
|
|
2
|
+
var path = require("path");
|
|
3
|
+
var webpackDevMiddleware = require("webpack-dev-middleware");
|
|
4
|
+
var express = require("express");
|
|
5
|
+
var compress = require("compression");
|
|
6
|
+
var sockjs = require("sockjs");
|
|
7
|
+
var StreamCache = require("stream-cache");
|
|
8
|
+
var http = require("http");
|
|
9
|
+
var https = require("https");
|
|
10
|
+
var httpProxyMiddleware = require("http-proxy-middleware");
|
|
11
|
+
var serveIndex = require("serve-index");
|
|
12
|
+
var historyApiFallback = require("connect-history-api-fallback");
|
|
13
|
+
|
|
14
|
+
function Server(compiler, options) {
|
|
15
|
+
// Default options
|
|
16
|
+
if(!options) options = {};
|
|
17
|
+
|
|
18
|
+
if(options.lazy && !options.filename) {
|
|
19
|
+
throw new Error("'filename' option must be set in lazy mode.");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
this.hot = options.hot;
|
|
23
|
+
this.headers = options.headers;
|
|
24
|
+
this.clientLogLevel = options.clientLogLevel;
|
|
25
|
+
this.sockets = [];
|
|
26
|
+
|
|
27
|
+
// Listening for events
|
|
28
|
+
var invalidPlugin = function() {
|
|
29
|
+
this.sockWrite(this.sockets, "invalid");
|
|
30
|
+
}.bind(this);
|
|
31
|
+
compiler.plugin("compile", invalidPlugin);
|
|
32
|
+
compiler.plugin("invalid", invalidPlugin);
|
|
33
|
+
compiler.plugin("done", function(stats) {
|
|
34
|
+
this._sendStats(this.sockets, stats.toJson());
|
|
35
|
+
this._stats = stats;
|
|
36
|
+
}.bind(this));
|
|
37
|
+
|
|
38
|
+
// Prepare live html page
|
|
39
|
+
var livePage = this.livePage = new StreamCache();
|
|
40
|
+
fs.createReadStream(path.join(__dirname, "..", "client", "live.html")).pipe(livePage);
|
|
41
|
+
|
|
42
|
+
// Prepare the live js file
|
|
43
|
+
var liveJs = new StreamCache();
|
|
44
|
+
fs.createReadStream(path.join(__dirname, "..", "client", "live.bundle.js")).pipe(liveJs);
|
|
45
|
+
|
|
46
|
+
// Prepare the inlined js file
|
|
47
|
+
var inlinedJs = new StreamCache();
|
|
48
|
+
fs.createReadStream(path.join(__dirname, "..", "client", "index.bundle.js")).pipe(inlinedJs);
|
|
49
|
+
|
|
50
|
+
// Init express server
|
|
51
|
+
var app = this.app = new express();
|
|
52
|
+
|
|
53
|
+
// middleware for serving webpack bundle
|
|
54
|
+
this.middleware = webpackDevMiddleware(compiler, options);
|
|
55
|
+
|
|
56
|
+
app.get("/__webpack_dev_server__/live.bundle.js", function(req, res) {
|
|
57
|
+
res.setHeader("Content-Type", "application/javascript");
|
|
58
|
+
liveJs.pipe(res);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
app.get("/webpack-dev-server.js", function(req, res) {
|
|
62
|
+
res.setHeader("Content-Type", "application/javascript");
|
|
63
|
+
inlinedJs.pipe(res);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
app.get("/webpack-dev-server/*", function(req, res) {
|
|
67
|
+
res.setHeader("Content-Type", "text/html");
|
|
68
|
+
this.livePage.pipe(res);
|
|
69
|
+
}.bind(this));
|
|
70
|
+
|
|
71
|
+
app.get("/webpack-dev-server", function(req, res) {
|
|
72
|
+
res.setHeader("Content-Type", "text/html");
|
|
73
|
+
res.write('<!DOCTYPE html><html><head><meta charset="utf-8"/></head><body>');
|
|
74
|
+
var path = this.middleware.getFilenameFromUrl(options.publicPath || "/");
|
|
75
|
+
var fs = this.middleware.fileSystem;
|
|
76
|
+
|
|
77
|
+
function writeDirectory(baseUrl, basePath) {
|
|
78
|
+
var content = fs.readdirSync(basePath);
|
|
79
|
+
res.write("<ul>");
|
|
80
|
+
content.forEach(function(item) {
|
|
81
|
+
var p = basePath + "/" + item;
|
|
82
|
+
if(fs.statSync(p).isFile()) {
|
|
83
|
+
res.write('<li><a href="');
|
|
84
|
+
res.write(baseUrl + item);
|
|
85
|
+
res.write('">');
|
|
86
|
+
res.write(item);
|
|
87
|
+
res.write('</a></li>');
|
|
88
|
+
if(/\.js$/.test(item)) {
|
|
89
|
+
var htmlItem = item.substr(0, item.length - 3);
|
|
90
|
+
res.write('<li><a href="');
|
|
91
|
+
res.write(baseUrl + htmlItem);
|
|
92
|
+
res.write('">');
|
|
93
|
+
res.write(htmlItem);
|
|
94
|
+
res.write('</a> (magic html for ');
|
|
95
|
+
res.write(item);
|
|
96
|
+
res.write(') (<a href="');
|
|
97
|
+
res.write(baseUrl.replace(/(^(https?:\/\/[^\/]+)?\/)/, "$1webpack-dev-server/") + htmlItem);
|
|
98
|
+
res.write('">webpack-dev-server</a>)</li>');
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
res.write('<li>');
|
|
102
|
+
res.write(item);
|
|
103
|
+
res.write('<br>');
|
|
104
|
+
writeDirectory(baseUrl + item + "/", p);
|
|
105
|
+
res.write('</li>');
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
res.write("</ul>");
|
|
109
|
+
}
|
|
110
|
+
writeDirectory(options.publicPath || "/", path);
|
|
111
|
+
res.end('</body></html>');
|
|
112
|
+
}.bind(this));
|
|
113
|
+
|
|
114
|
+
var features = {
|
|
115
|
+
compress: function() {
|
|
116
|
+
if(options.compress) {
|
|
117
|
+
// Enable gzip compression.
|
|
118
|
+
app.use(compress());
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
proxy: function() {
|
|
123
|
+
if(options.proxy) {
|
|
124
|
+
/**
|
|
125
|
+
* Assume a proxy configuration specified as:
|
|
126
|
+
* proxy: 'a url'
|
|
127
|
+
*/
|
|
128
|
+
if(typeof options.proxy === 'string') {
|
|
129
|
+
options.proxy = [{
|
|
130
|
+
context: options.proxy
|
|
131
|
+
}];
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Assume a proxy configuration specified as:
|
|
136
|
+
* proxy: {
|
|
137
|
+
* 'context': { options }
|
|
138
|
+
* }
|
|
139
|
+
* OR
|
|
140
|
+
* proxy: {
|
|
141
|
+
* 'context': 'target'
|
|
142
|
+
* }
|
|
143
|
+
*/
|
|
144
|
+
if(!Array.isArray(options.proxy)) {
|
|
145
|
+
options.proxy = Object.keys(options.proxy).map(function(context) {
|
|
146
|
+
var proxyOptions;
|
|
147
|
+
// For backwards compatibility reasons.
|
|
148
|
+
var correctedContext = context.replace(/^\*$/, "**").replace(/\/\*$/, "");
|
|
149
|
+
|
|
150
|
+
if(typeof options.proxy[context] === 'string') {
|
|
151
|
+
proxyOptions = {
|
|
152
|
+
context: correctedContext,
|
|
153
|
+
target: options.proxy[context]
|
|
154
|
+
};
|
|
155
|
+
} else {
|
|
156
|
+
proxyOptions = options.proxy[context];
|
|
157
|
+
proxyOptions.context = correctedContext;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return proxyOptions;
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Assume a proxy configuration specified as:
|
|
166
|
+
* proxy: [
|
|
167
|
+
* {
|
|
168
|
+
* context: ...,
|
|
169
|
+
* ...options...
|
|
170
|
+
* }
|
|
171
|
+
* ]
|
|
172
|
+
*/
|
|
173
|
+
options.proxy.forEach(function(proxyConfig) {
|
|
174
|
+
var bypass = typeof proxyConfig.bypass === 'function';
|
|
175
|
+
var context = proxyConfig.context || proxyConfig.path;
|
|
176
|
+
var proxyMiddleware;
|
|
177
|
+
// It is possible to use the `bypass` method without a `target`.
|
|
178
|
+
// However, the proxy middleware has no use in this case, and will fail to instantiate.
|
|
179
|
+
if(proxyConfig.target) {
|
|
180
|
+
proxyMiddleware = httpProxyMiddleware(context, proxyConfig);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
app.use(function(req, res, next) {
|
|
184
|
+
var bypassUrl = bypass && proxyConfig.bypass(req, res, proxyConfig) || false;
|
|
185
|
+
|
|
186
|
+
if(bypassUrl) {
|
|
187
|
+
req.url = bypassUrl;
|
|
188
|
+
next();
|
|
189
|
+
} else if(proxyMiddleware) {
|
|
190
|
+
return proxyMiddleware(req, res, next);
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
|
|
197
|
+
historyApiFallback: function() {
|
|
198
|
+
if(options.historyApiFallback) {
|
|
199
|
+
// Fall back to /index.html if nothing else matches.
|
|
200
|
+
app.use(historyApiFallback(typeof options.historyApiFallback === 'object' ? options.historyApiFallback : null));
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
|
|
204
|
+
contentBase: function() {
|
|
205
|
+
if(options.contentBase !== false) {
|
|
206
|
+
var contentBase = options.contentBase || process.cwd();
|
|
207
|
+
|
|
208
|
+
if(Array.isArray(contentBase)) {
|
|
209
|
+
contentBase.forEach(function(item) {
|
|
210
|
+
app.get("*", express.static(item));
|
|
211
|
+
});
|
|
212
|
+
contentBase.forEach(function(item) {
|
|
213
|
+
app.get("*", serveIndex(item));
|
|
214
|
+
});
|
|
215
|
+
} else if(typeof contentBase === "object") {
|
|
216
|
+
console.log('Using contentBase as a proxy is deprecated and will be removed in the next major version. Please use the proxy option instead.\n\nTo update remove the contentBase option from webpack.config.js and add this:');
|
|
217
|
+
console.log('proxy: {\n\t"*": <your current contentBase configuration>\n}');
|
|
218
|
+
// Proxy every request to contentBase.target
|
|
219
|
+
app.all("*", function(req, res) {
|
|
220
|
+
proxy.web(req, res, contentBase, function(err) {
|
|
221
|
+
var msg = "cannot proxy to " + contentBase.target + " (" + err.message + ")";
|
|
222
|
+
this.sockWrite(this.sockets, "proxy-error", [msg]);
|
|
223
|
+
res.statusCode = 502;
|
|
224
|
+
res.end();
|
|
225
|
+
}.bind(this));
|
|
226
|
+
}.bind(this));
|
|
227
|
+
} else if(/^(https?:)?\/\//.test(contentBase)) {
|
|
228
|
+
// Redirect every request to contentBase
|
|
229
|
+
app.get("*", function(req, res) {
|
|
230
|
+
res.writeHead(302, {
|
|
231
|
+
'Location': contentBase + req.path + (req._parsedUrl.search || "")
|
|
232
|
+
});
|
|
233
|
+
res.end();
|
|
234
|
+
});
|
|
235
|
+
} else if(typeof contentBase === "number") {
|
|
236
|
+
// Redirect every request to the port contentBase
|
|
237
|
+
app.get("*", function(req, res) {
|
|
238
|
+
res.writeHead(302, {
|
|
239
|
+
'Location': "//localhost:" + contentBase + req.path + (req._parsedUrl.search || "")
|
|
240
|
+
});
|
|
241
|
+
res.end();
|
|
242
|
+
});
|
|
243
|
+
} else {
|
|
244
|
+
// route content request
|
|
245
|
+
app.get("*", express.static(contentBase, options.staticOptions), serveIndex(contentBase));
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}.bind(this),
|
|
249
|
+
|
|
250
|
+
middleware: function() {
|
|
251
|
+
// include our middleware to ensure it is able to handle '/index.html' request after redirect
|
|
252
|
+
app.use(this.middleware);
|
|
253
|
+
}.bind(this),
|
|
254
|
+
|
|
255
|
+
headers: function() {
|
|
256
|
+
app.all("*", this.setContentHeaders.bind(this));
|
|
257
|
+
}.bind(this),
|
|
258
|
+
|
|
259
|
+
magicHtml: function() {
|
|
260
|
+
app.get("*", this.serveMagicHtml.bind(this));
|
|
261
|
+
}.bind(this),
|
|
262
|
+
|
|
263
|
+
setup: function() {
|
|
264
|
+
if(typeof options.setup === "function")
|
|
265
|
+
options.setup(app, this);
|
|
266
|
+
}.bind(this)
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
var defaultFeatures = ["setup", "headers", "middleware"];
|
|
270
|
+
if(options.proxy)
|
|
271
|
+
defaultFeatures.push("proxy", "middleware");
|
|
272
|
+
if(options.historyApiFallback)
|
|
273
|
+
defaultFeatures.push("historyApiFallback", "middleware");
|
|
274
|
+
defaultFeatures.push("magicHtml");
|
|
275
|
+
if(options.contentBase !== false)
|
|
276
|
+
defaultFeatures.push("contentBase");
|
|
277
|
+
// compress is placed last and uses unshift so that it will be the first middleware used
|
|
278
|
+
if(options.compress)
|
|
279
|
+
defaultFeatures.unshift("compress");
|
|
280
|
+
|
|
281
|
+
(options.features || defaultFeatures).forEach(function(feature) {
|
|
282
|
+
features[feature]();
|
|
283
|
+
}, this);
|
|
284
|
+
|
|
285
|
+
if(options.https) {
|
|
286
|
+
// for keep supporting CLI parameters
|
|
287
|
+
if(typeof options.https === 'boolean') {
|
|
288
|
+
options.https = {
|
|
289
|
+
key: options.key,
|
|
290
|
+
cert: options.cert,
|
|
291
|
+
ca: options.ca,
|
|
292
|
+
pfx: options.pfx,
|
|
293
|
+
passphrase: options.pfxPassphrase
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// using built-in self-signed certificate if no certificate was configured
|
|
298
|
+
options.https.key = options.https.key || fs.readFileSync(path.join(__dirname, "../ssl/server.key"));
|
|
299
|
+
options.https.cert = options.https.cert || fs.readFileSync(path.join(__dirname, "../ssl/server.crt"));
|
|
300
|
+
options.https.ca = options.https.ca || fs.readFileSync(path.join(__dirname, "../ssl/ca.crt"));
|
|
301
|
+
|
|
302
|
+
this.listeningApp = https.createServer(options.https, app);
|
|
303
|
+
} else {
|
|
304
|
+
this.listeningApp = http.createServer(app);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
Server.prototype.use = function() {
|
|
309
|
+
this.app.use.apply(this.app, arguments);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
Server.prototype.setContentHeaders = function(req, res, next) {
|
|
313
|
+
if(this.headers) {
|
|
314
|
+
for(var name in this.headers) {
|
|
315
|
+
res.setHeader(name, this.headers[name]);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
next();
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// delegate listen call and init sockjs
|
|
323
|
+
Server.prototype.listen = function() {
|
|
324
|
+
this.listeningApp.listen.apply(this.listeningApp, arguments);
|
|
325
|
+
var sockServer = sockjs.createServer({
|
|
326
|
+
// Limit useless logs
|
|
327
|
+
log: function(severity, line) {
|
|
328
|
+
if(severity === "error") {
|
|
329
|
+
console.log(line);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
sockServer.on("connection", function(conn) {
|
|
334
|
+
if(!conn) return;
|
|
335
|
+
this.sockets.push(conn);
|
|
336
|
+
|
|
337
|
+
conn.on("close", function() {
|
|
338
|
+
var connIndex = this.sockets.indexOf(conn);
|
|
339
|
+
if(connIndex >= 0) {
|
|
340
|
+
this.sockets.splice(connIndex, 1);
|
|
341
|
+
}
|
|
342
|
+
}.bind(this));
|
|
343
|
+
|
|
344
|
+
if(this.clientLogLevel)
|
|
345
|
+
this.sockWrite([conn], "log-level", this.clientLogLevel);
|
|
346
|
+
|
|
347
|
+
if(this.hot) this.sockWrite([conn], "hot");
|
|
348
|
+
|
|
349
|
+
if(!this._stats) return;
|
|
350
|
+
this._sendStats([conn], this._stats.toJson(), true);
|
|
351
|
+
}.bind(this));
|
|
352
|
+
|
|
353
|
+
sockServer.installHandlers(this.listeningApp, {
|
|
354
|
+
prefix: '/sockjs-node'
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
Server.prototype.close = function() {
|
|
359
|
+
this.sockets.forEach(function(sock) {
|
|
360
|
+
sock.close();
|
|
361
|
+
});
|
|
362
|
+
this.sockets = [];
|
|
363
|
+
this.middleware.close();
|
|
364
|
+
this.listeningApp.close();
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
Server.prototype.sockWrite = function(sockets, type, data) {
|
|
368
|
+
sockets.forEach(function(sock) {
|
|
369
|
+
sock.write(JSON.stringify({
|
|
370
|
+
type: type,
|
|
371
|
+
data: data
|
|
372
|
+
}));
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
Server.prototype.serveMagicHtml = function(req, res, next) {
|
|
377
|
+
var _path = req.path;
|
|
378
|
+
try {
|
|
379
|
+
if(!this.middleware.fileSystem.statSync(this.middleware.getFilenameFromUrl(_path + ".js")).isFile())
|
|
380
|
+
return next();
|
|
381
|
+
// Serve a page that executes the javascript
|
|
382
|
+
res.write('<!DOCTYPE html><html><head><meta charset="utf-8"/></head><body><script type="text/javascript" charset="utf-8" src="');
|
|
383
|
+
res.write(_path);
|
|
384
|
+
res.write('.js');
|
|
385
|
+
res.write(req._parsedUrl.search || "");
|
|
386
|
+
res.end('"></script></body></html>');
|
|
387
|
+
} catch(e) {
|
|
388
|
+
return next();
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// send stats to a socket or multiple sockets
|
|
393
|
+
Server.prototype._sendStats = function(sockets, stats, force) {
|
|
394
|
+
if(!force &&
|
|
395
|
+
stats &&
|
|
396
|
+
(!stats.errors || stats.errors.length === 0) &&
|
|
397
|
+
stats.assets &&
|
|
398
|
+
stats.assets.every(function(asset) {
|
|
399
|
+
return !asset.emitted;
|
|
400
|
+
})
|
|
401
|
+
)
|
|
402
|
+
return this.sockWrite(sockets, "still-ok");
|
|
403
|
+
this.sockWrite(sockets, "hash", stats.hash);
|
|
404
|
+
if(stats.errors.length > 0)
|
|
405
|
+
this.sockWrite(sockets, "errors", stats.errors);
|
|
406
|
+
else if(stats.warnings.length > 0)
|
|
407
|
+
this.sockWrite(sockets, "warnings", stats.warnings);
|
|
408
|
+
else
|
|
409
|
+
this.sockWrite(sockets, "ok");
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
Server.prototype.invalidate = function() {
|
|
413
|
+
if(this.middleware) this.middleware.invalidate();
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
module.exports = Server;
|