From f2aecdd198070f59d40950a37041a3d57491f5ef Mon Sep 17 00:00:00 2001 From: James Halliday Date: Tue, 14 Sep 2010 22:31:20 -0800 Subject: [PATCH 01/11] separate function from exports so sys.inherits() works --- lib/cart.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/cart.js b/lib/cart.js index 51debcf..bd56432 100644 --- a/lib/cart.js +++ b/lib/cart.js @@ -3,7 +3,9 @@ var sys = require('sys'); var ConnectStore = require('connect/middleware/session/store'); var Store = require('supermarket'); -module.exports = function Cart(options) { +module.exports = Cart; + +function Cart(options) { var self = this; options = options || {}; From 6eeef0ab8bb910ca386795f51e113567c0afbcbb Mon Sep 17 00:00:00 2001 From: James Halliday Date: Tue, 14 Sep 2010 22:56:59 -0800 Subject: [PATCH 02/11] web connect test that fails --- test/web.js | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 test/web.js diff --git a/test/web.js b/test/web.js new file mode 100644 index 0000000..275f8b9 --- /dev/null +++ b/test/web.js @@ -0,0 +1,36 @@ +var Cart = require('cart'); +var connect = require('connect'); +var http = require('http'); + +exports.webserver = function (assert) { + var port = Math.floor(Math.random() * 40000 + 10000); + + var server = connect.createServer(); + server.use(connect.cookieDecoder()); + //* + server.use(connect.session({ + store : new Cart({ dbFile : '/tmp/cart-' + port + '.db' }), + secret : 'meowmers', + })); + //*/ + server.use(connect.router(function (app) { + app.get('/', function (req, res) { + res.writeHead(200, { 'Content-Type' : 'text/html' }); + res.write('catface'); + res.end(); + }); + })); + server.listen(port, 'localhost'); + + { + var client = http.createClient(port); + var req = client.request('GET', '/', { host : 'localhost' }); + req.end(); + req.on('response', function (res) { + res.on('data', function (data) { + assert.equal('catface', data.toString()); + }); + server.close(); + }); + } +}; From 1e6273ea14a75acffec6e1f17fa42eb1a32b48a0 Mon Sep 17 00:00:00 2001 From: James Halliday Date: Tue, 14 Sep 2010 22:59:24 -0800 Subject: [PATCH 03/11] give the server 100ms to start up --- test/web.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/web.js b/test/web.js index 275f8b9..8631364 100644 --- a/test/web.js +++ b/test/web.js @@ -7,12 +7,11 @@ exports.webserver = function (assert) { var server = connect.createServer(); server.use(connect.cookieDecoder()); - //* server.use(connect.session({ store : new Cart({ dbFile : '/tmp/cart-' + port + '.db' }), secret : 'meowmers', })); - //*/ + server.use(connect.router(function (app) { app.get('/', function (req, res) { res.writeHead(200, { 'Content-Type' : 'text/html' }); @@ -22,7 +21,7 @@ exports.webserver = function (assert) { })); server.listen(port, 'localhost'); - { + setTimeout(function () { var client = http.createClient(port); var req = client.request('GET', '/', { host : 'localhost' }); req.end(); @@ -32,5 +31,5 @@ exports.webserver = function (assert) { }); server.close(); }); - } + }, 100); }; From aca15d53e85d61504b3378d2bd2b23645792bb9c Mon Sep 17 00:00:00 2001 From: James Halliday Date: Tue, 14 Sep 2010 23:03:03 -0800 Subject: [PATCH 04/11] saltier --- test/web.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/web.js b/test/web.js index 8631364..73eeac6 100644 --- a/test/web.js +++ b/test/web.js @@ -9,7 +9,7 @@ exports.webserver = function (assert) { server.use(connect.cookieDecoder()); server.use(connect.session({ store : new Cart({ dbFile : '/tmp/cart-' + port + '.db' }), - secret : 'meowmers', + secret : 'salty-' + Math.floor(Math.random() * 1e16) })); server.use(connect.router(function (app) { From 4f73bfa84663a6f2464e1b37a2c5e4bfcabcb722 Mon Sep 17 00:00:00 2001 From: James Halliday Date: Tue, 14 Sep 2010 23:48:15 -0800 Subject: [PATCH 05/11] more complicated tests, should refactor for http-agent --- test/web.js | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/test/web.js b/test/web.js index 73eeac6..4aea48b 100644 --- a/test/web.js +++ b/test/web.js @@ -1,12 +1,14 @@ var Cart = require('cart'); var connect = require('connect'); var http = require('http'); +var qs = require('querystring'); exports.webserver = function (assert) { var port = Math.floor(Math.random() * 40000 + 10000); var server = connect.createServer(); server.use(connect.cookieDecoder()); + server.use(connect.bodyDecoder()); server.use(connect.session({ store : new Cart({ dbFile : '/tmp/cart-' + port + '.db' }), secret : 'salty-' + Math.floor(Math.random() * 1e16) @@ -18,18 +20,42 @@ exports.webserver = function (assert) { res.write('catface'); res.end(); }); + app.post('/login', function (req, res) { +console.dir(req.body); + res.writeHead(200, { 'Content-Type' : 'text/html' }); + res.write('meow'); + res.end(); + }); })); server.listen(port, 'localhost'); + var get = request.bind({}, port, 'GET', {}); + var post = request.bind({}, port, 'POST'); + setTimeout(function () { - var client = http.createClient(port); - var req = client.request('GET', '/', { host : 'localhost' }); - req.end(); - req.on('response', function (res) { - res.on('data', function (data) { - assert.equal('catface', data.toString()); - }); - server.close(); + get('/', function (s) { + assert.equal('catface', s); + }); + post({ user : 'substack', pass : 'hax' }, '/login', function (s) { + console.log(s); }); }, 100); + + setTimeout(function () { server.close() }, 500); }; + +function request (port, method, vars, path, cb) { + var client = http.createClient(port); + var opts = { host : 'localhost' }; + if (method == 'POST') { + opts['Content-Type'] = 'application/x-www-form-urlencoded'; + } + var req = client.request(method, path, opts); + req.end(qs.stringify(vars)); + + req.on('response', function (res) { + var s = ''; + res.on('data', function (buf) { s += buf.toString() }); + res.on('end', function () { cb(s) }); + }); +} From 18bd9e93e6e8972f5ad86046cf2b53b790e72162 Mon Sep 17 00:00:00 2001 From: James Halliday Date: Wed, 15 Sep 2010 00:28:36 -0800 Subject: [PATCH 06/11] using request for tests now --- test/web.js | 33 +++++++-------------------------- 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/test/web.js b/test/web.js index 4aea48b..76081c1 100644 --- a/test/web.js +++ b/test/web.js @@ -1,6 +1,6 @@ var Cart = require('cart'); var connect = require('connect'); -var http = require('http'); +var request = require('request'); var qs = require('querystring'); exports.webserver = function (assert) { @@ -21,41 +21,22 @@ exports.webserver = function (assert) { res.end(); }); app.post('/login', function (req, res) { -console.dir(req.body); res.writeHead(200, { 'Content-Type' : 'text/html' }); res.write('meow'); res.end(); }); })); server.listen(port, 'localhost'); - - var get = request.bind({}, port, 'GET', {}); - var post = request.bind({}, port, 'POST'); + var uri = 'http://localhost:' + port + '/'; setTimeout(function () { - get('/', function (s) { - assert.equal('catface', s); - }); - post({ user : 'substack', pass : 'hax' }, '/login', function (s) { - console.log(s); + request({ uri : uri }, function (err, res, body) { + assert.equal('catface', body); + var cookie = res.headers['set-cookie'][0]; + var cookies = qs.parse(cookie); + assert.ok(cookies.connect.sid); }); }, 100); setTimeout(function () { server.close() }, 500); }; - -function request (port, method, vars, path, cb) { - var client = http.createClient(port); - var opts = { host : 'localhost' }; - if (method == 'POST') { - opts['Content-Type'] = 'application/x-www-form-urlencoded'; - } - var req = client.request(method, path, opts); - req.end(qs.stringify(vars)); - - req.on('response', function (res) { - var s = ''; - res.on('data', function (buf) { s += buf.toString() }); - res.on('end', function () { cb(s) }); - }); -} From f225efa0906641500630b96bfe90968c402f08f2 Mon Sep 17 00:00:00 2001 From: James Halliday Date: Wed, 15 Sep 2010 00:59:21 -0800 Subject: [PATCH 07/11] using an agent thing to thread cookies --- test/web.js | 54 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/test/web.js b/test/web.js index 76081c1..6ece207 100644 --- a/test/web.js +++ b/test/web.js @@ -1,6 +1,7 @@ var Cart = require('cart'); var connect = require('connect'); var request = require('request'); +var Hash = require('traverse/hash'); var qs = require('querystring'); exports.webserver = function (assert) { @@ -20,23 +21,66 @@ exports.webserver = function (assert) { res.write('catface'); res.end(); }); + app.post('/login', function (req, res) { + res.writeHead(200, { 'Content-Type' : 'text/html' }); + if (req.body.user == 'substack' && req.body.pass == 'hax') { + + res.write('ok'); + } + else { + res.write('failed'); + } + res.end(); + }); + + app.get('/logout', function (req, res) { res.writeHead(200, { 'Content-Type' : 'text/html' }); res.write('meow'); res.end(); }); })); server.listen(port, 'localhost'); - var uri = 'http://localhost:' + port + '/'; + + var agent = new Agent('http://localhost:' + port); setTimeout(function () { - request({ uri : uri }, function (err, res, body) { + agent.request({ uri : '/' }, function (err, res, body) { +console.log(body); assert.equal('catface', body); - var cookie = res.headers['set-cookie'][0]; - var cookies = qs.parse(cookie); - assert.ok(cookies.connect.sid); +console.dir(agent.cookies); }); }, 100); setTimeout(function () { server.close() }, 500); }; + +function Agent (uri) { + var self = this; + self.cookies = {}; + + self.request = function (params, cb) { + request(Hash.merge(params, { + uri : uri + params.uri, + headers : Hash.merge(params.headers, { + cookie : qs.stringify(Hash.merge( + self.cookies, + qs.parse((params.headers || {}).cookie) + )) + })}), + function (err, res, body) { + ((res.headers || {})['set-cookie'] || []) + .forEach(function (raw) { + var key = raw.split(/=/)[0]; + self.cookies[key] = {}; + raw.replace(key, 'value').split(/;\s*/) + .forEach(function (kv) { + var k = kv.split(/=/)[0]; + self.cookies[key][k] = kv.split(/=/)[1] || true; + }); + }); + cb(err, res, body); + } + ); + }; +} From ddcfcfbfabb878301e432bf2a4ea0092f187601a Mon Sep 17 00:00:00 2001 From: James Halliday Date: Wed, 15 Sep 2010 01:08:12 -0800 Subject: [PATCH 08/11] chainable agent to thread cookies --- test/web.js | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/test/web.js b/test/web.js index 6ece207..6c1dc11 100644 --- a/test/web.js +++ b/test/web.js @@ -45,21 +45,44 @@ exports.webserver = function (assert) { var agent = new Agent('http://localhost:' + port); setTimeout(function () { - agent.request({ uri : '/' }, function (err, res, body) { -console.log(body); - assert.equal('catface', body); -console.dir(agent.cookies); - }); + agent + .request({ uri : '/' }, function (err, res, body) { + assert.equal('catface', body); + console.dir(agent.cookies); + }) + .request({ uri : '/' }, function (err, res, body) { + assert.equal('catface', body); + console.dir(agent.cookies); + }) + ; }, 100); setTimeout(function () { server.close() }, 500); }; -function Agent (uri) { +function Agent (uri, cookies) { var self = this; - self.cookies = {}; + self.cookies = cookies || {}; + var requests = []; self.request = function (params, cb) { + requests.push({ + params : params, + cb : function (err, res, body) { + cb(err, res, body); + next(); + } + }); + next(); + return self; + }; + + function next () { + var r = requests.shift(); + if (r) process(r.params, r.cb); + } + + function process (params, cb) { request(Hash.merge(params, { uri : uri + params.uri, headers : Hash.merge(params.headers, { From 40b065dee027c5f9a7f822b15e539664bc7e12b0 Mon Sep 17 00:00:00 2001 From: James Halliday Date: Wed, 15 Sep 2010 01:28:59 -0800 Subject: [PATCH 09/11] tries to log in but the session isn't recognized yet --- test/web.js | 58 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/test/web.js b/test/web.js index 6c1dc11..805d4e3 100644 --- a/test/web.js +++ b/test/web.js @@ -18,15 +18,18 @@ exports.webserver = function (assert) { server.use(connect.router(function (app) { app.get('/', function (req, res) { res.writeHead(200, { 'Content-Type' : 'text/html' }); - res.write('catface'); + res.write(req.session.name || 'nobody'); res.end(); }); app.post('/login', function (req, res) { res.writeHead(200, { 'Content-Type' : 'text/html' }); if (req.body.user == 'substack' && req.body.pass == 'hax') { - - res.write('ok'); + req.session.regenerate(function (err) { + if (err) throw err; + req.session.name = req.body.user; + res.write('ok'); + }); } else { res.write('failed'); @@ -47,12 +50,23 @@ exports.webserver = function (assert) { setTimeout(function () { agent .request({ uri : '/' }, function (err, res, body) { - assert.equal('catface', body); - console.dir(agent.cookies); + assert.ok(!err); + assert.equal(body, 'nobody'); }) + .request( + { + uri : '/login', + method : 'POST', + body : { user : 'substack', pass : 'hax' } + }, + function (err, res, body) { + assert.ok(!err); + assert.equal(body, 'ok'); + } + ) .request({ uri : '/' }, function (err, res, body) { - assert.equal('catface', body); - console.dir(agent.cookies); + assert.ok(!err); + assert.equal(body, 'substack'); }) ; }, 100); @@ -79,18 +93,30 @@ function Agent (uri, cookies) { function next () { var r = requests.shift(); - if (r) process(r.params, r.cb); + if (r) process(Hash.copy(r.params), r.cb); } function process (params, cb) { - request(Hash.merge(params, { - uri : uri + params.uri, - headers : Hash.merge(params.headers, { - cookie : qs.stringify(Hash.merge( - self.cookies, - qs.parse((params.headers || {}).cookie) - )) - })}), + var headers = Hash.merge(params.headers, { + cookie : qs.stringify(Hash.merge( + self.cookies, + qs.parse((params.headers || {}).cookie) + )) + }); + if (params.method == 'POST') { + if (params.body && !headers['Content-Type']) { + headers['Content-Type'] = 'application/x-www-form-urlencoded'; + } + if (!Array.isArray(params.body) && typeof params.body == 'object') { + params.body = qs.stringify(params.body); + } + } + + request( + Hash.merge(params, { + uri : uri + params.uri, + headers : headers + }), function (err, res, body) { ((res.headers || {})['set-cookie'] || []) .forEach(function (raw) { From 0b7bd4220f43dcb9efb8e3b940edd73f7c1a2d8e Mon Sep 17 00:00:00 2001 From: James Halliday Date: Wed, 15 Sep 2010 01:51:32 -0800 Subject: [PATCH 10/11] folds over cookies correctly but no session vars yet --- test/web.js | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/test/web.js b/test/web.js index 805d4e3..35dd266 100644 --- a/test/web.js +++ b/test/web.js @@ -68,6 +68,7 @@ exports.webserver = function (assert) { assert.ok(!err); assert.equal(body, 'substack'); }) + .end() ; }, 100); @@ -87,22 +88,26 @@ function Agent (uri, cookies) { next(); } }); - next(); return self; }; + self.end = function () { next() }; + function next () { var r = requests.shift(); if (r) process(Hash.copy(r.params), r.cb); } function process (params, cb) { - var headers = Hash.merge(params.headers, { - cookie : qs.stringify(Hash.merge( + var headers = Hash.copy(params.headers || {}); + + if (Hash.size(self.cookies)) { + headers.cookie = qs.stringify(Hash.map( self.cookies, - qs.parse((params.headers || {}).cookie) - )) - }); + function (c) { return c.value } + )); + } + if (params.method == 'POST') { if (params.body && !headers['Content-Type']) { headers['Content-Type'] = 'application/x-www-form-urlencoded'; @@ -118,16 +123,16 @@ function Agent (uri, cookies) { headers : headers }), function (err, res, body) { - ((res.headers || {})['set-cookie'] || []) - .forEach(function (raw) { - var key = raw.split(/=/)[0]; - self.cookies[key] = {}; - raw.replace(key, 'value').split(/;\s*/) - .forEach(function (kv) { - var k = kv.split(/=/)[0]; - self.cookies[key][k] = kv.split(/=/)[1] || true; - }); + var set = (res.headers || {})['set-cookie'] || []; + set.forEach(function (raw) { + var key = raw.split(/=/)[0]; + self.cookies[key] = {}; + var vars = raw.replace(key, 'value').split(/;\s*/); + vars.forEach(function (kv) { + var k = kv.split(/=/)[0]; + self.cookies[key][k] = kv.split(/=/)[1] || true; }); + }); cb(err, res, body); } ); From 968deb76048e5ff71d1bccb03771adaec33f4f4f Mon Sep 17 00:00:00 2001 From: James Halliday Date: Wed, 15 Sep 2010 02:31:46 -0800 Subject: [PATCH 11/11] using get for login, test fails in the console and the browser too --- test/web.js | 59 +++++++++++++++++++++-------------------------------- 1 file changed, 23 insertions(+), 36 deletions(-) diff --git a/test/web.js b/test/web.js index 35dd266..0a1e734 100644 --- a/test/web.js +++ b/test/web.js @@ -22,19 +22,13 @@ exports.webserver = function (assert) { res.end(); }); - app.post('/login', function (req, res) { + app.get('/login', function (req, res) { res.writeHead(200, { 'Content-Type' : 'text/html' }); - if (req.body.user == 'substack' && req.body.pass == 'hax') { - req.session.regenerate(function (err) { - if (err) throw err; - req.session.name = req.body.user; - res.write('ok'); - }); - } - else { - res.write('failed'); - } - res.end(); + req.session.regenerate(function (err) { + if (err) throw err; + req.session.name = 'substack'; + res.end('ok'); + }); }); app.get('/logout', function (req, res) { @@ -53,20 +47,14 @@ exports.webserver = function (assert) { assert.ok(!err); assert.equal(body, 'nobody'); }) - .request( - { - uri : '/login', - method : 'POST', - body : { user : 'substack', pass : 'hax' } - }, - function (err, res, body) { - assert.ok(!err); - assert.equal(body, 'ok'); - } - ) + .request({ uri : '/login', }, function (err, res, body) { + assert.ok(!err); + assert.equal(body, 'ok'); + }) .request({ uri : '/' }, function (err, res, body) { assert.ok(!err); assert.equal(body, 'substack'); + server.close(); }) .end() ; @@ -81,22 +69,21 @@ function Agent (uri, cookies) { var requests = []; self.request = function (params, cb) { - requests.push({ - params : params, - cb : function (err, res, body) { - cb(err, res, body); - next(); - } - }); + requests.push({ params : params, cb : cb }); return self; }; - self.end = function () { next() }; - - function next () { - var r = requests.shift(); - if (r) process(Hash.copy(r.params), r.cb); - } + self.end = function () { + if (!requests.length) return; + + (function next () { + var r = requests.shift(); + if (r) process(Hash.copy(r.params), function (err, res, body) { + r.cb(err, res, body); + next(); + }); + })(); + }; function process (params, cb) { var headers = Hash.copy(params.headers || {});