Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The Meteor router installs a middleware to do the routing. All Connect middleware either MUST call <code>next()</code> (exactly once) to indicate that the response is not yet settled or MUST settle the response by calling <code>res.end()</code> or by piping to the response. It is not allowed to do both.</p> <p>I studied the source code of the middleware (see below). We see that we can return <code>false</code> to tell the middleware to call <code>next()</code>. This means we declare that this route did not settle the response and we would like to let other middleware do their work.</p> <p>Or we can return a template name, a text, an array <code>[status, text]</code> or an array <code>[status, headers, text]</code>, and the middleware will settle the response on our behalf by calling <code>res.end()</code> using the data we returned.</p> <p>However, by piping to the response, we already settled the response. The Meteor router should not call <code>next()</code> nor <code>res.end()</code>.</p> <p>We solved the problem by forking the Meteor router and making a small change. We replaced the <code>else</code> in line 87 (after <code>if (output === false)</code>) by:</p> <pre><code>else if (typeof(output)!="undefined") { </code></pre> <p>See the commit with sha <a href="https://github.com/nalply/meteor-router/commit/8d8fc23d9c932fad0f63fd21884f1d22e37fc05e" rel="nofollow">8d8fc23d9c</a> in my fork.</p> <p>This way <code>return;</code> in the route method will tell the router to do <strong>nothing</strong>. Of course you already settled the response by piping to it.</p> <hr> <p>Source code of the middleware as in the commit with sha <a href="https://github.com/tmeasday/meteor-router/blob/e5beb618c880aa4a3e721256169e5ea2506ef11c/lib/router_server.js#L73" rel="nofollow">f910a090ae</a>:</p> <pre><code>// hook up the serving __meteor_bootstrap__.app .use(connect.query()) // &lt;- XXX: we can probably assume accounts did this .use(this._config.requestParser(this._config.bodyParser)) .use(function(req, res, next) { // need to wrap in a fiber in case they do something async // (e.g. in the database) if(typeof(Fiber)=="undefined") Fiber = Npm.require('fibers'); Fiber(function() { var output = Meteor.Router.match(req, res); if (output === false) { return next(); } else { // parse out the various type of response we can have // array can be // [content], [status, content], [status, headers, content] if (_.isArray(output)) { // copy the array so we aren't actually modifying it! output = output.slice(0); if (output.length === 3) { var headers = output.splice(1, 1)[0]; _.each(headers, function(value, key) { res.setHeader(key, value); }); } if (output.length === 2) { res.statusCode = output.shift(); } output = output[0]; } if (_.isNumber(output)) { res.statusCode = output; output = ''; } return res.end(output); } }).run(); }); </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload