Fixing iron:router issue with latest Chrome version
This commit is contained in:
parent
3734b5f31a
commit
6f23c7163a
@ -26,8 +26,8 @@ clinical:hipaa-audit-log@2.4.2
|
|||||||
clinical:hipaa-logger@1.0.1
|
clinical:hipaa-logger@1.0.1
|
||||||
clinical:router@2.0.17
|
clinical:router@2.0.17
|
||||||
clinical:router-location@2.0.14
|
clinical:router-location@2.0.14
|
||||||
clinical:router-middleware-stack@2.0.13
|
clinical:router-middleware-stack@2.1.2
|
||||||
clinical:router-url@2.0.15
|
clinical:router-url@2.1.0
|
||||||
clinical:theming@0.4.10
|
clinical:theming@0.4.10
|
||||||
coffeescript@1.0.11
|
coffeescript@1.0.11
|
||||||
cornerstone@0.0.1
|
cornerstone@0.0.1
|
||||||
|
|||||||
@ -14,8 +14,8 @@ callback-hook@1.0.4
|
|||||||
check@1.1.0
|
check@1.1.0
|
||||||
clinical:router@2.0.17
|
clinical:router@2.0.17
|
||||||
clinical:router-location@2.0.14
|
clinical:router-location@2.0.14
|
||||||
clinical:router-middleware-stack@2.0.13
|
clinical:router-middleware-stack@2.1.2
|
||||||
clinical:router-url@2.0.15
|
clinical:router-url@2.1.0
|
||||||
coffeescript@1.0.11
|
coffeescript@1.0.11
|
||||||
cornerstone@0.0.1
|
cornerstone@0.0.1
|
||||||
ddp@1.2.2
|
ddp@1.2.2
|
||||||
|
|||||||
6
Packages/router-middleware-stack/.gitignore
vendored
Normal file
6
Packages/router-middleware-stack/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.DS_Store
|
||||||
|
.npm
|
||||||
|
.build*
|
||||||
|
smart.lock
|
||||||
|
versions.json
|
||||||
|
.versions
|
||||||
3
Packages/router-middleware-stack/History.md
Normal file
3
Packages/router-middleware-stack/History.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
v1.0.11 / 2015-10-09
|
||||||
|
==================
|
||||||
|
* Support Meteor 1.2
|
||||||
21
Packages/router-middleware-stack/LICENSE.txt
Normal file
21
Packages/router-middleware-stack/LICENSE.txt
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 EventedMind <chris@eventedmind.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
18
Packages/router-middleware-stack/README.md
Normal file
18
Packages/router-middleware-stack/README.md
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
Clinical Router MiddlewareStack
|
||||||
|
==============================================================================
|
||||||
|
|
||||||
|
Client and server middleware support inspired by Connect.
|
||||||
|
|
||||||
|
===============================
|
||||||
|
#### Installation
|
||||||
|
|
||||||
|
This package is a dependency of ``clinical:router``. Just install the router package, and you'll get this included.
|
||||||
|
|
||||||
|
````bash
|
||||||
|
meteor add clinical:router
|
||||||
|
````
|
||||||
|
|
||||||
|
===============================
|
||||||
|
#### Licensing
|
||||||
|
|
||||||
|

