Comparing version 0.0.18 to 0.0.19
module.exports = { | ||
// Startup: pre initializing procedures | ||
startup: { | ||
config: "local", // or you can specify URL to load config from | ||
check: "http://localhost/" // if we can get this page it means that another copy is runing | ||
}, | ||
// Plugins to be loaded using require by Impress | ||
@@ -4,0 +10,0 @@ plugins: { |
@@ -0,1 +1,7 @@ | ||
0.0.19 / 2010-07-04 | ||
================== | ||
* Implemented file uploads: req.impress.files array is accessible in "post.js" handlers | ||
* Startup check to prevent running if another copy is already running | ||
0.0.18 / 2010-07-03 | ||
@@ -5,3 +11,3 @@ ================== | ||
* Fixed routing with regexp simplified syntax (characters auto escaping ".", "?" and "/") | ||
* Added simple routing without regexp | ||
* Added simple routing without regexp | ||
* Added "uglify-js" to minify static js files (using memory cache to avoid multiple minification) | ||
@@ -8,0 +14,0 @@ |
@@ -41,2 +41,3 @@ (function(impress) { | ||
impress.httpErrorCodes = { | ||
400: "Bad request", | ||
404: "File not found", | ||
@@ -43,0 +44,0 @@ 301: "Moved Permanently", |
@@ -22,2 +22,3 @@ (function(impress) { | ||
impress.zlib = require('zlib'); | ||
impress.multiparty = require('multiparty'); | ||
@@ -274,69 +275,84 @@ var configFile = impress.dir+'/config.js', | ||
impress.init = function(callback) { | ||
if (impress.cluster.isMaster) console.log('Impress starting'.bold.green+', reading configuration'.green); | ||
if (impress.cluster.isMaster && impress.config.startup && impress.config.startup.check) { | ||
console.log('Startup check: '.green+impress.config.startup.check); | ||
impress.http.get(impress.config.startup.check, function(res) { | ||
if (res.statusCode == 404) startup(callback); | ||
else { | ||
console.log('Status: server is already started'.green); | ||
process.exit(1); | ||
} | ||
}).on('error', function(e) { | ||
startup(callback); | ||
}); | ||
} else startup(callback); | ||
// Open log files | ||
impress.mkdirp(impress.dir+'/log', function (err) { | ||
if (err) console.error(err); | ||
else { | ||
if (impress.config.log.access) impress.log.fdAccess = impress.fs.createWriteStream( | ||
impress.dir+'/log/'+impress.config.log.access, {flags: 'a'} | ||
); | ||
if (impress.config.log.error) impress.log.fdError = impress.fs.createWriteStream( | ||
impress.dir+'/log/'+impress.config.log.error, {flags: 'a'} | ||
); | ||
} | ||
}); | ||
function startup(callback) { | ||
if (impress.cluster.isMaster) console.log('Impress Application Server starting'.bold.green+', reading configuration'.green); | ||
if(impress.config.databases) impress.openDatabases(callback); | ||
// Open log files | ||
impress.mkdirp(impress.dir+'/log', function (err) { | ||
if (err) console.error(err); | ||
else { | ||
if (impress.config.log.access) impress.log.fdAccess = impress.fs.createWriteStream( | ||
impress.dir+'/log/'+impress.config.log.access, {flags: 'a'} | ||
); | ||
if (impress.config.log.error) impress.log.fdError = impress.fs.createWriteStream( | ||
impress.dir+'/log/'+impress.config.log.error, {flags: 'a'} | ||
); | ||
} | ||
}); | ||
// Config initialization | ||
preprocessConfiguration(); | ||
impress.fs.watch(configFile, function(event, fileName) { | ||
if ((new Date() - configLoadTime)>2000) { | ||
configLoadTime = new Date(); | ||
if (impress.cluster.isMaster) console.log('Reloading server configuration'.green); | ||
impress.restart(); | ||
} | ||
}); | ||
if(impress.config.databases) impress.openDatabases(callback); | ||
// Start workers | ||
if (impress.cluster.isMaster) { | ||
impress.workers = []; | ||
if (impress.config.cluster.strategy == "multiple" || impress.config.cluster.strategy == "sticky") { | ||
for (var workerId = 0; workerId < impress.config.cluster.workers; workerId++) { | ||
if (isFirstStart) impress.spawn(workerId); | ||
// Config initialization | ||
preprocessConfiguration(); | ||
impress.fs.watch(configFile, function(event, fileName) { | ||
if ((new Date() - configLoadTime)>2000) { | ||
configLoadTime = new Date(); | ||
if (impress.cluster.isMaster) console.log('Reloading server configuration'.green); | ||
impress.restart(); | ||
} | ||
} | ||
process.on('SIGINT', impress.shutdown); | ||
process.on('SIGTERM', impress.shutdown); | ||
} else { | ||
process.on('message', function(message, socket) { | ||
if (message.name == 'impress:socket') { | ||
var servers = impress.config.servers; | ||
for (var serverName in servers) { | ||
var server = servers[serverName]; | ||
if (server.address == message.address && server.port == message.port) { | ||
socket.server = server.listener; | ||
server.listener.emit('connection', socket); | ||
}); | ||
// Start workers | ||
if (impress.cluster.isMaster) { | ||
impress.workers = []; | ||
if (impress.config.cluster.strategy == "multiple" || impress.config.cluster.strategy == "sticky") { | ||
for (var workerId = 0; workerId < impress.config.cluster.workers; workerId++) { | ||
if (isFirstStart) impress.spawn(workerId); | ||
} | ||
} | ||
process.on('SIGINT', impress.shutdown); | ||
process.on('SIGTERM', impress.shutdown); | ||
} else { | ||
process.on('message', function(message, socket) { | ||
if (message.name == 'impress:socket') { | ||
var servers = impress.config.servers; | ||
for (var serverName in servers) { | ||
var server = servers[serverName]; | ||
if (server.address == message.address && server.port == message.port) { | ||
socket.server = server.listener; | ||
server.listener.emit('connection', socket); | ||
} | ||
} | ||
} else if (message.name == 'impress:sse') { | ||
// Retranslated SSE from master to worker | ||
//console.dir({workerRetranslated:{message:message, id:impress.workerId}}); | ||
if (message.user) impress.sse.userEvent(message.user, message.eventName, message.data, true); | ||
else if (message.channel) impress.sse.channelEvent(message.channel, message.eventName, message.data, true); | ||
else if (message.global) impress.sse.globalEvent(message.eventName, message.data, true); | ||
} | ||
} else if (message.name == 'impress:sse') { | ||
// Retranslated SSE from master to worker | ||
//console.dir({workerRetranslated:{message:message, id:impress.workerId}}); | ||
}); | ||
} | ||
if (message.user) impress.sse.userEvent(message.user, message.eventName, message.data, true); | ||
else if (message.channel) impress.sse.channelEvent(message.channel, message.eventName, message.data, true); | ||
else if (message.global) impress.sse.globalEvent(message.eventName, message.data, true); | ||
} | ||
}); | ||
} | ||
impress.start(); | ||
impress.start(); | ||
// Set garbage collection interval | ||
var gcInterval = duration(impress.config.cluster.gc); | ||
if (typeof(global.gc) === 'function' && gcInterval > 0) { | ||
setInterval(function () { | ||
global.gc(); | ||
}, gcInterval*1000); | ||
// Set garbage collection interval | ||
var gcInterval = duration(impress.config.cluster.gc); | ||
if (typeof(global.gc) === 'function' && gcInterval > 0) { | ||
setInterval(function () { | ||
global.gc(); | ||
}, gcInterval*1000); | ||
} | ||
} | ||
@@ -368,3 +384,3 @@ } | ||
console.log('Impress shutting down'.bold.green); | ||
process.exit(); | ||
process.exit(0); | ||
} | ||
@@ -462,16 +478,23 @@ | ||
var contentType = req.headers['content-type']; | ||
req.setEncoding('utf8'); | ||
req.impress.data = ""; | ||
req.on("data", function(chunk) { | ||
req.impress.data += chunk; | ||
}); | ||
req.on("end", function() { | ||
if (contentType && contentType.startsWith('multipart')) { // !!!!!!!!!!!!!! | ||
impress.fs.writeFile('./file.dat', req.impress.data, {encoding:'binary'}, function(err) { | ||
if (contentType && contentType.startsWith('multipart')) { // !!!!!!!!!!!!!! | ||
var form = new impress.multiparty.Form(); | ||
form.parse(req, function(err, fields, files) { | ||
if (err) { | ||
impress.error(req, res, 400); | ||
return; | ||
} else { | ||
req.impress.files = files; | ||
restoreSession(req, res); | ||
}); | ||
} else req.post = impress.qs.parse(req.impress.data); | ||
restoreSession(req, res); | ||
}); | ||
} | ||
}); | ||
} else { | ||
req.impress.data = ""; | ||
req.on("data", function(chunk) { | ||
req.impress.data += chunk; | ||
}); | ||
req.on("end", function() { | ||
req.post = impress.qs.parse(req.impress.data); | ||
restoreSession(req, res); | ||
}); | ||
} | ||
} else restoreSession(req, res); | ||
@@ -478,0 +501,0 @@ return; |
{ | ||
"name": "impress", | ||
"version": "0.0.18", | ||
"version": "0.0.19", | ||
"author": "Timur Shemsedinov <timur.shemsedinov@gmail.com>", | ||
@@ -48,3 +48,4 @@ "description": "Impressive totalitarian style multipurpose web application server. All decisions are made. Ready for applied development.", | ||
"geoip-lite": "1.0.x", | ||
"uglify-js": "2.3.x" | ||
"uglify-js": "2.3.x", | ||
"multiparty": "2.1.x" | ||
}, | ||
@@ -51,0 +52,0 @@ "engines": { |
@@ -7,3 +7,2 @@ # TODO | ||
* Separate database access for different sites/applications | ||
* Add support for file uploads (POST requests) | ||
* Add json api example 'auth' for registration, sign in, sign out, recovery password and so on | ||
@@ -17,6 +16,5 @@ * Add examples with web GUI controls | ||
* Make config parameters optional, prosess, route, hosts, etc. | ||
* Implemented file uploads | ||
## Bugs | ||
* Add error messages when starting second copy on same config | ||
* Fixed all known bugs as of now, please report to github |
561223
58
12150
11
799
+ Addedmultiparty@2.1.x
+ Addedmultiparty@2.1.9(transitive)
+ Addedreadable-stream@1.0.34(transitive)
+ Addedstream-counter@0.1.0(transitive)