Comparing version 0.3.0 to 0.4.0
@@ -9,5 +9,3 @@ /** | ||
http = require('http'), | ||
nepp = require('nepp'), | ||
ReqCtrl = require('../request/Controller.js'), | ||
HTTPStatusCodes = require('../http/StatusCodes'); | ||
nepp = require('nepp'); | ||
@@ -17,3 +15,3 @@ /** | ||
* | ||
* The filename to register to may either be a string or a RegExp object. | ||
* The path to register to may either be a string or a RegExp object. | ||
* | ||
@@ -23,17 +21,46 @@ * Please note, that a pattern as a string will NOT work for pattern matching, | ||
* | ||
* @param {String|RegExp} filename Filename to register to. | ||
* @param {Object} options The base controller do not accept any | ||
* options, but inherited objects may do. | ||
* @param {String|RegExp} path Path to register to. | ||
* @param {Object} options Optional options: | ||
* - {String|RegExp} host: Bind this controller | ||
* to a specific host. E.g. "localhost" | ||
* or "www.example.org". May be a | ||
* regular expression object, so | ||
* /.*\.example\.org$/i is also valid. | ||
* Defaults to any host. | ||
* - {Integer|RegExp} port: Bind this controller | ||
* to a specific port. May be a regular | ||
* expression object, so /8.*$/ is | ||
* also valid. Defaults to any port. | ||
* @constructor | ||
*/ | ||
module.exports = function(filename, options) { | ||
module.exports = function(path, options) { | ||
if (!options) options = {}; | ||
else VC.instance_of(options, 'options', Object); | ||
/** | ||
* The filename this controller is registered to. | ||
* The path this controller is registered to. | ||
* | ||
* @protected | ||
* @var {String} | ||
* @var {String|RegExp} | ||
*/ | ||
this._filename = ''; | ||
this._path = ''; | ||
/** | ||
* The host this controller is registered to. | ||
* | ||
* @protected | ||
* @var {String|RegExp} | ||
*/ | ||
this._host = null; | ||
/** | ||
* The port this controller is registered to. | ||
* | ||
* @protected | ||
* @var {Integer|RegExp} | ||
*/ | ||
this._port = null; | ||
/** | ||
* The controller manager will be set on registering the controller. | ||
@@ -63,26 +90,42 @@ * See request.Controller.prototype.addController for details. | ||
try { | ||
this._filename = VC.instance_of(filename, 'filename', RegExp); | ||
this._path = VC.instance_of(path, 'path', RegExp); | ||
} catch (e) { | ||
filename = VC.string(filename, 'filename'); | ||
path = VC.string(path, 'path', false); | ||
if (filename.charAt(0) != '/') { | ||
if (path.charAt(0) != '/') { | ||
throw new Error( | ||
'The static ressource path has to start with a slash. '+ | ||
'Try /' + filename + ' instead' | ||
'Try /' + path + ' instead' | ||
); | ||
} | ||
this._filename = filename; | ||
this._path = path; | ||
} | ||
if (options.host) { | ||
try { | ||
this._host = VC.instance_of(options.host, 'options.host', RegExp); | ||
} catch (e) { | ||
this._host = VC.string(options.host, 'options.host', false); | ||
} | ||
} | ||
if (options.port) { | ||
try { | ||
this._port = VC.instance_of(options.port, 'options.port', RegExp); | ||
} catch (e) { | ||
this._port = VC.string(options.port, 'options.port', false); | ||
} | ||
} | ||
}; | ||
/** | ||
* The filename the controller is registered to. | ||
* The path the controller is registered to. | ||
* | ||
* @member {String|RegExp} filename | ||
* @member {String|RegExp} path | ||
* @readonly | ||
*/ | ||
nepp.createGS(module.exports.prototype, 'filename', | ||
function getFilename() { | ||
return this._filename; | ||
nepp.createGS(module.exports.prototype, 'path', | ||
function getPath() { | ||
return this._path; | ||
} | ||
@@ -92,2 +135,26 @@ ); | ||
/** | ||
* The host the controller is registered to. | ||
* | ||
* @member {String|RegExp} host | ||
* @readonly | ||
*/ | ||
nepp.createGS(module.exports.prototype, 'host', | ||
function getHost() { | ||
return this._host; | ||
} | ||
); | ||
/** | ||
* The port the controller is registered to. | ||
* | ||
* @member {Integer|RegExp} port | ||
* @readonly | ||
*/ | ||
nepp.createGS(module.exports.prototype, 'port', | ||
function getPort() { | ||
return this._port; | ||
} | ||
); | ||
/** | ||
* The response manager. | ||
@@ -203,7 +270,5 @@ * | ||
* into this object directly. | ||
* @param {String} path Fully qualified path to requested object... | ||
*/ | ||
module.exports.prototype.run = function(resp, path) { | ||
module.exports.prototype.run = function(resp) { | ||
VC.instance_of(resp, 'resp', http.ServerResponse); | ||
VC.string(path, 'path', true); | ||
this.responseManager.writeText( | ||
@@ -216,5 +281,6 @@ resp, | ||
'request body:' + JSON.stringify(this.request.body) + "\n" + | ||
'query:' + JSON.stringify(this.request.query), | ||
'path:' + this.request.path + "\n" + | ||
'query:' + JSON.stringify(this.request.query) + "\n", | ||
this.language | ||
); | ||
}; |
@@ -18,24 +18,31 @@ /** | ||
* | ||
* The filename to register to may either be a string or a RegExp object. | ||
* The path to register to may either be a string or a RegExp object. | ||
* Please note, that a pattern as a string will NOT work for pattern matching, | ||
* you have to pass a valid RegExp object to make this feature work. | ||
* | ||
* @param {String|RegExp} filename Filename to register to. | ||
* @param {String|RegExp} path Path to register to. | ||
* @param {Object} options Options are: | ||
* - alwaysForbidden: If this is true, forbidden | ||
* will be echoed always. If | ||
* false and the requested | ||
* ressource doesn't exist, | ||
* 404 will be returned | ||
* instead. Defaults to | ||
* false. | ||
* - htdocsDir: If alwaysForbidden is | ||
* false, the file test will | ||
* be done relatively to this | ||
* directory. Defaults to | ||
* './htdocs'. | ||
* - {Boolean} alwaysForbidden: If this is true, | ||
* forbidden will be echoed always. If | ||
* false and the requested ressource | ||
* doesn't exist, 404 will be returned | ||
* instead. Defaults to false. | ||
* - {String} htdocsDir: If alwaysForbidden is | ||
* false, the file test will be done | ||
* relatively to this directory. | ||
* Defaults to './htdocs'. | ||
* - {String|RegExp} host: Bind this controller | ||
* to a specific host. E.g. "localhost" | ||
* or "www.example.org". May be a | ||
* regular expression object, so | ||
* /.*\.example\.org$/i is also valid. | ||
* Defaults to any host. | ||
* - {Integer|RegExp} port: Bind this controller | ||
* to a specific port. May be a regular | ||
* expression object, so /8.*$/ is | ||
* also valid. Defaults to any port. | ||
* @constructor | ||
*/ | ||
module.exports = function(filename, options) { | ||
Base.call(this, filename, options); | ||
module.exports = function(path, options) { | ||
Base.call(this, path, options); | ||
@@ -73,9 +80,8 @@ if (!options) options = {}; | ||
* into this object directly. | ||
* @param {String} path Fully qualified path to requested object. | ||
*/ | ||
module.exports.prototype.run = function(resp, path) { | ||
module.exports.prototype.run = function(resp) { | ||
VC.instance_of(resp, 'resp', http.ServerResponse); | ||
if (!this.alwaysForbidden) { | ||
var path = this.htdocsDir + path; | ||
var path = this.htdocsDir + this.request.path; | ||
var _this = this; | ||
@@ -93,2 +99,4 @@ fs.exists(path, function(exists) { | ||
// {{{ Getter/Setter | ||
/** | ||
@@ -120,1 +128,2 @@ * If this is true, forbidden will be echoed always. If false and the requested | ||
// }}} |
@@ -9,4 +9,5 @@ /** | ||
Forbidden: require('./Forbidden'), | ||
Redirect: require('./Redirect'), | ||
Static: require('./Static'), | ||
Swig: require('./Swig') | ||
}; |
@@ -61,7 +61,5 @@ /** | ||
* this object directly. | ||
* @param String path Fully qualified path to requested object.. | ||
*/ | ||
REST.prototype.run = function(resp, path) { | ||
REST.prototype.run = function(resp) { | ||
VC.instance_of(resp, 'resp', http.ServerResponse); | ||
VC.string(path, 'path', true); | ||
@@ -68,0 +66,0 @@ switch (this.request.method) { |
@@ -21,15 +21,25 @@ /** | ||
* | ||
* The filename to register to may either be a string or a RegExp object. | ||
* The path to register to may either be a string or a RegExp object. | ||
* Please note, that a pattern as a string will NOT work for pattern matching, | ||
* you have to pass a valid RegExp object to make this feature work. | ||
* | ||
* @param {String|RegExp} filename Filename to register to. | ||
* @param {String|RegExp} path Path to register to. | ||
* @param {Object} options Options: | ||
* - htdocsDir: The files to serve are relative | ||
* to this directory. Defaults to | ||
* './htdocs'. | ||
* - {String} htdocsDir: The files to serve | ||
* are relative to this directory. | ||
* Defaults to './htdocs'. | ||
* - {String|RegExp} host: Bind this controller | ||
* to a specific host. E.g. "localhost" | ||
* or "www.example.org". May be a | ||
* regular expression object, so | ||
* /.*\.example\.org$/i is also valid. | ||
* Defaults to any host. | ||
* - {Integer|RegExp} port: Bind this controller | ||
* to a specific port. May be a regular | ||
* expression object, so /8.*$/ is | ||
* also valid. Defaults to any port. | ||
* @constructor | ||
*/ | ||
module.exports = function(filename, options) { | ||
Base.call(this, filename, options); | ||
module.exports = function(path, options) { | ||
Base.call(this, path, options); | ||
@@ -56,10 +66,8 @@ if (!options) options = {}; | ||
* The header (especially the content type) is always determined by the | ||
* filename provided. | ||
* path provided. | ||
* | ||
* @param {http.ServerResponse} resp Server response Object. Write your data | ||
* into this object directly. | ||
* @param {String} path Fully qualified path to requested object. | ||
*/ | ||
module.exports.prototype.run = function(resp, path) { | ||
module.exports.prototype.run = function(resp) { | ||
if (this.request.method != 'GET') { | ||
@@ -73,3 +81,3 @@ this.responseManager.writeMethodNotAllowed( | ||
this._serveStatic( | ||
this.htdocsDir + VC.string(path, 'path', true), | ||
this.htdocsDir + this.request.path, | ||
VC.instance_of(resp, 'resp', http.ServerResponse) | ||
@@ -82,3 +90,3 @@ ); | ||
* | ||
* @param {String} filename File to serve. | ||
* @param {String} path File to serve. | ||
* @param {http.ServerResponse} resp Server response Object. Write your data | ||
@@ -88,7 +96,7 @@ * into this object directly. | ||
*/ | ||
module.exports.prototype._serveStatic = function(filename, resp) { | ||
module.exports.prototype._serveStatic = function(path, resp) { | ||
var _this = this; | ||
var mime = new Mime(filename); | ||
var mime = new Mime(path); | ||
fs.exists(filename, function(exists) { | ||
fs.exists(path, function(exists) { | ||
if (exists) { | ||
@@ -102,3 +110,3 @@ var header = { | ||
if (mime.mime == 'image') { | ||
fs.stat(filename, function(err, stat) { | ||
fs.stat(path, function(err, stat) { | ||
if (err) | ||
@@ -110,3 +118,3 @@ _this.emit('error', err); | ||
var rs = fs.createReadStream(filename); | ||
var rs = fs.createReadStream(path); | ||
rs.pipe(resp); | ||
@@ -119,3 +127,3 @@ rs.on('error', function(err) { | ||
} else { | ||
fs.readFile(filename, function(err, content) { | ||
fs.readFile(path, function(err, content) { | ||
if (err) { | ||
@@ -133,3 +141,3 @@ _this.emit('error', err); | ||
} else { | ||
_this.responseManager.writeNotFound(resp, filename, _this.language); | ||
_this.responseManager.writeNotFound(resp, path, _this.language); | ||
} | ||
@@ -136,0 +144,0 @@ }); |
@@ -252,4 +252,2 @@ /** | ||
// REDIRECT HERE | ||
_this.requestManager._requestData = requestData; | ||
@@ -256,0 +254,0 @@ _this.requestManager.run(resp, filename); |
@@ -15,2 +15,3 @@ /** | ||
_ = require('underscore'), | ||
regexp = require('../regexp'), | ||
VC = require('valuechecker'); | ||
@@ -27,3 +28,3 @@ | ||
/** | ||
* Maps filenames to their controller. | ||
* Maps paths to their controller. | ||
* | ||
@@ -34,9 +35,2 @@ * @protected | ||
/** | ||
* Ordered array of regex controllers. First match found will be used.. | ||
* | ||
* @protected | ||
*/ | ||
this._controllers_regexp = []; | ||
nepp(this); | ||
@@ -50,21 +44,38 @@ }; | ||
* | ||
* @param {controller.Helper} controller The controller to add. | ||
* @param {controller.Base} controller The controller to add. | ||
*/ | ||
module.exports.prototype.addController = function(controller) { | ||
var filename = controller.filename; | ||
VC.instance_of(controller, 'controller', require('../controller/Base')); | ||
var path = controller.path; | ||
var host = controller.host || '*'; | ||
var port = controller.port || '*'; | ||
if (filename instanceof RegExp) { | ||
// Add on stack, that we will search later | ||
this._controllers_regexp.push(VC.instance_of( | ||
controller, 'controller', require('../controller/Base.js') | ||
)); | ||
this._controllers_regexp[this._controllers_regexp.length - 1] | ||
._requestController = this; | ||
if (_.isEqual(path, regexp.all)) path = '*'; | ||
if (_.isEqual(host, regexp.all)) host = '*'; | ||
if (_.isEqual(port, regexp.all)) port = '*'; | ||
controller._requestController = this; | ||
if (host instanceof RegExp) { | ||
if (!this._controllers.__RegExp) | ||
this._controllers.__RegExp = []; | ||
this._controllers.__RegExp.push(controller); | ||
} else { | ||
// Add to map of static files | ||
this._controllers[filename] | ||
= VC.instance_of( | ||
controller, 'controller', require('../controller/Base.js') | ||
); | ||
this._controllers[filename]._requestController = this; | ||
if (!this._controllers[host]) | ||
this._controllers[host] = {}; | ||
if (port instanceof RegExp) { | ||
if (!this._controllers[host].__RegExp) | ||
this._controllers[host].__RegExp = []; | ||
this._controllers[host].__RegExp.push(controller); | ||
} else { | ||
if (!this._controllers[host][port]) | ||
this._controllers[host][port] = {}; | ||
if (path instanceof RegExp) { | ||
if (!this._controllers[host][port].__RegExp) | ||
this._controllers[host][port].__RegExp = []; | ||
this._controllers[host][port].__RegExp.push(controller); | ||
} else { | ||
this._controllers[host][port][path] = controller; | ||
} | ||
} | ||
} | ||
@@ -75,20 +86,104 @@ | ||
/** | ||
* Returns the controller registered for the given filename. | ||
* Returns the controller registered for the given path. | ||
* | ||
* The static (non-regexp) controllers will be checked first. Iff no static | ||
* controller matches perfectly the given filename, the RegExp ones will be | ||
* controller matches perfectly the given path, the RegExp ones will be | ||
* checked. | ||
* | ||
* @param {String} filename Filename. | ||
* @returns {controller.Helper} | ||
* @param {String} host Host. | ||
* @param {Integer} port Port. | ||
* @param {String} path Path. | ||
* @returns {controller.Base} | ||
*/ | ||
module.exports.prototype.getController = function(filename) { | ||
// Static file names have highest prio, always | ||
if (this._controllers[filename]) { | ||
return this._controllers[filename]; | ||
module.exports.prototype.getController = function(host, port, path) { | ||
VC.string(host, 'host', false); | ||
VC.int(port, 'port', 0); | ||
VC.string(path, 'path', false); | ||
var equals = function(a, b, hard) { | ||
if (hard) return a == b; | ||
return (a instanceof RegExp && a.exec(b)); | ||
} | ||
for (var i = this._controllers_regexp.length - 1; i >= 0; --i) { | ||
if (this._controllers_regexp[i].filename.exec(filename)) | ||
return this._controllers_regexp[i]; | ||
var _c = this._controllers; | ||
var hostarr = [host, '*']; | ||
var portarr = [port, '*']; | ||
var checkarr = [true, false]; | ||
// Prio 1: host, port and path: perfect hit, then * hit | ||
for (var hi = 0; hi < hostarr.length; ++hi) { | ||
var h = hostarr[hi]; | ||
for (var pi = 0; pi < portarr.length; ++pi) { | ||
var p = portarr[pi]; | ||
if (_c[h] && _c[h][p] && _c[h][p][path]) return _c[h][p][path]; | ||
if (_c[h] && _c[h][p] && _c[h][p]['*']) return _c[h][p]['*']; | ||
} | ||
} | ||
// Prio 2: host and port are perfect or *, path is regex hit | ||
for (var hi = 0; hi < hostarr.length; ++hi) { | ||
var h = hostarr[hi]; | ||
for (var pi = 0; pi < portarr.length; ++pi) { | ||
var p = portarr[pi]; | ||
if (_c[h] && _c[h][p] && _c[h][p].__RegExp) { | ||
for (var i = 0; i < _c[h][p].__RegExp.length; ++i) { | ||
if (equals(_c[h][p].__RegExp[i].path, path, false)) | ||
return _c[h][p].__RegExp[i]; | ||
} | ||
} | ||
} | ||
} | ||
// Prio 3: host is perfect or *, port is regex, path is perfect | ||
// Prio 4: host is regex, port is perfect or *, path is perfect | ||
// Prio 5: As 3, but path is regex | ||
// Prio 6: As 4, but path is regex | ||
for (var ci = 0; ci < checkarr.length; ++ci) { | ||
var hard_check = checkarr[ci]; | ||
for (var hi = 0; hi < hostarr.length; ++hi) { | ||
var h = hostarr[hi]; | ||
if (_c[h] && _c[h].__RegExp) { | ||
for (var i = 0; i < _c[h].__RegExp.length; ++i) { | ||
if (equals(_c[h].__RegExp[i].port, port, false) | ||
&& equals(_c[h].__RegExp[i].path, path, hard_check) | ||
) { | ||
return _c[h].__RegExp[i]; | ||
} | ||
} | ||
} | ||
} | ||
if (_c.__RegExp) { | ||
for (var i = 0; i < _c.__RegExp.length; ++i) { | ||
if (equals(_c.__RegExp[i].host, host, false)) { | ||
for (var pi = 0; pi < portarr.length; ++pi) { | ||
var p = portarr[pi]; | ||
if (equals(_c.__RegExp[i].port, p, true) | ||
&& equals(_c.__RegExp[i].path, path, hard_check) | ||
) { | ||
return _c.__RegExp[i]; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
// Prio 7: path and port are regex, path is perfect | ||
// Prio 8: path and port and path are regex | ||
if (_c.__RegExp) { | ||
for (var ci = 0; ci < checkarr.length; ++ci) { | ||
var hard_check = checkarr[ci]; | ||
for (var i = 0; i < _c.__RegExp.length; ++i) { | ||
if (equals(_c.__RegExp[i].host, host, false) | ||
&& equals(_c.__RegExp[i].port, port, false) | ||
&& equals(_c.__RegExp[i].port, port, hard_check) | ||
) { | ||
return _c.__RegExp[i]; | ||
} | ||
} | ||
} | ||
} | ||
return null; | ||
@@ -98,48 +193,23 @@ }; | ||
/** | ||
* Removes all controllers registered to it. | ||
*/ | ||
module.exports.prototype.removeAllControllers = function() { | ||
this._controllers = {}; | ||
}; | ||
/** | ||
* Removes a controller. | ||
* | ||
* The controller may be identified by either the instance, that had been | ||
* added before, or the filename the controller is bound to. | ||
* added before, or the path the controller is bound to. | ||
* | ||
* @param {controller.Helper|String|RegExp} id Either controller instance or | ||
* filename. | ||
* @param {controller.Base|String|RegExp} id Either controller instance or | ||
* path. | ||
* @returns {Boolean} If the controller was found. | ||
*/ | ||
module.exports.prototype.removeController = function(id) { | ||
if (id instanceof require('../controller/Base.js')) { | ||
var deleted = false; | ||
[ this._controllers_regexp, this._controllers ].forEach( | ||
function(elem, index, arr) { | ||
if (deleted) return; | ||
for (var i in arr[index]) { | ||
if (arr[index][i].filename == id.filename) { | ||
if (_.isArray(arr[index])) | ||
arr[index].splice(i,1); | ||
else | ||
delete arr[index][i]; | ||
deleted = true; | ||
} | ||
} | ||
} | ||
); | ||
return deleted; | ||
} else if (typeof(id) == 'string') { | ||
if (this._controllers[id]) { | ||
delete this._controllers[id]; | ||
return true; | ||
} | ||
} else if (id instanceof RegExp) { | ||
for (var i = 0; i < this._controllers_regexp.length; ++i) { | ||
if (_.isEqual(this._controllers_regexp[i].filename, id)) { | ||
this._controllers_regexp.splice(i,1); | ||
return true; | ||
} | ||
} | ||
} else { | ||
throw new Error( | ||
"id has to be of type String, RegExp or controller.Helper; " + id + | ||
" given; type is " + typeof(id) | ||
); | ||
} | ||
// TODO | ||
return false; | ||
}; | ||
@@ -150,24 +220,21 @@ | ||
* | ||
* If a controller is registered to the given filename, then its output will be | ||
* written to the response object. Otherwise it'll be tried to load the static | ||
* file from hard disk and its content will be written to the reponse object. | ||
* If a controller is registered to the given path, then its output will be | ||
* written to the response object. | ||
* | ||
* @param {http.ServerResponse} resp Server response Object. Write your data | ||
* into this object directly. | ||
* @param {String} filename Request path and filename. | ||
* This emits an error, if the controller throws. | ||
* | ||
* @param {http.ServerResponse} resp Server response Object. Write your data | ||
* into this object directly. | ||
* @param {mvcfun.controller.Base} ctrl Controller to run. | ||
*/ | ||
module.exports.prototype.run = function(resp, filename) { | ||
VC.string(filename, 'filename', true); | ||
module.exports.prototype.run = function(resp, ctrl) { | ||
VC.instance_of(resp, 'resp', http.ServerResponse); | ||
var c = this.getController(filename); | ||
VC.instance_of(ctrl, 'ctrl', require('../controller/Base.js')); | ||
if (c) { | ||
try { | ||
c.run(resp, filename); | ||
} catch(err) { | ||
this.emit('error', err); | ||
} | ||
} else | ||
this.responseManager.writeNotFound(resp); | ||
try { | ||
ctrl.run(resp); | ||
} catch(err) { | ||
this.emit('error', err); | ||
} | ||
}; | ||
@@ -17,2 +17,3 @@ /** | ||
* @param {String} rawBody Raw body. | ||
* @constructor | ||
*/ | ||
@@ -51,5 +52,14 @@ module.exports = function(req, rawBody) { | ||
/** | ||
* Contains the request path. | ||
* | ||
* @var {String} | ||
* @protected | ||
*/ | ||
this._path = ''; | ||
if (req.url) { | ||
this._query = url.parse(req.url, true).query || {}; | ||
var tmp = url.parse(req.url, true); | ||
this._query = tmp.query || {}; | ||
this._path = tmp.pathname || ''; | ||
} | ||
@@ -69,3 +79,2 @@ | ||
/** | ||
@@ -132,2 +141,14 @@ * Contains the host the request was sent to, e.g. 'localhost' or | ||
/** | ||
* The path requested (without query string and without fragment). | ||
* | ||
* @member {Object} path | ||
* @readonly | ||
*/ | ||
nepp.createGS(module.exports.prototype, 'path', | ||
function getPath() { | ||
return this._path; | ||
} | ||
); | ||
/** | ||
* The parsed body object. | ||
@@ -134,0 +155,0 @@ * |
@@ -7,6 +7,6 @@ /** | ||
module.exports = { | ||
Controller: require('./Controller'), | ||
Data: require('./Data'), | ||
Helper: require('./Helper'), | ||
Controller: require('./Controller'), | ||
Manager: require('./Manager'), | ||
Data: require('./Data') | ||
Manager: require('./Manager') | ||
}; |
@@ -97,4 +97,10 @@ /** | ||
if (this.requestController.getController(filename)) | ||
this.requestController.run(resp, filename); | ||
var ctrl = this.requestController.getController( | ||
this.requestData.host, | ||
this.requestData.port, | ||
filename | ||
); | ||
if (ctrl) | ||
this.requestController.run(resp, ctrl); | ||
else | ||
@@ -101,0 +107,0 @@ this.responseManager.writeNotFound(resp); |
@@ -211,2 +211,24 @@ /** | ||
/** | ||
* Writes a redirect (http status and location header). | ||
* | ||
* @param {http.ServerResponse} resp Response object. | ||
* @param {String} uri Uri to direct to. | ||
*/ | ||
module.exports.prototype.writeRedirect = function(resp, status, uri) { | ||
VC.instance_of(resp, 'resp', http.ServerResponse); | ||
resp.writeHead(status, {Location: uri}); | ||
resp.end(); | ||
}; | ||
/** | ||
* Writes a 301 redirect (moved permanently). | ||
* | ||
* @param {http.ServerResponse} resp Response Object. | ||
* @param {String} uri Uri to direct to. | ||
*/ | ||
module.exports.prototype.writeMovedPermanently = function(resp, uri) { | ||
this.writeRedirect(resp, HTTPStatusCodes.MOVED_PERMANENTLY, uri); | ||
}; | ||
/** | ||
* The charset that will be used for all responses. | ||
@@ -213,0 +235,0 @@ * |
{ | ||
"name": "mvcfun", | ||
"version": "0.3.0", | ||
"version": "0.4.0", | ||
"description": "MVC based web server framework", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -34,3 +34,3 @@ /** | ||
reqCtrl.addController(ctrl); | ||
ctrl.run(resp, '/1'); | ||
reqCtrl.run(resp, ctrl); | ||
}); | ||
@@ -47,3 +47,3 @@ it('should send the correct Content-Language header', function(done) { | ||
reqCtrl.addController(ctrl); | ||
ctrl.run(resp, '/1'); | ||
reqCtrl.run(resp, ctrl); | ||
}); | ||
@@ -50,0 +50,0 @@ }) |
@@ -53,3 +53,3 @@ /** | ||
ctrl.run(httpresp, '/filename'); | ||
reqCtrl.run(httpresp, ctrl); | ||
} | ||
@@ -78,2 +78,3 @@ })(languages[l]) | ||
reqMan._requestData = {path: '/filename'}; | ||
var ctrl = new mvcfun.controller.Forbidden( | ||
@@ -86,3 +87,3 @@ '/filename', | ||
ctrl.run(httpresp, '/filename'); | ||
reqCtrl.run(httpresp, ctrl); | ||
} | ||
@@ -118,2 +119,3 @@ })(languages[l]) | ||
reqMan._requestData = {path: '/filename'} | ||
var ctrl = new mvcfun.controller.Forbidden( | ||
@@ -125,4 +127,3 @@ '/filename', | ||
ctrl.language = language; | ||
ctrl.run(httpresp, '/filename'); | ||
reqCtrl.run(httpresp, ctrl); | ||
}); | ||
@@ -129,0 +130,0 @@ } |
@@ -59,9 +59,9 @@ /** | ||
); | ||
var req = new http.IncomingMessage(); | ||
req.method = 'GET'; | ||
ctrl.language = language; | ||
reqCtrl.addController(ctrl); | ||
reqCtrl.requestManager._requestData | ||
= new mvcfun.request.Data(req, ''); | ||
ctrl.run(resp, '/1'); | ||
reqMan._requestData = { | ||
path: '/1', | ||
method: 'GET' | ||
} | ||
reqCtrl.run(resp, ctrl); | ||
}); | ||
@@ -110,9 +110,9 @@ } | ||
); | ||
var req = new http.IncomingMessage(); | ||
req.method = method; | ||
ctrl.language = language; | ||
reqCtrl.addController(ctrl); | ||
reqCtrl.requestManager._requestData | ||
= new mvcfun.request.Data(req, ''); | ||
ctrl.run(resp, '/1'); | ||
reqMan._requestData = { | ||
path: '/1', | ||
method: method | ||
} | ||
reqCtrl.run(resp, ctrl); | ||
}); | ||
@@ -119,0 +119,0 @@ } |
@@ -23,25 +23,174 @@ /** | ||
describe('#addController', function() { | ||
it( | ||
'should add a controller for a string filename', | ||
function() { | ||
var ctrl = new mvcfun.controller.Base('/filename.html'); | ||
reqCtrl.addController(ctrl); | ||
reqCtrl.getController('/filename.html') | ||
.should.equal(ctrl); | ||
} | ||
); | ||
it( | ||
'should add a controller for a regexp filename', | ||
function() { | ||
var ctrl = new mvcfun.controller.Base(/huhu/i); | ||
reqCtrl.addController(ctrl); | ||
reqCtrl.getController('/huhu.html') | ||
.should.equal(ctrl); | ||
reqCtrl.getController('huHu.o') | ||
.should.equal(ctrl); | ||
reqCtrl.getController('/jh/HUHU') | ||
.should.equal(ctrl); | ||
} | ||
); | ||
var cases = [ | ||
[ // 0 | ||
['/filename.html', undefined, undefined], | ||
['www.example.org', 80, '/filename.html'], | ||
true | ||
], | ||
[ // 1 | ||
['/filename.html', undefined, undefined], | ||
['anyany', 88930 /*any*/, '/filename.html'], | ||
true | ||
], | ||
[ | ||
['/filename.html', undefined, undefined], | ||
['anyany', 80, '/wrong.html'], | ||
false | ||
], | ||
[ | ||
['/filename.html', 'www.example.org', undefined], | ||
['www.example.org', 80, '/filename.html'], | ||
true | ||
], | ||
[ | ||
['/filename.html', 'www.example.org', undefined], | ||
['www.example.org', 8028 /*any*/, '/filename.html'], | ||
true | ||
], | ||
[ // 5 | ||
['/filename.html', 'www.example.org', undefined], | ||
['wrong.org', 80, '/filename.html'], | ||
false | ||
], | ||
[ | ||
['/filename.html', 'www.example.org', undefined], | ||
['www.example.org', 80, '/wrong.html'], | ||
false | ||
], | ||
[ | ||
['/filename.html', 'www.example.org', 8080], | ||
['www.example.org', 8080, '/filename.html'], | ||
true | ||
], | ||
[ | ||
['/filename.html', 'www.example.org', 8080], | ||
['wrong.org', 8080, '/filename.html'], | ||
false | ||
], | ||
[ | ||
['/filename.html', 'www.example.org', 8080], | ||
['www.example.org', 80 /*wrong*/, '/filename.html'], | ||
false | ||
], | ||
[ // 10 | ||
['/filename.html', 'www.example.org', 8080], | ||
['www.example.org', 8080, '/wrong.html'], | ||
false | ||
], | ||
[ | ||
[/name\.html$/i, undefined, undefined], | ||
['www.example.org', 80, '/filenAmE.html'], | ||
true | ||
], | ||
[ | ||
[/name\.html$/i, undefined, undefined], | ||
['anyany', 88930 /*any*/, '/filename.html'], | ||
true | ||
], | ||
[ | ||
[/name\.html$/i, undefined, undefined], | ||
['anyany', 80, '/wrong.html'], | ||
false | ||
], | ||
[ | ||
[/name\.html$/i, 'www.example.org', undefined], | ||
['www.example.org', 80, '/filename.html'], | ||
true | ||
], | ||
[ // 15 | ||
[/name\.html$/i, 'www.example.org', undefined], | ||
['www.example.org', 8028 /*any*/, '/filename.html'], | ||
true | ||
], | ||
[ | ||
[/name\.html$/i, 'www.example.org', undefined], | ||
['wrong.org', 80, '/filename.html'], | ||
false | ||
], | ||
[ | ||
[/name\.html$/i, 'www.example.org', undefined], | ||
['www.example.org', 80, '/wrong.html'], | ||
false | ||
], | ||
[ | ||
[/name\.html$/i, 'www.example.org', 8080], | ||
['www.example.org', 8080, '/filename.html'], | ||
true | ||
], | ||
[ | ||
[/name\.html$/i, 'www.example.org', 8080], | ||
['wrong.org', 8080, '/filename.html'], | ||
false | ||
], | ||
[ // 20 | ||
[/name\.html$/i, 'www.example.org', 8080], | ||
['www.example.org', 80 /*wrong*/, '/filename.html'], | ||
false | ||
], | ||
[ | ||
[/name\.html$/i, 'www.example.org', 8080], | ||
['www.example.org', 8080, '/wrong.html'], | ||
false | ||
], | ||
[ | ||
[/name\.html$/i, /\.example\.org$/, 8080], | ||
['www.example.org', 8080, '/filename.html'], | ||
true | ||
], | ||
[ | ||
[/name\.html$/i, /\.example\.org$/, 8080], | ||
['lala.example.org', 8080, '/filenAme.html'], | ||
true | ||
], | ||
[ | ||
[/name\.html$/i, /\.example\.org$/, 8080], | ||
['wrong.org', 8080, '/filenAme.html'], | ||
false | ||
], | ||
[ // 25 | ||
[/name\.html$/i, /\.example\.org$/, /^88*$/], | ||
['www.example.org', 8, '/filenAme.html'], | ||
true | ||
], | ||
[ | ||
[/name\.html$/i, /\.example\.org$/, /^88*$/], | ||
['.example.org', 8888, '/filenAme.html'], | ||
true | ||
] | ||
]; | ||
for (var i = 0; i < cases.length; ++i) { | ||
it('should add a single controller controller [Case ' + i + ']', | ||
(function(ctrlConstrParams, getCtrlParams, result) { | ||
return function() { | ||
reqCtrl.removeAllControllers(); | ||
var ctrl = new mvcfun.controller.Base( | ||
ctrlConstrParams[0], | ||
{ | ||
host: ctrlConstrParams[1], | ||
port: ctrlConstrParams[2] | ||
} | ||
); | ||
reqCtrl.addController(ctrl); | ||
var ctrlResult = reqCtrl.getController( | ||
getCtrlParams[0], | ||
getCtrlParams[1], | ||
getCtrlParams[2] | ||
); | ||
if (result) | ||
ctrlResult.should.equal(ctrl); | ||
else | ||
(ctrlResult === null).should.be.true; | ||
} | ||
})(cases[i][0], cases[i][1], cases[i][2])); | ||
} | ||
}); | ||
@@ -52,3 +201,3 @@ | ||
// | ||
describe('#removeController', function() { | ||
/* describe('#removeController', function() { | ||
it( | ||
@@ -102,3 +251,3 @@ 'should remove a controller by string filename', | ||
); | ||
}); | ||
});*/ | ||
@@ -128,34 +277,4 @@ // | ||
reqCtrl.addController(myCtrl); | ||
reqCtrl.run(resp, '/x.file'); | ||
reqCtrl.run(resp, myCtrl); | ||
}); | ||
it('should output 404 if controller does not exist on run', | ||
function(done) { | ||
var resp = new http.ServerResponse({'GET': 'GET'}); | ||
resp.end = function(content) { | ||
this.should.have.status( | ||
mvcfun.http.StatusCodes.NOT_FOUND | ||
); | ||
done(); | ||
}; | ||
reqCtrl.run(resp, '/y.file'); | ||
} | ||
); | ||
it('should call the last added controller on regexp overlap', | ||
function(done) { | ||
var ctrl1 = new mvcfun.controller.Base(/a/); | ||
ctrl1.run = function(resp, path) { | ||
done('Must not be called!'); | ||
}; | ||
var ctrl2 = new mvcfun.controller.Base(/ab/); | ||
ctrl2.run = function(resp, path) { | ||
done(); | ||
}; | ||
var resp = new http.ServerResponse({'GET': 'GET'}); | ||
reqCtrl.addController(ctrl1); | ||
reqCtrl.addController(ctrl2); | ||
reqCtrl.run(resp, '/ababaa'); | ||
} | ||
); | ||
it('should emit error if controller throws', function(done) { | ||
@@ -179,6 +298,5 @@ var myCtrl = new mvcfun.controller.Base('/z.file'); | ||
reqCtrl.addController(myCtrl); | ||
reqCtrl.run(new Resp(), '/z.file'); | ||
reqCtrl.removeController('/z.file').should.be.true; | ||
reqCtrl.run(new Resp(), myCtrl); | ||
}); | ||
}); | ||
}); |
@@ -28,4 +28,3 @@ /** | ||
util.inherits(ReqCtrlMock, mvcfun.request.Controller); | ||
ReqCtrlMock.prototype.run = function(resp, f) { | ||
f.should.equal(filename); | ||
ReqCtrlMock.prototype.run = function(resp) { | ||
resp.should.equal(httpresp); | ||
@@ -42,2 +41,3 @@ done(); | ||
); | ||
reqMan._requestData = {host: 'example.org', port:80}; | ||
reqMan.run(httpresp, filename); | ||
@@ -70,2 +70,3 @@ } | ||
); | ||
reqMan._requestData = {host: 'example.org', port:80}; | ||
reqMan.run(httpresp, 'not_registerd_file'); | ||
@@ -72,0 +73,0 @@ } |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
139690
41
3927
20