|
||||||
57
Packages/router-middleware-stack/circle.yml
Normal file
57
Packages/router-middleware-stack/circle.yml
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
## Customize the test machine
|
||||||
|
machine:
|
||||||
|
|
||||||
|
# Timezone
|
||||||
|
timezone:
|
||||||
|
America/Los_Angeles # Set the timezone
|
||||||
|
|
||||||
|
# Add some environment variables
|
||||||
|
environment:
|
||||||
|
CIRCLE_ENV: test
|
||||||
|
CXX: g++-4.8
|
||||||
|
DISPLAY: :99.0
|
||||||
|
NPM_PREFIX: /home/ubuntu/nvm/v0.10.33
|
||||||
|
|
||||||
|
#general:
|
||||||
|
# build_dir: helloworld
|
||||||
|
|
||||||
|
## Customize dependencies
|
||||||
|
dependencies:
|
||||||
|
cache_directories:
|
||||||
|
- ~/.meteor # relative to the user's home directory
|
||||||
|
- ~/nvm/v0.10.33/lib/node_modules/starrynight
|
||||||
|
- ~/nvm/v0.10.33/bin/starrynight
|
||||||
|
|
||||||
|
pre:
|
||||||
|
# Install Starrynight unless it is cached
|
||||||
|
- if [ ! -e ~/nvm/v0.10.33/bin/starrynight ]; then npm install -g starrynight; else echo "Starrynight seems to be cached"; fi;
|
||||||
|
# Install Meteor
|
||||||
|
- mkdir -p ${HOME}/.meteor
|
||||||
|
# If Meteor is already cached, do not need to build it again.
|
||||||
|
- if [ ! -e ${HOME}/.meteor/meteor ]; then curl https://install.meteor.com | /bin/sh; else echo "Meteor seems to be cached"; fi;
|
||||||
|
# Link the meteor executable into /usr/bin
|
||||||
|
- sudo ln -s $HOME/.meteor/meteor /usr/bin/meteor
|
||||||
|
# Check if the helloworld directory already exists, if it doesn't, create the helloworld app
|
||||||
|
- if [ ! -e ${HOME}/helloworld ]; then meteor create --release METEOR@1.1.0.3 helloworld; else echo "helloworld app seems to be cached"; fi;
|
||||||
|
|
||||||
|
override:
|
||||||
|
- cd helloworld
|
||||||
|
- cd helloworld && ls -la
|
||||||
|
- cd helloworld && rm helloworld.*
|
||||||
|
- cd helloworld && meteor add anti:gagarin@0.4.11 session meteor-platform clinical:theming clinical:default-theme clinical:router clinical:router-default-config clinical:active-layout clinical:active-layout-reset clinical:active-layout-pagescreen-config grove:less
|
||||||
|
- cd helloworld && git clone http://github.com/clinical-meteor/router-middleware-stack packages/router-middleware-stack
|
||||||
|
- cd helloworld && meteor add clinical:router clinical:router-middleware-stack
|
||||||
|
- cd helloworld/packages && ls -la
|
||||||
|
- cd helloworld/packages/router-middleware-stack && ls -la
|
||||||
|
- cd helloworld/packages/router-middleware-stack/tests && ls -la
|
||||||
|
- cd helloworld/packages/router-middleware-stack/tests/gagarin && ls -la
|
||||||
|
- cd helloworld && starrynight autoconfig
|
||||||
|
|
||||||
|
## Customize test commands
|
||||||
|
test:
|
||||||
|
pre:
|
||||||
|
- cd helloworld && meteor:
|
||||||
|
background: true
|
||||||
|
- sleep 80
|
||||||
|
override:
|
||||||
|
- cd helloworld && starrynight run-tests --type package-verification
|
||||||
1
Packages/router-middleware-stack/examples/basic/.meteor/.gitignore
vendored
Normal file
1
Packages/router-middleware-stack/examples/basic/.meteor/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
local
|
||||||
@ -0,0 +1 @@
|
|||||||
|
ofqtruq93rux231sdq
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
# Meteor packages used by this project, one per line.
|
||||||
|
#
|
||||||
|
# 'meteor add' and 'meteor remove' will edit this file for you,
|
||||||
|
# but you can also edit it by hand.
|
||||||
|
|
||||||
|
standard-app-packages
|
||||||
|
autopublish
|
||||||
|
insecure
|
||||||
|
iron:middleware-stack
|
||||||
|
|
||||||
@ -0,0 +1 @@
|
|||||||
|
none
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
application-configuration@1.0.0
|
||||||
|
autopublish@1.0.0
|
||||||
|
autoupdate@1.0.0
|
||||||
|
binary-heap@1.0.0
|
||||||
|
blaze-tools@1.0.0
|
||||||
|
blaze@1.0.0
|
||||||
|
callback-hook@1.0.0
|
||||||
|
check@1.0.0
|
||||||
|
ctl-helper@1.0.0
|
||||||
|
ctl@1.0.0
|
||||||
|
deps@1.0.0
|
||||||
|
ejson@1.0.0
|
||||||
|
follower-livedata@1.0.0
|
||||||
|
geojson-utils@1.0.0
|
||||||
|
html-tools@1.0.0
|
||||||
|
htmljs@1.0.0
|
||||||
|
id-map@1.0.0
|
||||||
|
insecure@1.0.0
|
||||||
|
iron:core@0.1.0
|
||||||
|
iron:middleware-stack@0.1.0
|
||||||
|
iron:url@0.1.0
|
||||||
|
jquery@1.0.0
|
||||||
|
json@1.0.0
|
||||||
|
livedata@1.0.0
|
||||||
|
logging@1.0.0
|
||||||
|
meteor@1.0.0
|
||||||
|
minifiers@1.0.0
|
||||||
|
minimongo@1.0.0
|
||||||
|
mongo-livedata@1.0.1
|
||||||
|
observe-sequence@1.0.0
|
||||||
|
ordered-dict@1.0.0
|
||||||
|
random@1.0.0
|
||||||
|
reactive-dict@1.0.0
|
||||||
|
reload@1.0.0
|
||||||
|
retry@1.0.0
|
||||||
|
routepolicy@1.0.0
|
||||||
|
session@1.0.0
|
||||||
|
spacebars-compiler@1.0.0
|
||||||
|
spacebars@1.0.0
|
||||||
|
standard-app-packages@1.0.0
|
||||||
|
templating@1.0.0
|
||||||
|
ui@1.0.0
|
||||||
|
underscore@1.0.0
|
||||||
|
webapp@1.0.0
|
||||||
29
Packages/router-middleware-stack/examples/basic/basic.js
Normal file
29
Packages/router-middleware-stack/examples/basic/basic.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
stack = new Iron.MiddlewareStack;
|
||||||
|
|
||||||
|
printUrls = function (name, thisArg) {
|
||||||
|
console.log('%c***********************', 'color: orange;');
|
||||||
|
console.log("<" + name + "> this.originalUrl: " + JSON.stringify(thisArg.originalUrl));
|
||||||
|
console.log("<" + name + "> this.url: " + JSON.stringify(thisArg.url));
|
||||||
|
console.log('%c***********************', 'color: orange;');
|
||||||
|
};
|
||||||
|
|
||||||
|
stack.push(function m1 () {
|
||||||
|
printUrls('m1', this);
|
||||||
|
this.next();
|
||||||
|
});
|
||||||
|
|
||||||
|
stack.push(function m2 () {
|
||||||
|
printUrls('m2', this);
|
||||||
|
this.next();
|
||||||
|
});
|
||||||
|
|
||||||
|
stack.push('/admin', function adminApp () {
|
||||||
|
printUrls('adminApp', this);
|
||||||
|
}, {mount: true});
|
||||||
|
|
||||||
|
console.log('%cDispatch "/"', 'color: blue;');
|
||||||
|
stack.dispatch('/', {});
|
||||||
|
|
||||||
|
console.log('');
|
||||||
|
console.log('%cDispatch "/admin"', 'color: blue;');
|
||||||
|
stack.dispatch('/admin', {});
|
||||||
118
Packages/router-middleware-stack/lib/handler.js
Normal file
118
Packages/router-middleware-stack/lib/handler.js
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
var Url = Iron.Url;
|
||||||
|
|
||||||
|
Handler = function (path, fn, options) {
|
||||||
|
if (_.isFunction(path)) {
|
||||||
|
options = options || fn || {};
|
||||||
|
fn = path;
|
||||||
|
path = '/';
|
||||||
|
|
||||||
|
// probably need a better approach here to differentiate between
|
||||||
|
// Router.use(function () {}) and Router.use(MyAdminApp). In the first
|
||||||
|
// case we don't want to count it as a viable server handler when we're
|
||||||
|
// on the client and need to decide whether to go to the server. in the
|
||||||
|
// latter case, we DO want to go to the server, potentially.
|
||||||
|
this.middleware = true;
|
||||||
|
|
||||||
|
if (typeof options.mount === 'undefined')
|
||||||
|
options.mount = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if fn is a function then typeof fn => 'function'
|
||||||
|
// but note we can't use _.isObject here because that will return true if the
|
||||||
|
// fn is a function OR an object.
|
||||||
|
if (typeof fn === 'object') {
|
||||||
|
options = fn;
|
||||||
|
fn = options.action || 'action';
|
||||||
|
}
|
||||||
|
|
||||||
|
options = options || {};
|
||||||
|
|
||||||
|
this.options = options;
|
||||||
|
this.mount = options.mount;
|
||||||
|
this.method = (options.method && options.method.toLowerCase()) || false;
|
||||||
|
|
||||||
|
// should the handler be on the 'client', 'server' or 'both'?
|
||||||
|
// XXX can't we default this to undefined in which case it's run in all
|
||||||
|
// environments?
|
||||||
|
this.where = options.where || 'client';
|
||||||
|
|
||||||
|
// if we're mounting at path '/foo' then this handler should also handle
|
||||||
|
// '/foo/bar' and '/foo/bar/baz'
|
||||||
|
if (this.mount)
|
||||||
|
options.end = false;
|
||||||
|
|
||||||
|
// set the name
|
||||||
|
if (options.name)
|
||||||
|
this.name = options.name;
|
||||||
|
else if (typeof path === 'string' && path.charAt(0) !== '/')
|
||||||
|
this.name = path;
|
||||||
|
else if (typeof path === 'string' && path !== '/')
|
||||||
|
this.name = path.split('/').slice(1).join('.');
|
||||||
|
|
||||||
|
// if the path is explicitly set on the options (e.g. legacy router support)
|
||||||
|
// then use that
|
||||||
|
// otherwise use the path argument which could also be a name
|
||||||
|
path = options.path || path;
|
||||||
|
|
||||||
|
if (typeof path === 'string' && path.charAt(0) !== '/')
|
||||||
|
path = '/' + path;
|
||||||
|
|
||||||
|
this.path = path;
|
||||||
|
this.compiledUrl = new Url(path, options);
|
||||||
|
|
||||||
|
if (_.isString(fn)) {
|
||||||
|
this.handle = function handle () {
|
||||||
|
// try to find a method on the current thisArg which might be a Controller
|
||||||
|
// for example.
|
||||||
|
var func = this[fn];
|
||||||
|
|
||||||
|
if (typeof func !== 'function')
|
||||||
|
throw new Error("No method named " + JSON.stringify(fn) + " found on handler.");
|
||||||
|
|
||||||
|
return func.apply(this, arguments);
|
||||||
|
};
|
||||||
|
} else if (_.isFunction(fn)) {
|
||||||
|
// or just a regular old function
|
||||||
|
this.handle = fn;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the path matches the handler's compiled url, method
|
||||||
|
* and environment (e.g. client/server). If no options.method or options.where
|
||||||
|
* is provided, then only the path will be used to test.
|
||||||
|
*/
|
||||||
|
Handler.prototype.test = function (path, options) {
|
||||||
|
options = options || {};
|
||||||
|
|
||||||
|
var isUrlMatch = this.compiledUrl.test(path);
|
||||||
|
var isMethodMatch = true;
|
||||||
|
var isEnvMatch = true;
|
||||||
|
|
||||||
|
if (this.method && options.method)
|
||||||
|
isMethodMatch = this.method == options.method.toLowerCase();
|
||||||
|
|
||||||
|
if (options.where)
|
||||||
|
isEnvMatch = this.where == options.where;
|
||||||
|
|
||||||
|
return isUrlMatch && isMethodMatch && isEnvMatch;
|
||||||
|
};
|
||||||
|
|
||||||
|
Handler.prototype.params = function (path) {
|
||||||
|
return this.compiledUrl.params(path);
|
||||||
|
};
|
||||||
|
|
||||||
|
Handler.prototype.resolve = function (params, options) {
|
||||||
|
return this.compiledUrl.resolve(params, options);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new cloned Handler.
|
||||||
|
* XXX problem is here because we're not storing the original path.
|
||||||
|
*/
|
||||||
|
Handler.prototype.clone = function () {
|
||||||
|
var clone = new Handler(this.path, this.handle, this.options);
|
||||||
|
// in case the original function had a name
|
||||||
|
clone.name = this.name;
|
||||||
|
return clone;
|
||||||
|
};
|
||||||
282
Packages/router-middleware-stack/lib/middleware_stack.js
Normal file
282
Packages/router-middleware-stack/lib/middleware_stack.js
Normal file
@ -0,0 +1,282 @@
|
|||||||
|
var Url = Iron.Url;
|
||||||
|
var assert = Iron.utils.assert;
|
||||||
|
var defaultValue = Iron.utils.defaultValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect inspired middleware stack that works on the client and the server.
|
||||||
|
*
|
||||||
|
* You can add handlers to the stack for various paths. Those handlers can run
|
||||||
|
* on the client or server. Then you can dispatch into the stack with a
|
||||||
|
* given path by calling the dispatch method. This goes down the stack looking
|
||||||
|
* for matching handlers given the url and environment (client/server). If we're
|
||||||
|
* on the client and we should make a trip to the server, the onServerDispatch
|
||||||
|
* callback is called.
|
||||||
|
*
|
||||||
|
* The middleware stack supports the Connect API. But it also allows you to
|
||||||
|
* specify a context so we can have one context object (like a Controller) that
|
||||||
|
* is a consistent context for each handler function called on a dispatch.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
MiddlewareStack = function () {
|
||||||
|
this._stack = [];
|
||||||
|
this.length = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
MiddlewareStack.prototype._create = function (path, fn, options) {
|
||||||
|
var handler = new Handler(path, fn, options);
|
||||||
|
var name = handler.name;
|
||||||
|
|
||||||
|
if (name) {
|
||||||
|
if (_.has(this._stack, name)) {
|
||||||
|
throw new Error("Handler with name '" + name + "' already exists.");
|
||||||
|
}
|
||||||
|
this._stack[name] = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
return handler;
|
||||||
|
};
|
||||||
|
|
||||||
|
MiddlewareStack.prototype.findByName = function (name) {
|
||||||
|
return this._stack[name];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Push a new handler onto the stack.
|
||||||
|
*/
|
||||||
|
MiddlewareStack.prototype.push = function (path, fn, options) {
|
||||||
|
var handler = this._create(path, fn, options);
|
||||||
|
this._stack.push(handler);
|
||||||
|
this.length++;
|
||||||
|
return handler;
|
||||||
|
};
|
||||||
|
|
||||||
|
MiddlewareStack.prototype.append = function (/* fn1, fn2, [f3, f4]... */) {
|
||||||
|
var self = this;
|
||||||
|
var args = _.toArray(arguments);
|
||||||
|
var options = {};
|
||||||
|
|
||||||
|
if (typeof args[args.length-1] === 'object')
|
||||||
|
options = args.pop();
|
||||||
|
|
||||||
|
_.each(args, function (fnOrArray) {
|
||||||
|
if (typeof fnOrArray === 'undefined')
|
||||||
|
return;
|
||||||
|
else if (typeof fnOrArray === 'function')
|
||||||
|
self.push(fnOrArray, options);
|
||||||
|
else if (_.isArray(fnOrArray))
|
||||||
|
self.append.apply(self, fnOrArray.concat([options]));
|
||||||
|
else
|
||||||
|
throw new Error("Can only append functions or arrays to the MiddlewareStack");
|
||||||
|
});
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a handler at a specific index in the stack.
|
||||||
|
*
|
||||||
|
* The index behavior is the same as Array.prototype.splice. If the index is
|
||||||
|
* greater than the stack length the handler will be appended at the end of the
|
||||||
|
* stack. If the index is negative, the item will be inserted "index" elements
|
||||||
|
* from the end.
|
||||||
|
*/
|
||||||
|
MiddlewareStack.prototype.insertAt = function (index, path, fn, options) {
|
||||||
|
var handler = this._create(path, fn, options);
|
||||||
|
this._stack.splice(index, 0, handler);
|
||||||
|
this.length = this._stack.length;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a handler before another named handler.
|
||||||
|
*/
|
||||||
|
MiddlewareStack.prototype.insertBefore = function (name, path, fn, options) {
|
||||||
|
var beforeHandler;
|
||||||
|
var index;
|
||||||
|
|
||||||
|
if (!(beforeHandler = this._stack[name]))
|
||||||
|
throw new Error("Couldn't find a handler named '" + name + "' on the path stack");
|
||||||
|
|
||||||
|
index = _.indexOf(this._stack, beforeHandler);
|
||||||
|
this.insertAt(index, path, fn, options);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a handler after another named handler.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
MiddlewareStack.prototype.insertAfter = function (name, path, fn, options) {
|
||||||
|
var handler;
|
||||||
|
var index;
|
||||||
|
|
||||||
|
if (!(handler = this._stack[name]))
|
||||||
|
throw new Error("Couldn't find a handler named '" + name + "' on the path stack");
|
||||||
|
|
||||||
|
index = _.indexOf(this._stack, handler);
|
||||||
|
this.insertAt(index + 1, path, fn, options);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new MiddlewareStack comprised of this stack joined with other
|
||||||
|
* stacks. Note the new stack will not have named handlers anymore. Only the
|
||||||
|
* handlers are cloned but not the name=>handler mapping.
|
||||||
|
*/
|
||||||
|
MiddlewareStack.prototype.concat = function (/* stack1, stack2, */) {
|
||||||
|
var ret = new MiddlewareStack;
|
||||||
|
var concat = Array.prototype.concat;
|
||||||
|
var clonedThisStack = EJSON.clone(this._stack);
|
||||||
|
var clonedOtherStacks = _.map(_.toArray(arguments), function (s) { return EJSON.clone(s._stack); });
|
||||||
|
ret._stack = concat.apply(clonedThisStack, clonedOtherStacks);
|
||||||
|
ret.length = ret._stack.length;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatch into the middleware stack, allowing the handlers to control the
|
||||||
|
* iteration by calling this.next();
|
||||||
|
*/
|
||||||
|
MiddlewareStack.prototype.dispatch = function dispatch (url, context, done) {
|
||||||
|
var self = this;
|
||||||
|
var originalUrl = url;
|
||||||
|
|
||||||
|
assert(typeof url === 'string', "Requires url");
|
||||||
|
assert(typeof context === 'object', "Requires context object");
|
||||||
|
|
||||||
|
url = Url.normalize(url || '/');
|
||||||
|
|
||||||
|
defaultValue(context, 'request', {});
|
||||||
|
defaultValue(context, 'response', {});
|
||||||
|
defaultValue(context, 'originalUrl', url);
|
||||||
|
|
||||||
|
//defaultValue(context, 'location', Url.parse(originalUrl));
|
||||||
|
defaultValue(context, '_method', context.method);
|
||||||
|
defaultValue(context, '_handlersForEnv', {client: false, server: false});
|
||||||
|
defaultValue(context, '_handled', false);
|
||||||
|
|
||||||
|
defaultValue(context, 'isHandled', function () {
|
||||||
|
return context._handled;
|
||||||
|
});
|
||||||
|
|
||||||
|
defaultValue(context, 'willBeHandledOnClient', function () {
|
||||||
|
return context._handlersForEnv.client;
|
||||||
|
});
|
||||||
|
|
||||||
|
defaultValue(context, 'willBeHandledOnServer', function () {
|
||||||
|
return context._handlersForEnv.server;
|
||||||
|
});
|
||||||
|
|
||||||
|
var wrappedDone = function () {
|
||||||
|
if (done) {
|
||||||
|
try {
|
||||||
|
done.apply(this, arguments);
|
||||||
|
} catch (err) {
|
||||||
|
// if we catch an error at this point in the stack we don't want it
|
||||||
|
// handled in the next() iterator below. So we'll mark the error to tell
|
||||||
|
// the next iterator to ignore it.
|
||||||
|
err._punt = true;
|
||||||
|
|
||||||
|
// now rethrow it!
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var index = 0;
|
||||||
|
|
||||||
|
var next = Meteor.bindEnvironment(function boundNext (err) {
|
||||||
|
var handler = self._stack[index++];
|
||||||
|
|
||||||
|
// reset the url
|
||||||
|
context.url = context.request.url = context.originalUrl;
|
||||||
|
|
||||||
|
if (!handler)
|
||||||
|
return wrappedDone.call(context, err);
|
||||||
|
|
||||||
|
if (!handler.test(url, {method: context._method}))
|
||||||
|
return next(err);
|
||||||
|
|
||||||
|
// okay if we've gotten this far the handler matches our url but we still
|
||||||
|
// don't know if this is a client or server handler. Let's track that.
|
||||||
|
// XXX couldn't the environment be something else like cordova?
|
||||||
|
var where = Meteor.isClient ? 'client' : 'server';
|
||||||
|
|
||||||
|
// track that we have a handler for the given environment so long as it's
|
||||||
|
// not middleware created like this Router.use(function () {}). We'll assume
|
||||||
|
// that if the handler is of that form we don't want to make a trip to
|
||||||
|
// the client or the server for it.
|
||||||
|
if (!handler.middleware)
|
||||||
|
context._handlersForEnv[handler.where] = true;
|
||||||
|
|
||||||
|
// but if we're not actually on that env, skip to the next handler.
|
||||||
|
if (handler.where !== where)
|
||||||
|
return next(err);
|
||||||
|
|
||||||
|
// get the parameters for this url from the handler's compiled path
|
||||||
|
// XXX removing for now
|
||||||
|
//var params = handler.params(context.location.href);
|
||||||
|
//context.request.params = defaultValue(context, 'params', {});
|
||||||
|
//_.extend(context.params, params);
|
||||||
|
|
||||||
|
// so we can call this.next()
|
||||||
|
// XXX this breaks with things like request.body which require that the
|
||||||
|
// iterator be saved for the given function call.
|
||||||
|
context.next = next;
|
||||||
|
|
||||||
|
if (handler.mount) {
|
||||||
|
var mountpath = Url.normalize(handler.compiledUrl.pathname);
|
||||||
|
var newUrl = url.substr(mountpath.length, url.length);
|
||||||
|
newUrl = Url.normalize(newUrl);
|
||||||
|
context.url = context.request.url = newUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
//
|
||||||
|
// The connect api says a handler signature (arity) can look like any of:
|
||||||
|
//
|
||||||
|
// 1) function (req, res, next)
|
||||||
|
// 2) function (err, req, res, next)
|
||||||
|
// 3) function (err)
|
||||||
|
var arity = handler.handle.length
|
||||||
|
var req = context.request;
|
||||||
|
var res = context.response;
|
||||||
|
|
||||||
|
// function (err, req, res, next)
|
||||||
|
if (err && arity === 4)
|
||||||
|
return handler.handle.call(context, err, req, res, next);
|
||||||
|
|
||||||
|
// function (req, res, next)
|
||||||
|
if (!err && arity < 4)
|
||||||
|
return handler.handle.call(context, req, res, next);
|
||||||
|
|
||||||
|
// default is function (err) so punt the error down the stack
|
||||||
|
// until we either find a handler who likes to deal with errors or we call
|
||||||
|
// out
|
||||||
|
return next(err);
|
||||||
|
} catch (err) {
|
||||||
|
if (err._punt)
|
||||||
|
// ignore this error and throw it down the stack
|
||||||
|
throw err;
|
||||||
|
else
|
||||||
|
// see if the next handler wants to deal with the error
|
||||||
|
next(err);
|
||||||
|
} finally {
|
||||||
|
// we'll put this at the end because some middleware
|
||||||
|
// might want to decide what to do based on whether we've
|
||||||
|
// been handled "yet". If we set this to true before the handler
|
||||||
|
// is called, there's no way for the handler to say, if we haven't been
|
||||||
|
// handled yet go to the server, for example.
|
||||||
|
context._handled = true;
|
||||||
|
context.next = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
next();
|
||||||
|
|
||||||
|
context.next = null;
|
||||||
|
return context;
|
||||||
|
};
|
||||||
|
|
||||||
|
Iron = Iron || {};
|
||||||
|
Iron.MiddlewareStack = MiddlewareStack;
|
||||||
32
Packages/router-middleware-stack/package.js
Normal file
32
Packages/router-middleware-stack/package.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
Package.describe({
|
||||||
|
name: 'clinical:router-middleware-stack',
|
||||||
|
summary: 'Client and server middleware support inspired by Connect.',
|
||||||
|
version: '2.1.2',
|
||||||
|
git: 'https://github.com/clinical-meteor/clinical-router-middleware-stack'
|
||||||
|
});
|
||||||
|
|
||||||
|
Package.on_use(function (api) {
|
||||||
|
api.versionsFrom('1.1.0.3');
|
||||||
|
|
||||||
|
api.use('underscore');
|
||||||
|
api.use('ejson');
|
||||||
|
|
||||||
|
api.use('iron:core@1.0.11');
|
||||||
|
api.imply('iron:core');
|
||||||
|
|
||||||
|
api.use('clinical:router-url@2.1.0');
|
||||||
|
|
||||||
|
api.add_files('lib/handler.js');
|
||||||
|
api.add_files('lib/middleware_stack.js');
|
||||||
|
|
||||||
|
api.export('MiddlewareStack');
|
||||||
|
api.export('Handler', {testOnly: true});
|
||||||
|
});
|
||||||
|
|
||||||
|
Package.on_test(function (api) {
|
||||||
|
api.use('clinical:router-middleware-stack');
|
||||||
|
api.use('tinytest');
|
||||||
|
api.use('test-helpers');
|
||||||
|
api.add_files('tests/tinytests/handler_test.js');
|
||||||
|
api.add_files('tests/tinytests/middleware_stack_test.js');
|
||||||
|
});
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
describe('clinical:router-middleware-stack', function () {
|
||||||
|
var server = meteor();
|
||||||
|
var client = browser(server);
|
||||||
|
|
||||||
|
it('MiddlewareStack should exist on the client', function () {
|
||||||
|
return client.execute(function () {
|
||||||
|
expect(MiddlewareStack).to.exist;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('MiddlewareStack should exist on the client', function () {
|
||||||
|
return server.execute(function () {
|
||||||
|
expect(MiddlewareStack).to.exist;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
Tinytest.add('MiddlewareStack - handler basics', function (test) {
|
||||||
|
var handler;
|
||||||
|
var fn = function myName () {};
|
||||||
|
var opts = {};
|
||||||
|
// constructor options
|
||||||
|
|
||||||
|
// middleware handler
|
||||||
|
handler = new Handler(fn);
|
||||||
|
test.equal(handler.handle, fn);
|
||||||
|
test.equal(handler.name, 'myName', 'name is "myName"');
|
||||||
|
test.equal(handler.where, 'client');
|
||||||
|
test.isTrue(handler.test('/'));
|
||||||
|
test.isTrue(handler.test('/match/everything'));
|
||||||
|
|
||||||
|
opts.name = 'newName';
|
||||||
|
handler = new Handler('/items/:id', fn, opts);
|
||||||
|
test.equal(handler.handle, fn);
|
||||||
|
test.equal(handler.name, 'newName', 'name is "newName"');
|
||||||
|
test.equal(handler.options, opts);
|
||||||
|
test.isTrue(handler.test('/items/1'));
|
||||||
|
test.isTrue(handler.test('/items/2'));
|
||||||
|
|
||||||
|
|
||||||
|
handler = new Handler('/items/:id?', fn, opts);
|
||||||
|
test.isTrue(handler.test('/items/1'));
|
||||||
|
test.isTrue(handler.test('/items'));
|
||||||
|
|
||||||
|
handler = new Handler(/.*/, fn, opts);
|
||||||
|
test.isTrue(handler.test('/'));
|
||||||
|
test.isTrue(handler.test('/foo'));
|
||||||
|
|
||||||
|
var called = false;
|
||||||
|
var thisArg = {
|
||||||
|
methodName: function () {called = true;}
|
||||||
|
};
|
||||||
|
handler = new Handler('/items/:id', 'methodName');
|
||||||
|
handler.handle.call(thisArg);
|
||||||
|
test.isTrue(called);
|
||||||
|
|
||||||
|
handler = new Handler('/items/:id', fn);
|
||||||
|
var params = handler.params('/items/5');
|
||||||
|
test.equal(params.id, "5");
|
||||||
|
});
|
||||||
|
|
||||||
|
Tinytest.add('Handler - test', function (test) {
|
||||||
|
var handler = new Handler('/testme', function () {}, {
|
||||||
|
where: 'server',
|
||||||
|
method: 'GET'
|
||||||
|
});
|
||||||
|
|
||||||
|
test.isTrue(handler.test('/testme', {where: 'server', method: 'GET'}));
|
||||||
|
test.isFalse(handler.test('/testme', {where: 'client', method: 'GET'}));
|
||||||
|
test.isFalse(handler.test('/testme', {where: 'server', method: 'POST'}));
|
||||||
|
});
|
||||||
@ -0,0 +1,182 @@
|
|||||||
|
Tinytest.add('MiddlewareStack - handler names and paths', function (test) {
|
||||||
|
var handler;
|
||||||
|
|
||||||
|
// path is a name
|
||||||
|
handler = new Handler('home', {});
|
||||||
|
test.equal(handler.name, 'home', 'name is "home"');
|
||||||
|
test.equal(handler.path, '/home', 'path is "/home"');
|
||||||
|
|
||||||
|
// path is an option
|
||||||
|
handler = new Handler('home', {path: '/foo'});
|
||||||
|
test.equal(handler.name, 'home', 'name is "home"');
|
||||||
|
test.equal(handler.path, '/foo', 'path is "/foo"');
|
||||||
|
|
||||||
|
handler = new Handler('/home', {path: '/bar'});
|
||||||
|
test.equal(handler.path, '/bar', 'path is "/bar"');
|
||||||
|
|
||||||
|
handler = new Handler('/home', {path: '/bar', name: 'foo'});
|
||||||
|
test.equal(handler.path, '/bar', 'path is "/bar"');
|
||||||
|
test.equal(handler.name, 'foo', 'name is "foo"');
|
||||||
|
});
|
||||||
|
|
||||||
|
Tinytest.add('MiddlewareStack - create and find by name', function (test) {
|
||||||
|
// basically just test that a handler gets created and keyed by name if thee's
|
||||||
|
// a name. Also test duplicate named handlers throws an error.
|
||||||
|
|
||||||
|
var stack = new Iron.MiddlewareStack;
|
||||||
|
stack._create('/items', function () {}, {name: 'items'});
|
||||||
|
test.isTrue(stack.findByName('items'));
|
||||||
|
|
||||||
|
test.throws(function () {
|
||||||
|
// same name
|
||||||
|
stack._create('/items', function () {}, {name: 'items'});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Tinytest.add('MiddlewareStack - push', function (test) {
|
||||||
|
var stack = new Iron.MiddlewareStack;
|
||||||
|
var fns = [function () {}, function () {}];
|
||||||
|
stack.push(fns[0]);
|
||||||
|
test.equal(stack._stack[0].handle, fns[0]);
|
||||||
|
stack.push(fns[1]);
|
||||||
|
test.equal(stack._stack[1].handle, fns[1]);
|
||||||
|
});
|
||||||
|
|
||||||
|
Tinytest.add('MiddlewareStack - insertAt', function (test) {
|
||||||
|
var stack = new Iron.MiddlewareStack;
|
||||||
|
var fns = [function () {}, function () {}, function () {}];
|
||||||
|
stack.push(fns[0]);
|
||||||
|
stack.push(fns[2]);
|
||||||
|
|
||||||
|
stack.insertAt(1, fns[1]);
|
||||||
|
test.equal(stack._stack[1].handle, fns[1]);
|
||||||
|
});
|
||||||
|
|
||||||
|
Tinytest.add('MiddlewareStack - insertBefore', function (test) {
|
||||||
|
var stack = new Iron.MiddlewareStack;
|
||||||
|
var fns = [function one() {}, function two() {}, function three() {}];
|
||||||
|
stack.push(fns[0]);
|
||||||
|
stack.push(fns[2]);
|
||||||
|
stack.insertBefore('three', fns[1]);
|
||||||
|
test.equal(stack._stack[1].handle, fns[1]);
|
||||||
|
});
|
||||||
|
|
||||||
|
Tinytest.add('MiddlewareStack - insertAfter ', function (test) {
|
||||||
|
var stack = new Iron.MiddlewareStack;
|
||||||
|
var fns = [function one() {}, function two() {}, function three() {}];
|
||||||
|
stack.push(fns[0]);
|
||||||
|
stack.push(fns[2]);
|
||||||
|
stack.insertAfter('one', fns[1]);
|
||||||
|
test.equal(stack._stack[1].handle, fns[1]);
|
||||||
|
});
|
||||||
|
|
||||||
|
Tinytest.add('MiddlewareStack - dispatch iteration with this.next', function (test) {
|
||||||
|
var stack = new Iron.MiddlewareStack;
|
||||||
|
var calls = [];
|
||||||
|
|
||||||
|
if (Meteor.isClient) {
|
||||||
|
stack.push(function m1 () {
|
||||||
|
calls.push('m1');
|
||||||
|
this.next();
|
||||||
|
});
|
||||||
|
|
||||||
|
stack.push(function m2 () {
|
||||||
|
calls.push('m2');
|
||||||
|
// no call to next
|
||||||
|
});
|
||||||
|
|
||||||
|
stack.push(function m3 () {
|
||||||
|
calls.push('m3');
|
||||||
|
});
|
||||||
|
|
||||||
|
stack.dispatch('/', {});
|
||||||
|
test.equal(calls.length, 2, "call length is two");
|
||||||
|
test.equal(calls[0], 'm1', "m1 called");
|
||||||
|
test.equal(calls[1], 'm2', "m2 called");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Meteor.isServer) {
|
||||||
|
stack.push(function m1 () {
|
||||||
|
calls.push('m1');
|
||||||
|
this.next();
|
||||||
|
}, {where: 'server'});
|
||||||
|
|
||||||
|
stack.push(function m2 () {
|
||||||
|
calls.push('m2');
|
||||||
|
// no call to next
|
||||||
|
}, {where: 'server'});
|
||||||
|
|
||||||
|
stack.push(function m3 () {
|
||||||
|
calls.push('m3');
|
||||||
|
}, {where: 'server'});
|
||||||
|
|
||||||
|
stack.dispatch('/', {});
|
||||||
|
test.equal(calls.length, 2, "call length is two");
|
||||||
|
test.equal(calls[0], 'm1', "m1 called");
|
||||||
|
test.equal(calls[1], 'm2', "m2 called");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Tinytest.add('MiddlewareStack - dispatch callback', function (test) {
|
||||||
|
var stack = new Iron.MiddlewareStack;
|
||||||
|
var calls = [];
|
||||||
|
|
||||||
|
if (Meteor.isClient) {
|
||||||
|
stack.push(function m1 () {
|
||||||
|
calls.push('m1');
|
||||||
|
this.next();
|
||||||
|
});
|
||||||
|
|
||||||
|
stack.dispatch('/', {}, function () {
|
||||||
|
calls.push('done');
|
||||||
|
});
|
||||||
|
|
||||||
|
test.equal(calls.length, 2, "call length is two");
|
||||||
|
test.equal(calls[0], 'm1', "m1 called");
|
||||||
|
test.equal(calls[1], 'done', "done called");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Meteor.isServer) {
|
||||||
|
stack.push(function m1 () {
|
||||||
|
calls.push('m1');
|
||||||
|
this.next();
|
||||||
|
}, {where: 'server'});
|
||||||
|
|
||||||
|
stack.dispatch('/', {}, function () {
|
||||||
|
calls.push('done');
|
||||||
|
});
|
||||||
|
|
||||||
|
test.equal(calls.length, 2, "call length is two");
|
||||||
|
test.equal(calls[0], 'm1', "m1 called");
|
||||||
|
test.equal(calls[1], 'done', "done called");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (Meteor.isServer) {
|
||||||
|
var Fiber = Npm.require('fibers');
|
||||||
|
Tinytest.addAsync('MiddlewareStack - async next maintains fibers', function (test, done) {
|
||||||
|
var envVar = new Meteor.EnvironmentVariable;
|
||||||
|
|
||||||
|
envVar.withValue(true, function () {
|
||||||
|
var stack = new Iron.MiddlewareStack;
|
||||||
|
|
||||||
|
test.isTrue(envVar.getOrNullIfOutsideFiber());
|
||||||
|
stack.push(function(req, res, next) {
|
||||||
|
// break out of the current fiber
|
||||||
|
setTimeout(function() {
|
||||||
|
next();
|
||||||
|
}, 0);
|
||||||
|
}, {where: 'server'});
|
||||||
|
|
||||||
|
stack.push(function(req, res, next) {
|
||||||
|
test.isTrue(envVar.getOrNullIfOutsideFiber());
|
||||||
|
this.next();
|
||||||
|
}, {where: 'server'});
|
||||||
|
|
||||||
|
stack.dispatch('/', {}, function () {
|
||||||
|
test.isTrue(envVar.getOrNullIfOutsideFiber());
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
194
Packages/router-middleware-stack/tests/tinytests/notes.js
Normal file
194
Packages/router-middleware-stack/tests/tinytests/notes.js
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
Tinytest.add('MiddlewareStack - dispatch', function (test) {
|
||||||
|
var stack = new Iron.MiddlewareStack;
|
||||||
|
var calls = {};
|
||||||
|
var call = function (name) {
|
||||||
|
calls[name] = calls[name] || 0;
|
||||||
|
calls[name]++;
|
||||||
|
};
|
||||||
|
|
||||||
|
// client middleware
|
||||||
|
stack.push(function m1 (req, res, next) {
|
||||||
|
call('m1');
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
|
stack.push(function m2 (req, res, next) {
|
||||||
|
call('m2');
|
||||||
|
this.next();
|
||||||
|
});
|
||||||
|
|
||||||
|
// client handlers
|
||||||
|
var params;
|
||||||
|
stack.push('/items/:id', function item (req, res, next) {
|
||||||
|
call('item');
|
||||||
|
params = this.params;
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
|
// same path is okay as long as name is different
|
||||||
|
stack.push('/items/:id', function itemTwo (req, res, next) {
|
||||||
|
call('item2');
|
||||||
|
});
|
||||||
|
|
||||||
|
// server handler
|
||||||
|
stack.push('/server', function server (req, res, next) {
|
||||||
|
call('server');
|
||||||
|
}, { where: 'server' });
|
||||||
|
|
||||||
|
var thisArg = {};
|
||||||
|
|
||||||
|
if (Meteor.isClient) {
|
||||||
|
stack.dispatch('/', {});
|
||||||
|
test.equal(calls.m1, 1, 'm1 not called');
|
||||||
|
test.equal(calls.m2, 1, 'm2 not called');
|
||||||
|
test.isFalse(calls.item);
|
||||||
|
test.isFalse(calls.item2);
|
||||||
|
test.isFalse(calls.server);
|
||||||
|
|
||||||
|
stack.dispatch('/items/1', thisArg);
|
||||||
|
test.equal(calls.m1, 2, 'm1 not called');
|
||||||
|
test.equal(calls.m2, 2, 'm2 not called');
|
||||||
|
test.equal(calls.item, 1, 'item not called');
|
||||||
|
test.equal(calls.item2, 1, 'item2 not called');
|
||||||
|
test.isFalse(calls.server);
|
||||||
|
|
||||||
|
var params = thisArg.params;
|
||||||
|
test.equal(params.id, "1");
|
||||||
|
|
||||||
|
stack.onServerDispatch(function () {
|
||||||
|
call('serverDispatch');
|
||||||
|
});
|
||||||
|
|
||||||
|
stack.dispatch('/server', {});
|
||||||
|
test.equal(calls.serverDispatch, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Meteor.isServer) {
|
||||||
|
stack.dispatch('/server', {});
|
||||||
|
test.isFalse(calls.m1);
|
||||||
|
test.isFalse(calls.m2);
|
||||||
|
test.equal(calls.server, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Tinytest.add('MiddlewareStack - dispatch error handling', function (test) {
|
||||||
|
if (Meteor.isClient) {
|
||||||
|
var stack = new Iron.MiddlewareStack;
|
||||||
|
var calls = [];
|
||||||
|
stack.push(function (req, res, next) {
|
||||||
|
calls.push(1);
|
||||||
|
throw new Error('test');
|
||||||
|
});
|
||||||
|
|
||||||
|
stack.push(function (req, res, next) {
|
||||||
|
calls.push(2);
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
|
stack.dispatch('/', {
|
||||||
|
next: function (err) {
|
||||||
|
calls.push(3);
|
||||||
|
test.equal(err.message, 'test');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test.equal(calls.length, 2);
|
||||||
|
|
||||||
|
// first fn throws an error
|
||||||
|
test.equal(calls[0], 1);
|
||||||
|
|
||||||
|
// rest of middleware skipped
|
||||||
|
test.equal(calls[1], 3);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Tinytest.add('MiddlewareStack - mounting paths', function (test) {
|
||||||
|
var stack = new Iron.MiddlewareStack;
|
||||||
|
var calls = [];
|
||||||
|
|
||||||
|
if (Meteor.isClient) {
|
||||||
|
// add a mounted handler at mountpath /foo
|
||||||
|
stack.push('/foo', function (req, res, next) {
|
||||||
|
calls.push({args: EJSON.clone(arguments), thisArg: EJSON.clone(this)});
|
||||||
|
next();
|
||||||
|
}, {mount: true});
|
||||||
|
|
||||||
|
// add a regular handler at /foo/bar/baz
|
||||||
|
stack.push('/foo/bar/baz', function (req, res, next) {
|
||||||
|
calls.push({args: EJSON.clone(arguments), thisArg: EJSON.clone(this)});
|
||||||
|
});
|
||||||
|
|
||||||
|
stack.dispatch('/foo/bar/baz', {});
|
||||||
|
|
||||||
|
// make sure it got called
|
||||||
|
test.equal(calls.length, 2);
|
||||||
|
|
||||||
|
// this.url
|
||||||
|
test.equal(calls[0].thisArg.url, '/bar/baz', 'url wrong on controller');
|
||||||
|
test.equal(calls[0].thisArg.originalUrl, '/foo/bar/baz', 'originalUrl wrong on controller');
|
||||||
|
|
||||||
|
// fn (req, res, next)
|
||||||
|
// req.url
|
||||||
|
test.equal(calls[0].args[0].url, '/bar/baz', 'url wrong on req');
|
||||||
|
test.equal(calls[0].args[0].originalUrl, '/foo/bar/baz', 'originalUrl wrong on req');
|
||||||
|
|
||||||
|
// now make sure the url is set back to the originalUrl for non mounted
|
||||||
|
// handlers.
|
||||||
|
test.equal(calls[1].thisArg.url, '/foo/bar/baz');
|
||||||
|
test.equal(calls[1].thisArg.originalUrl, '/foo/bar/baz');
|
||||||
|
|
||||||
|
// fn (req, res, next)
|
||||||
|
// req.url
|
||||||
|
test.equal(calls[1].args[0].url, '/foo/bar/baz');
|
||||||
|
test.equal(calls[1].args[0].originalUrl, '/foo/bar/baz');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Meteor.isServer) {
|
||||||
|
stack.push('/foo', function (req, res, next) {
|
||||||
|
calls.push({args: EJSON.clone(arguments), thisArg: EJSON.clone(this)});
|
||||||
|
next();
|
||||||
|
}, {mount: true, where: 'server'});
|
||||||
|
|
||||||
|
// add a regular handler at /foo/bar/baz
|
||||||
|
stack.push('/foo/bar/baz', function (req, res, next) {
|
||||||
|
calls.push({args: EJSON.clone(arguments), thisArg: EJSON.clone(this)});
|
||||||
|
}, {where: 'server'});
|
||||||
|
|
||||||
|
stack.dispatch('/foo/bar/baz', {});
|
||||||
|
|
||||||
|
// make sure it got called
|
||||||
|
test.equal(calls.length, 2);
|
||||||
|
|
||||||
|
// this.url
|
||||||
|
test.equal(calls[0].thisArg.url, '/bar/baz');
|
||||||
|
test.equal(calls[0].thisArg.originalUrl, '/foo/bar/baz');
|
||||||
|
|
||||||
|
// fn (req, res, next)
|
||||||
|
// req.url
|
||||||
|
test.equal(calls[0].args[0].url, '/bar/baz');
|
||||||
|
test.equal(calls[0].args[0].originalUrl, '/foo/bar/baz');
|
||||||
|
|
||||||
|
// now make sure the url is set back to the originalUrl for non mounted
|
||||||
|
// handlers.
|
||||||
|
test.equal(calls[1].thisArg.url, '/foo/bar/baz');
|
||||||
|
test.equal(calls[1].thisArg.originalUrl, '/foo/bar/baz');
|
||||||
|
|
||||||
|
// fn (req, res, next)
|
||||||
|
// req.url
|
||||||
|
test.equal(calls[1].args[0].url, '/foo/bar/baz');
|
||||||
|
test.equal(calls[1].args[0].originalUrl, '/foo/bar/baz');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Tinytest.add('MiddlewareStack - append with options', function (test) {
|
||||||
|
var fn1 = function () {};
|
||||||
|
var fn2 = function () {};
|
||||||
|
var stack = new Iron.MiddlewareStack;
|
||||||
|
stack.append(fn1, fn2, {where: 'server'});
|
||||||
|
|
||||||
|
test.equal(stack._stack[0].where, 'server');
|
||||||
|
test.equal(stack._stack[1].where, 'server');
|
||||||
|
});
|
||||||
|
|
||||||
|
//TODO concat
|
||||||
|
//TODO append
|
||||||
Loading…
Reference in New Issue
Block a user