For the last two days, I have be spiking in an attempt to get SPDY and express.js playing nicely. Day 3 picks up where I left off yesterday, with an exception being generated from within the
http.js module of connect:Server.prototype.handle = function(req, res, out) {
// ...
// Call the layer handler
// Trim off the part of the url that matches the route
removed = layer.route;
req.url = req.url.substr(removed.length);
// Ensure leading slash
if ('/' != req.url[0]) req.url = '/' + req.url;
// ...After some rooting around in node debug, I come across a seemingly unhelpful exception:RangeError undefined.It is an odd little error because it seemingly comes from nowhere (there is no associated stacktrace). Eventually, I step through enough code to come across:
debug> break in #<Object>.render(view=index, opts=#<Object>, fn=undefined, parent=undefined, sub=undefined), /home/cstrom/repos/node-spdy/node_modules/express/lib/view.js:308I actually go through many more iterations than shown above before I realize that it is repeating. I think the endless repeating must eventually result in the
if ('function' == typeof opts) {
^
debug>
break in #<Object>.render(view=index, opts=#<Object>, fn=undefined, parent=undefined, sub=undefined), /home/cstrom/repos/node-spdy/node_modules/express/lib/view.js:313
return this._render(view, opts, fn, parent, sub);
^
debug>
break in #<Object>.render(view=index, opts=#<Object>, fn=undefined, parent=undefined, sub=undefined), /home/cstrom/repos/node-spdy/node_modules/express/lib/view.js:308
if ('function' == typeof opts) {
^
debug>
break in #<Object>.render(view=index, opts=#<Object>, fn=undefined, parent=undefined, sub=undefined), /home/cstrom/repos/node-spdy/node_modules/express/lib/view.js:313
return this._render(view, opts, fn, parent, sub);
^
debug>
break in #<Object>.render(view=index, opts=#<Object>, fn=undefined, parent=undefined, sub=undefined), /home/cstrom/repos/node-spdy/node_modules/express/lib/view.js:308
if ('function' == typeof opts) {
^
RangeError. Regardless, I need to figure out why it is repeating. More to the point, why is a call to the _render() method stepping right back into render() on line 308?It turns out that there is a perfectly reasonable answer to that question. In my sleep deprived delirium yesterday, I defined
_render and render in the SPDY response object to be the same thing:spdy_res.partial = res.partial;Both are pointing to the
spdy_res.render = res.render;
spdy_res._render = res.render;
render() method from Response in express.js. The solution is easy enough, point spdy_res._render to res._render:spdy_res.partial = res.partial;That gets me a little farther. But, when I load the express sample app now, I get:
spdy_res.render = res.render;
spdy_res._render = res._render;
TypeError: Object [object Object] has no method 'send'That is a similar class of error to what I was seeing last night. Specifically, express decorates connect and node.js objects with new methods (like
at [object Object]._render (/home/cstrom/repos/node-spdy/node_modules/express/lib/view.js:439:10)
at [object Object].render (/home/cstrom/repos/node-spdy/node_modules/express/lib/view.js:313:17)
at [object Object]._render (/home/cstrom/repos/node-spdy/node_modules/express/lib/view.js:429:10)
at [object Object].render (/home/cstrom/repos/node-spdy/node_modules/express/lib/view.js:313:17)
at Router.(/home/cstrom/repos/node-spdy/test/express/app.js:39:7)
at done (/home/cstrom/repos/node-spdy/node_modules/express/lib/router/index.js:250:22)
at middleware (/home/cstrom/repos/node-spdy/node_modules/express/lib/router/index.js:244:9)
at param (/home/cstrom/repos/node-spdy/node_modules/express/lib/router/index.js:227:11)
at pass (/home/cstrom/repos/node-spdy/node_modules/express/lib/router/index.js:232:6)
at Router._dispatch (/home/cstrom/repos/node-spdy/node_modules/express/lib/router/index.js:255:4)
render() and send()). I already figured out how to add render() (it did take a few tries to get _render() working). Unfortunately, that same technique won't quite work with send().For
render() I was able to decorate directly in my newly added express/lib/spdy.js. Unfortunately, the send() method is added to Response.prototype after lib/spdy.js is loaded. So I have to add code directly to lib/express.js:var http = require('http')
, res = http.ServerResponse.prototype
, spdy = require('../../../lib/spdy')
, spdy_res = spdy.Response.prototype;
spdy_res.send = res.send;After doing the same for contentType() and header(), I am actually able to load up the app!Even more impressive, when I check out the SPDY tab in Chrome's
about:net-internals, I find:t=1308442868018 [st=24936] SPDY_SESSION_SYN_STREAMHoly wow! That's a real SPDY session. And it is powered by express.js! And no errors!
--> flags = 1
--> accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
accept-charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
accept-encoding: gzip,deflate,sdch
accept-language: en-US,en;q=0.8
cache-control: max-age=0
host: localhost:3000
method: GET
scheme: https
url: /
user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.794.0 Safari/535.1
version: HTTP/1.1
--> id = 7
t=1308442868031 [st=24949] SPDY_SESSION_SYN_REPLY
--> flags = 0
--> connection: keep-alive
content-length: 277
content-type: text/html
status: 200 OK
version: HTTP/1.1
x-powered-by: Express
--> id = 7
Yay! It actually works!
Er... I mean of course it works. I'm brilliant! And tomorrow I'll see if I can figure out how it works. And maybe even implement it well.
Day #53
No comments:
Post a Comment