Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

needle

Package Overview
Dependencies
Maintainers
1
Versions
112
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

needle - npm Package Compare versions

Comparing version 0.9.1 to 0.9.2

test/cookies_spec.js.orig

120

lib/cookies.js

@@ -1,77 +0,81 @@

var valid_keys = ['domain', 'path', 'expires', 'httponly', 'secure'];
//
// Simple cookie handling implementation based on the standard RFC 6265.
// This module just has two functionalities:
// - Parse a set-cookie-header as a key value object
// - Write a cookie-string from a key value object
// All cookie attributes are ignored.
//
// modified version of the parse function from the cookie lib by jshttp:
// https://github.com/jshttp/cookie/blob/master/index.js
// RegExps
function parse(str, opt) {
var COOKIE_PAIR = /^([^=\s]+)\s*=\s*("?)\s*(.*)\s*\2\s*$/;
var EXCLUDED_CHARS = /[\x00-\x1F\x7F\x3B\x3B\s\"\,\\"%]/g;
var TRAILING_SEMICOLON = /\x3B+$/;
var SEP_SEMICOLON = /\s*\x3B\s*/;
var obj = {},
res = {},
pairs = str.split(/; */), // matches no whitespace too
dec = decodeURIComponent;
// Constants
pairs.forEach(function(pair) {
var index = pair.indexOf('=');
var KEY_INDEX = 1; // index of key from COOKIE_PAIR match
var VALUE_INDEX = 3; // index of value from COOKIE_PAIR match
// skip things that don't look like key=value
if (index < 0)
return;
// Convenience functions
var key = pair.substr(0, index).trim(),
val = pair.substr(++index, pair.length).trim();
// Returns a copy str trimmed and without trainling semicolon.
function cleanCookieString(str) {
return str.trim().replace(/\x3B+$/, '');
}
// quoted values
if ('"' == val[0]) {
val = val.slice(1, -1);
}
function getFirstPair(str) {
var index = str.indexOf('\x3B');
return index === -1 ? str : str.substr(0, index);
}
// only assign once
if (undefined == obj[key]) {
try {
obj[key] = dec(val);
} catch (e) {
obj[key] = val;
}
}
});
// Private functions
// if key is part of valid_keys, set it, otherwise set it as key=[key] and value=[val]
for (var key in obj) {
if (valid_keys.indexOf(key.toLowerCase()) != -1) {
res[key] = obj[key];
} else {
res.key = key;
res.value = obj[key];
}
}
// Returns a encoded copy of str based on RFC6265 S4.1.1.
function encodeCookieComponent(str) {
return str.toString().replace(EXCLUDED_CHARS, encodeURIComponent);
}
return res;
};
// Parses a set-cookie-string based on the standard definded in RFC6265 S4.1.1.
function parseSetCookieString(str) {
str = cleanCookieString(str);
str = getFirstPair(str);
function to_hash(arr, url) {
var res = {};
var res = COOKIE_PAIR.exec(str);
arr.forEach(function(obj) {
// if (!obj.path || (url.indexOf(obj.path) !== -1)) {
res[obj.key] = obj.value;
// }
})
return {
name: decodeURIComponent(res[KEY_INDEX]),
value: decodeURIComponent(res[VALUE_INDEX])
};
}
return res;
// Parses a set-cookie-header and returns a key/value object. Each key
// represent a name of a cookie.
function parseSetCookieHeader(header) {
header = (header instanceof Array) ? header : [header];
return header.reduce(function(res, str) {
var cookie = parseSetCookieString(str);
res[cookie.name] = cookie.value;
return res;
}, {});
}
// returns a key/val object from an array of
exports.read = function(header) {
var arr = (header instanceof Array) ? header : [header];
return to_hash(arr.map(function(c) { return parse(c); }));
// Writes a set-cookie-string based on the standard definded in RFC6265 S4.1.1.
function writeCookieString(obj) {
return Object.keys(obj).reduce(function(str, name) {
var encodedName = encodeCookieComponent(name);
var encodedValue = encodeCookieComponent(obj[name]);
str += (str ? "; " : "") + encodedName + '=' + encodedValue;
return str;
}, "");
}
exports.write = function(obj) {
var res, enc = encodeURIComponent;
// Module interface
res = Object.keys(obj).map(function(key) {
return enc(key) + '=' + enc(obj[key]);
})
// returns a key/val object from an array of cookie strings
exports.read = parseSetCookieHeader;
return res.join('; ');
};
// writes a cookie string header
exports.write = writeCookieString;

@@ -398,3 +398,3 @@ //////////////////////////////////////////

if (config.follow_set_cookies)
if (config.follow_set_cookies && resp.cookies)
config.headers['Cookie'] = cookies.write(resp.cookies);

@@ -401,0 +401,0 @@

@@ -16,3 +16,3 @@ // based on the qs module, but handles null objects as expected

} else {
throw new TypeError('Invalid object received:' + obj);
throw new TypeError('Cannot build a querystring out of: ' + obj);
}

@@ -19,0 +19,0 @@ };

{
"name": "needle",
"version": "0.9.1",
"version": "0.9.2",
"description": "The leanest and most handsome HTTP client in the Nodelands.",

@@ -5,0 +5,0 @@ "keywords": [

@@ -1,75 +0,204 @@

var needle = require('../'),
sinon = require('sinon'),
should = require('should'),
http = require('http'),
cookies = require('../lib/cookies');
var needle = require('../'),
sinon = require('sinon'),
http = require('http'),
should = require('should'),
assert = require('assert');
var WEIRD_COOKIE_NAME = 'wc',
BASE64_COOKIE_NAME = 'bc',
FORBIDDEN_COOKIE_NAME = 'fc',
NUMBER_COOKIE_NAME = 'nc',
WEIRD_COOKIE_VALUE = '!\'*+#()&-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[' +
']^_`abcdefghijklmnopqrstuvwxyz{|}~',
BASE64_COOKIE_VALUE = 'Y29va2llCg==',
FORBIDDEN_COOKIE_VALUE = ' ;"\\,',
NUMBER_COOKIE_VALUE = 12354342,
WEIRD_COOKIE = 'wc=!\'*+#()&-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~',
BASE64_COOKIE = 'bc=Y29va2llCg==',
FORBIDDEN_COOKIE = 'fc=%20%3B%22%5C%2C',
NUMBER_COOKIE = 'nc=12354342',
COOKIE_HEADER = WEIRD_COOKIE + '; ' + BASE64_COOKIE + '; ' +
FORBIDDEN_COOKIE + '; ' + NUMBER_COOKIE,
TEST_HOST = 'localhost';
NO_COOKIES_TEST_PORT = 11112, ALL_COOKIES_TEST_PORT = 11113;
function decode(str) {
return decodeURIComponent(str);
}
function encode(str) {
str = str.toString().replace(/[\x00-\x1F\x7F]/g, encodeURIComponent);
return str.replace(/[\s\"\,;\\%]/g, encodeURIComponent);
}
describe('cookies', function() {
var last_req;
var headers, server, opts;
var server = http.createServer(function(req, res) {
last_req = req;
res.end('Thanks.');
})
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) {
server.listen(function() {
port = this.address().port;
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, TEST_HOST, done);
});
after(function(done) {
server.close(done)
})
serverAllCookies.close(done);
});
describe('with default options', function() {
it('no cookie header is set on request', function(done) {
needle.get(
TEST_HOST + ':' + ALL_COOKIES_TEST_PORT, function(err, response) {
assert(!response.req._headers.cookie);
done();
});
});
});
it('no cookie header is set on request', function() {
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, TEST_HOST, done);
});
})
it('response.cookies is undefined', function(done) {
needle.get(
TEST_HOST + ':' + NO_COOKIES_TEST_PORT, function(error, response) {
assert(!response.cookies);
done();
});
});
})
after(function(done) {
serverNoCookies.close(done);
});
});
describe('if response does not contain cookies', function() {
describe('if response contains cookies', function() {
it('puts them on resp.cookies', function(done) {
needle.get(
TEST_HOST + ':' + ALL_COOKIES_TEST_PORT, function(error, response) {
response.should.have.property('cookies');
done();
});
});
it('resp.cookies is undefined', function() {
it('parses them as a object', function(done) {
needle.get(
TEST_HOST + ':' + 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(
TEST_HOST + ':' + 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('and response is a redirect', function() {
describe('and follow_set_cookies is false', function() {
it('no cookie header set on redirection request', function() {});
});
describe('and follow_set_cookies is true', function() {});
});
});
describe('if response contains cookies', function() {
describe('if resquest contains cookie header', function() {
var opts = {
cookies: {}
};
it('parses them', function() {
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*$/;
it('puts them on resp.cookies', function() {
needle.get(TEST_HOST + ':' + ALL_COOKIES_TEST_PORT, opts, function(error, response) {
var cookieString = response.req._headers.cookie;
})
cookieString.should.be.type('string');
describe('and response is a redirect', function() {
cookieString.split(/\s*;\s*/).forEach(function(pair) {
COOKIE_PAIR.test(pair).should.be.exactly(true);
});
describe('and follow_set_cookies is false', function() {
cookieString.should.be.exactly(COOKIE_HEADER);
})
done();
});
});
describe('and follow_set_cookies is true', function() {
})
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(TEST_HOST + ':' + 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];
});
describe('when passing an object on options.cookies', function() {
cookieObj[WEIRD_COOKIE_NAME].should.be.exactly(WEIRD_COOKIE_VALUE);
cookieObj[BASE64_COOKIE_NAME].should.be.exactly(BASE64_COOKIE_VALUE);
done();
});
});
it('sets the cookies', function() {
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(TEST_HOST + ':' + 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();
});
});
});
});

@@ -9,7 +9,6 @@ var should = require('should'),

var url;
this.timeout(5000);
describe('test A', function() {
this.timeout(5000);
before(function() {

@@ -44,3 +43,3 @@ url = 'http://www.huanqiukexue.com/html/newgc/2014/1215/25011.html';

})
})

@@ -47,0 +46,0 @@

@@ -110,27 +110,27 @@ var needle = require('../'),

it('emits end event once, with error', function(done) {
var called = 0,
var callcount = 0,
stream = needle.get(url);
stream.on('end', function(err) {
called++;
callcount++;
})
setTimeout(function() {
called.should.equal(1);
callcount.should.equal(1);
done();
}, 50)
}, 200)
})
it('error should be ENOTFOUND or EADDRINFO', function(done){
var error,
it('error should be ENOTFOUND or EADDRINFO', function(done) {
var errorific,
stream = needle.get(url);
stream.on('end', function(err) {
error = err;
errorific = err;
})
setTimeout(function() {
error.code.should.match(/ENOTFOUND|EADDRINFO/)
errorific.code.should.match(/ENOTFOUND|EADDRINFO/)
done();
}, 50)
}, 200)
})

@@ -137,0 +137,0 @@

@@ -64,3 +64,4 @@ var helpers = require('./helpers'),

var opts, // each test will modify this
url = protocol + '://localhost:' + ports[protocol] + '/hello';
host = '127.0.0.1',
url = protocol + '://' + host + ':' + ports[protocol] + '/hello';

@@ -165,3 +166,3 @@ function send_request(opts, cb) {

before(function() {
location = url.replace('localhost', hostname);
location = url.replace(host, hostname);
})

@@ -173,3 +174,3 @@ it('follows redirect', followed_same_protocol);

before(function() {
location = url.replace('localhost', hostname).replace(protocol, other_protocol).replace(ports[protocol], ports[other_protocol]);
location = url.replace(host, hostname).replace(protocol, other_protocol).replace(ports[protocol], ports[other_protocol]);
})

@@ -283,3 +284,3 @@ it('follows redirect', followed_other_protocol);

send_request(opts, function(err, resp) {
spies.http.args[0][0].headers['Referer'].should.eql("http://localhost:8888/hello");
spies.http.args[0][0].headers['Referer'].should.eql("http://" + host + ":8888/hello");
// spies.http.args[0][3].should.eql({ foo: 'bar'});

@@ -330,3 +331,3 @@ done();

before(function() {
location = url.replace('localhost', hostname);
location = url.replace(host, hostname);
})

@@ -347,3 +348,3 @@ it('follows redirect', followed_same_protocol);

before(function() {
location = url.replace('localhost', hostname);
location = url.replace(host, hostname);
})

@@ -365,3 +366,3 @@

before(function() {
location = url.replace('localhost', hostname).replace(protocol, other_protocol).replace(ports[protocol], ports[other_protocol]);
location = url.replace(host, hostname).replace(protocol, other_protocol).replace(ports[protocol], ports[other_protocol]);
})

@@ -382,3 +383,3 @@ it('follows redirect', followed_other_protocol);

before(function() {
location = url.replace('localhost', hostname).replace(protocol, other_protocol).replace(ports[protocol], ports[other_protocol]);
location = url.replace(host, hostname).replace(protocol, other_protocol).replace(ports[protocol], ports[other_protocol]);
})

@@ -385,0 +386,0 @@ it('does not follow redirect', not_followed);

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc