123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- var needle = require('../'),
- cookies = require('../lib/cookies'),
- sinon = require('sinon'),
- http = require('http'),
- should = require('should');
- var WEIRD_COOKIE_NAME = 'wc',
- BASE64_COOKIE_NAME = 'bc',
- FORBIDDEN_COOKIE_NAME = 'fc',
- NUMBER_COOKIE_NAME = 'nc';
- var WEIRD_COOKIE_VALUE = '!\'*+#()&-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~',
- BASE64_COOKIE_VALUE = 'Y29va2llCg==',
- FORBIDDEN_COOKIE_VALUE = ' ;"\\,',
- NUMBER_COOKIE_VALUE = 12354342;
- var NO_COOKIES_TEST_PORT = 11112,
- ALL_COOKIES_TEST_PORT = 11113;
- describe('cookies', function() {
- var setCookieHeader, headers, server, opts;
- function decode(str) {
- return decodeURIComponent(str);
- }
- function encode(str) {
- str = str.toString().replace(/[\x00-\x1F\x7F]/g, encodeURIComponent);
- return str.replace(/[\s\"\,;\\%]/g, encodeURIComponent);
- }
- before(function() {
- setCookieHeader = [
- WEIRD_COOKIE_NAME + '=' + encode(WEIRD_COOKIE_VALUE) + ';',
- BASE64_COOKIE_NAME + '=' + encode(BASE64_COOKIE_VALUE) + ';',
- FORBIDDEN_COOKIE_NAME + '=' + encode(FORBIDDEN_COOKIE_VALUE) + ';',
- NUMBER_COOKIE_NAME + '=' + encode(NUMBER_COOKIE_VALUE) + ';'
- ];
- });
- before(function(done) {
- serverAllCookies = http.createServer(function(req, res) {
- res.setHeader('Content-Type', 'text/html');
- res.setHeader('Set-Cookie', setCookieHeader);
- res.end('200');
- }).listen(ALL_COOKIES_TEST_PORT, done);
- });
- after(function(done) {
- serverAllCookies.close(done);
- });
- describe('with default options', function() {
- it('no cookie header is set on request', function(done) {
- needle.get(
- 'localhost:' + ALL_COOKIES_TEST_PORT, function(err, response) {
- should.not.exist(response.req._headers.cookie);
- done();
- });
- });
- });
- describe('if response does not contain cookies', function() {
- before(function(done) {
- serverNoCookies = http.createServer(function(req, res) {
- res.setHeader('Content-Type', 'text/html');
- res.end('200');
- }).listen(NO_COOKIES_TEST_PORT, done);
- });
- it('response.cookies is undefined', function(done) {
- needle.get(
- 'localhost:' + NO_COOKIES_TEST_PORT, function(error, response) {
- should.not.exist(response.cookies);
- done();
- });
- });
- after(function(done) {
- serverNoCookies.close(done);
- });
- });
- describe('if response contains cookies', function() {
- it('puts them on resp.cookies', function(done) {
- needle.get(
- 'localhost:' + ALL_COOKIES_TEST_PORT, function(error, response) {
- response.should.have.property('cookies');
- done();
- });
- });
- it('parses them as a object', function(done) {
- needle.get(
- 'localhost:' + ALL_COOKIES_TEST_PORT, function(error, response) {
- response.cookies.should.be.an.instanceOf(Object)
- .and.have.property(WEIRD_COOKIE_NAME);
- response.cookies.should.have.property(BASE64_COOKIE_NAME);
- response.cookies.should.have.property(FORBIDDEN_COOKIE_NAME);
- response.cookies.should.have.property(NUMBER_COOKIE_NAME);
- done();
- });
- });
- it('must decode it', function(done) {
- needle.get(
- 'localhost:' + ALL_COOKIES_TEST_PORT, function(error, response) {
- response.cookies.wc.should.be.eql(WEIRD_COOKIE_VALUE);
- response.cookies.bc.should.be.eql(BASE64_COOKIE_VALUE);
- response.cookies.fc.should.be.eql(FORBIDDEN_COOKIE_VALUE);
- response.cookies.nc.should.be.eql(NUMBER_COOKIE_VALUE.toString());
- done();
- });
- });
- describe('when a cookie value is invalid', function() {
- before(function() {
- setCookieHeader = [
- 'geo_city=%D1%E0%ED%EA%F2-%CF%E5%F2%E5%F0%E1%F3%F0%E3'
- ];
- })
- it('doesnt blow up', function(done) {
- needle.get('localhost:' + ALL_COOKIES_TEST_PORT, function(error, response) {
- should.not.exist(error)
- var whatever = 'efbfbdefbfbdefbfbdefbfbdefbfbd2defbfbdefbfbdefbfbdefbfbdefbfbdefbfbdefbfbdefbfbdefbfbd';
- Buffer.from(response.cookies.geo_city).toString('hex').should.eql(whatever)
- done();
- });
- })
- })
- describe('and response is a redirect', function() {
- var redirectServer, testPort = 22222;
- var requestCookies = [];
- var responseCookies = [
- [ // first req
- WEIRD_COOKIE_NAME + '=' + encode(WEIRD_COOKIE_VALUE) + ';',
- BASE64_COOKIE_NAME + '=' + encode(BASE64_COOKIE_VALUE) + ';',
- 'FOO=123;'
- ], [ // second req
- FORBIDDEN_COOKIE_NAME + '=' + encode(FORBIDDEN_COOKIE_VALUE) + ';',
- NUMBER_COOKIE_NAME + '=' + encode(NUMBER_COOKIE_VALUE) + ';'
- ], [ // third red
- 'FOO=BAR;'
- ]
- ]
- before(function(done) {
- redirectServer = http.createServer(function(req, res) {
- var number = parseInt(req.url.replace('/', ''));
- var nextUrl = 'http://' + 'localhost:' + testPort + '/' + (number + 1);
- if (number == 0) requestCookies = []; // reset
- requestCookies.push(req.headers['cookie']);
- if (responseCookies[number]) { // we should send cookies for this request
- res.statusCode = 302;
- res.setHeader('Set-Cookie', responseCookies[number]);
- res.setHeader('Location', nextUrl);
- } else if (number == 3) {
- res.statusCode = 302; // redirect but without cookies
- res.setHeader('Location', nextUrl);
- }
- res.end('OK');
- }).listen(22222, done);
- });
- after(function(done) {
- redirectServer.close(done);
- })
- describe('and follow_set_cookies is false', function() {
- describe('with original request cookie', function() {
- var opts = {
- follow_set_cookies: false,
- follow_max: 4,
- cookies: { 'xxx': 123 }
- };
- it('request cookie is not passed to redirects', function(done) {
- needle.get('localhost:' + testPort + '/0', opts, function(err, resp) {
- requestCookies.should.eql(["xxx=123", undefined, undefined, undefined, undefined])
- done();
- });
- });
- it('response cookies are not passed either', function(done) {
- needle.get('localhost:' + testPort + '/0', opts, function(err, resp) {
- should.not.exist(resp.cookies);
- done();
- });
- });
- })
- describe('without original request cookie', function() {
- var opts = {
- follow_set_cookies: false,
- follow_max: 4,
- };
- it('no request cookies are sent', function(done) {
- needle.get('localhost:' + testPort + '/0', opts, function(err, resp) {
- requestCookies.should.eql([undefined, undefined, undefined, undefined, undefined])
- done();
- });
- });
- it('response cookies are not passed either', function(done) {
- needle.get('localhost:' + testPort + '/0', opts, function(err, resp) {
- should.not.exist(resp.cookies);
- done();
- });
- });
- })
- });
- describe('and follow_set_cookies is true', function() {
- describe('with original request cookie', function() {
- var opts = {
- follow_set_cookies: true,
- follow_max: 4,
- cookies: { 'xxx': 123 }
- };
- it('request cookie is passed passed to redirects, and response cookies are added too', function(done) {
- needle.get('localhost:' + testPort + '/0', opts, function(err, resp) {
- requestCookies.should.eql([
- "xxx=123",
- "xxx=123; wc=!'*+#()&-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~; bc=Y29va2llCg==; FOO=123",
- "xxx=123; wc=!\'*+#()&-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~; bc=Y29va2llCg==; FOO=123; fc=%20%3B%22%5C%2C; nc=12354342",
- "xxx=123; wc=!\'*+#()&-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~; bc=Y29va2llCg==; FOO=BAR; fc=%20%3B%22%5C%2C; nc=12354342",
- "xxx=123; wc=!\'*+#()&-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~; bc=Y29va2llCg==; FOO=BAR; fc=%20%3B%22%5C%2C; nc=12354342"
- ])
- done();
- });
- });
- it('response cookies are passed as well', function(done) {
- needle.get('localhost:' + testPort + '/0', opts, function(err, resp) {
- resp.cookies.should.have.property(WEIRD_COOKIE_NAME);
- resp.cookies.should.have.property(BASE64_COOKIE_NAME);
- resp.cookies.should.have.property(FORBIDDEN_COOKIE_NAME);
- resp.cookies.should.have.property(NUMBER_COOKIE_NAME);
- resp.cookies.should.have.property('FOO');
- resp.cookies.FOO.should.eql('BAR'); // should overwrite previous one
- done();
- });
- });
- })
- describe('without original request cookie', function() {
- var opts = {
- follow_set_cookies: true,
- follow_max: 4,
- };
- it('response cookies are passed to redirects', function(done) {
- needle.get('localhost:' + testPort + '/0', opts, function(err, resp) {
- requestCookies.should.eql([
- undefined,
- "wc=!'*+#()&-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~; bc=Y29va2llCg==; FOO=123",
- "wc=!\'*+#()&-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~; bc=Y29va2llCg==; FOO=123; fc=%20%3B%22%5C%2C; nc=12354342",
- "wc=!\'*+#()&-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~; bc=Y29va2llCg==; FOO=BAR; fc=%20%3B%22%5C%2C; nc=12354342",
- "wc=!\'*+#()&-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~; bc=Y29va2llCg==; FOO=BAR; fc=%20%3B%22%5C%2C; nc=12354342"
- ])
- done();
- });
- });
- it('response cookies are passed as well', function(done) {
- needle.get('localhost:' + testPort + '/0', opts, function(err, resp) {
- // resp.cookies.should.have.property(WEIRD_COOKIE_NAME);
- // resp.cookies.should.have.property(BASE64_COOKIE_NAME);
- // resp.cookies.should.have.property(FORBIDDEN_COOKIE_NAME);
- // resp.cookies.should.have.property(NUMBER_COOKIE_NAME);
- // resp.cookies.should.have.property('FOO');
- // resp.cookies.FOO.should.eql('BAR'); // should overwrite previous one
- done();
- });
- });
- })
- });
- });
- describe('with parse_cookies = false', function() {
- it('does not parse them', function(done) {
- needle.get(
- 'localhost:' + ALL_COOKIES_TEST_PORT, { parse_cookies: false }, function(error, response) {
- should.not.exist(response.cookies);
- done();
- });
- });
- });
- });
- describe('if request contains cookie header', function() {
- var opts = {
- cookies: {}
- };
- before(function() {
- opts.cookies[WEIRD_COOKIE_NAME] = WEIRD_COOKIE_VALUE;
- opts.cookies[BASE64_COOKIE_NAME] = BASE64_COOKIE_VALUE;
- opts.cookies[FORBIDDEN_COOKIE_NAME] = FORBIDDEN_COOKIE_VALUE;
- opts.cookies[NUMBER_COOKIE_NAME] = NUMBER_COOKIE_VALUE;
- });
- it('must be a valid cookie string', function(done) {
- var COOKIE_PAIR = /^([^=\s]+)\s*=\s*("?)\s*(.*)\s*\2\s*$/;
- var full_header = [
- WEIRD_COOKIE_NAME + '=' + WEIRD_COOKIE_VALUE,
- BASE64_COOKIE_NAME + '=' + BASE64_COOKIE_VALUE,
- FORBIDDEN_COOKIE_NAME + '=' + encode(FORBIDDEN_COOKIE_VALUE),
- NUMBER_COOKIE_NAME + '=' + NUMBER_COOKIE_VALUE
- ].join('; ')
- needle.get('localhost:' + ALL_COOKIES_TEST_PORT, opts, function(error, response) {
- var cookieString = response.req._headers.cookie;
- cookieString.should.be.type('string');
- cookieString.split(/\s*;\s*/).forEach(function(pair) {
- COOKIE_PAIR.test(pair).should.be.exactly(true);
- });
- cookieString.should.be.exactly(full_header);
- done();
- });
- });
- it('dont have to encode allowed characters', function(done) {
- var COOKIE_PAIR = /^([^=\s]+)\s*=\s*("?)\s*(.*)\s*\2\s*$/,
- KEY_INDEX = 1,
- VALUE_INEX = 3;
- needle.get('localhost:' + ALL_COOKIES_TEST_PORT, opts, function(error, response) {
- var cookieObj = {},
- cookieString = response.req._headers.cookie;
- cookieString.split(/\s*;\s*/).forEach(function(str) {
- var pair = COOKIE_PAIR.exec(str);
- cookieObj[pair[KEY_INDEX]] = pair[VALUE_INEX];
- });
- cookieObj[WEIRD_COOKIE_NAME].should.be.exactly(WEIRD_COOKIE_VALUE);
- cookieObj[BASE64_COOKIE_NAME].should.be.exactly(BASE64_COOKIE_VALUE);
- done();
- });
- });
- it('must encode forbidden characters', function(done) {
- var COOKIE_PAIR = /^([^=\s]+)\s*=\s*("?)\s*(.*)\s*\2\s*$/,
- KEY_INDEX = 1,
- VALUE_INEX = 3;
- needle.get('localhost:' + ALL_COOKIES_TEST_PORT, opts, function(error, response) {
- var cookieObj = {},
- cookieString = response.req._headers.cookie;
- cookieString.split(/\s*;\s*/).forEach(function(str) {
- var pair = COOKIE_PAIR.exec(str);
- cookieObj[pair[KEY_INDEX]] = pair[VALUE_INEX];
- });
- cookieObj[FORBIDDEN_COOKIE_NAME].should.not.be.eql(
- FORBIDDEN_COOKIE_VALUE);
- cookieObj[FORBIDDEN_COOKIE_NAME].should.be.exactly(
- encode(FORBIDDEN_COOKIE_VALUE));
- cookieObj[FORBIDDEN_COOKIE_NAME].should.be.exactly(
- encodeURIComponent(FORBIDDEN_COOKIE_VALUE));
- done();
- });
- });
- });
- });
|