forked from jeffpar/pcjs.v1
-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.js
141 lines (124 loc) · 5.8 KB
/
server.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
/**
* @fileoverview Node web server for pcjs.org
* @author <a href="mailto:[email protected]">Jeff Parsons</a> (@jeffpar)
* @copyright © 2012-2020 Jeff Parsons
*
* This file is part of PCjs, a computer emulation software project at <https://www.pcjs.org>.
*
* PCjs is free software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* PCjs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCjs. If not,
* see <http://www.gnu.org/licenses/gpl.html>.
*
* You are required to include the above copyright notice in every source code file of every
* copy or modified version of this work, and to display that copyright notice on every screen
* that loads or runs any version of this software (see COPYRIGHT in /modules/shared/lib/defines.js).
*
* Some PCjs files also attempt to load external resource files, such as character-image files,
* ROM files, and disk image files. Those external resource files are not considered part of PCjs
* for purposes of the GNU General Public License, and the author does not claim any copyright
* as to their contents.
*/
/*
* Usage:
*
* node server.js [options]
*
* The options supported are basically just pass-through options for the HTMLOut module;
* (eg, --cache, --console, --debug, --rebuild, and --sockets). See HTMLOut for details.
*
* Options specific to this module include --logging, which turns on our own private logging
* (redundant when running on a service like Azure), and --sockets (which we also pass on to
* HTMLOut so that it can enable/disable client-side socket support).
*/
"use strict";
var fs = require("fs");
var path = require("path");
var http = require("http");
var express = require("express");
var slash = require("express-slash");
var defines = require("./modules/shared/lib/defines");
var proclib = require("./modules/shared/lib/proclib");
var args = proclib.getArgs();
var fCache = (args.argv['cache'] === undefined? true : args.argv['cache']);
var fConsole = (args.argv['console'] === undefined? false : args.argv['console']);
var fDebug = (args.argv['debug'] === undefined? false : args.argv['debug']);
var fLogging = (args.argv['logging'] === undefined? false : args.argv['logging']);
var fPrivate = (args.argv['private'] === undefined? false : args.argv['private']);
var fRebuild = (args.argv['rebuild'] === undefined? false : args.argv['rebuild']);
var fSockets = (args.argv['sockets'] === undefined? false : args.argv['sockets']);
var HTMLOut = require("./modules/htmlout/lib/htmlout");
var sServerRoot = __dirname;
HTMLOut.setRoot(sServerRoot);
/*
* In a production environment, you probably want to leave the 'console',
* 'debug' and 'rebuild' options OFF, which is why we warn if they're enabled.
*/
if (fConsole || fDebug || fRebuild) console.log("warning: non-production options enabled");
HTMLOut.setOptions({'cache': fCache, 'console': fConsole, 'debug': fDebug, 'private': fPrivate, 'rebuild': fRebuild, 'sockets': fSockets});
var app = express();
app.enable("strict routing");
var appPort = args.argv['port'] || process.env.PORT || 8088;
app.set('port', appPort);
/*
* For more information about express.logger():
*
* http://www.senchalabs.org/connect/logger.html
*
* NOTE: use {flags: 'a'} to open in append mode instead of write mode. The latter is the default,
* so that a simple server restart will generate a new log file.
*
* TODO: Consider some simple rotation scheme to retain at least a few previous log files.
*/
if (fLogging) {
var streamLog = fs.createWriteStream(path.join(sServerRoot, "./logs/node.log"), {flags: 'w'});
HTMLOut.setOptions({'logfile': streamLog});
app.use(express.logger({ format: 'default', stream: streamLog }));
}
/*
* To be able to save states for machines with large states, I have to rely on server-side
* state API support (see processUserAPI() in httpapi.js in the HTMLOut module), because there
* don't seem to be any good client-side solutions (localStorage is notoriously limited, and
* "data:" URLs crash the browser if they're too large). However, I don't want to jack up the
* server upload limits too high on a "production" server, so I set a higher limit only for
* "debug" servers).
*/
app.use(express.json({limit: fDebug? '128mb' : '4mb'}));
app.use(express.urlencoded({limit: fDebug? '128mb' : '4mb'}));
app.use(HTMLOut.filter);
app.use(express.compress());
/*
* The following hack ensures that our JavaScript files are delivered as UTF-8 files.
* You can tell when they're not: the copyright symbol (©) in my file headers doesn't
* display properly.
*
* TODO: Determine if we have any other UTF-8 files that Express fails to deliver as such.
*/
app.use(function(req, res, next) {
if (/.*\.(js|json)$/.test(req.path)) {
res.charset = "utf-8";
}
next();
});
app.use(express.static(sServerRoot));
app.use('/favicon.ico', express.static(path.join(sServerRoot, "versions/icons/current/favicon.ico")));
app.use(slash());
var server = http.createServer(app).listen(app.get('port'), function() {
console.log('Express server listening on port ' + app.get('port'));
});
/*
* socket.io support is still very experimental, so it should not be enabled by default
*/
if (fSockets) {
var io = require('socket.io').listen(server);
io.sockets.on('connection', function(socket) {
if (fConsole) console.log('A new user connected!');
socket.emit('info', { msg: 'The world is round, there is no up or down.' });
});
}