Skip to content

Commit 2f2f0b5

Browse files
committed
Improve cookie rewriting nfriedly#91
1 parent 1d96d6e commit 2f2f0b5

File tree

1 file changed

+59
-12
lines changed

1 file changed

+59
-12
lines changed

lib/cookies.js

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
var URL = require('url');
2-
var libCookie = require('cookie');
32
var setCookie = require('set-cookie-parser');
43
var TLD = require('tld');
54
var Transform = require('stream').Transform;
@@ -21,6 +20,54 @@ function cookies(config) {
2120

2221
var REDIRECT_QUERY_PARAM = '__proxy_cookies_to';
2322

23+
// Serializes cookie without changing it
24+
function serializeCookie(cookie) {
25+
var str = cookie.name + '=' + cookie.value;
26+
27+
if (cookie.maxAge) {
28+
str += '; Max-Age=' + cookie.maxAge;
29+
}
30+
if (cookie.domain) {
31+
str += '; Domain=' + cookie.domain;
32+
}
33+
if (cookie.path) {
34+
str += '; Path=' + cookie.path;
35+
}
36+
if (cookie.expires) {
37+
str += '; Expires=' + cookie.expires.toUTCString();
38+
}
39+
if (cookie.httpOnly) {
40+
str += '; HttpOnly';
41+
}
42+
if (cookie.secure) {
43+
str += '; Secure';
44+
}
45+
return str;
46+
}
47+
48+
// Parses the cookies without changing its value
49+
function parseCookies(rawCookies) {
50+
var obj = {};
51+
var cookies;
52+
if(typeof rawCookies !== 'string') return {};
53+
if(rawCookies === '') return {};
54+
cookies = rawCookies.split(';');
55+
for (var i = 0, ii = cookies.length; i < ii; i++) {
56+
// Removes first space if there is one
57+
// V8 should always support trimLeft even though there is no standard for it.
58+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trimLeft
59+
// https://www.npmjs.com/package/string could be a solution in case trimLeft() is dropped from V8.
60+
cookies[i] = cookies[i].trimLeft();
61+
// Puts the name and value in the object obj.
62+
if(cookies[i].indexOf('=') !== -1) {
63+
obj[cookies[i].substring(0, cookies[i].indexOf('='))] = cookies[i].substring(cookies[i].indexOf('=') + 1);
64+
} else {
65+
obj[cookies[i]] = '';
66+
}
67+
}
68+
return obj;
69+
}
70+
2471
// normally we do nothing here, but when the user is switching protocols or subdomains, the handleResponse function
2572
// will rewrite the links to start with the old protocol & domain (so that we get sent the cookies), and then it
2673
// will copy the old cookies to the new path
@@ -29,10 +76,11 @@ function cookies(config) {
2976
if (uri.query[REDIRECT_QUERY_PARAM]) {
3077
var nextUri = URL.parse(uri.query[REDIRECT_QUERY_PARAM]);
3178
debug('copying cookies from %s to %s', data.url, uri.query[REDIRECT_QUERY_PARAM]);
32-
var cookies = libCookie.parse(data.headers.cookie || '');
79+
var cookies = parseCookies(data.headers.cookie || '');
3380
var setCookieHeaders = Object.keys(cookies).map(function(name) {
34-
var value = cookies[name];
35-
return libCookie.serialize(name, value, {
81+
return serializeCookie({
82+
name: name,
83+
value: cookies[name],
3684
path: config.prefix + nextUri.protocol + '//' + nextUri.host + '/'
3785
});
3886
});
@@ -54,18 +102,15 @@ function cookies(config) {
54102
}
55103

56104
// first update any set-cookie headers to ensure the path is prefixed with the site
57-
var cookies = setCookie.parse(data, {
58-
decodeValues: false // Calls dcodeURIComponent on each value - but we want to just pass them along unchanged in this case.
59-
});
105+
var cookies = setCookie.parse(data);
60106
if (cookies.length) {
61107
debug('remaping set-cookie headers');
62108
data.headers['set-cookie'] = cookies.map(function(cookie) {
63109
var targetUri = nextUri || uri;
64110
cookie.path = config.prefix + targetUri.protocol + '//' + targetUri.host + (cookie.path || '/');
65111
delete cookie.domain;
66112
delete cookie.secure; // todo: maybe leave this if we knot the proxy is being accessed over https?
67-
cookie.value = decodeURIComponent(cookie.value); // Used to avoid double percent-encoding
68-
return libCookie.serialize(cookie.name, cookie.value, cookie);
113+
return serializeCookie(cookie);
69114
});
70115
}
71116

@@ -77,9 +122,11 @@ function cookies(config) {
77122
debug('copying cookies from %s to %s', data.url, data.redirectUrl);
78123

79124
// get all of the old cookies (from the request) indexed by name, and create set-cookie headers for each one
80-
var oldCookies = libCookie.parse(data.clientRequest.headers.cookie || '');
125+
var oldCookies = parseCookies(data.clientRequest.headers.cookie || '');
81126
var oldSetCookieHeaders = _.mapValues(oldCookies, function(value, name) {
82-
return libCookie.serialize(name, value, {
127+
return serializeCookie({
128+
name: name,
129+
value: value,
83130
path: config.prefix + nextUri.protocol + '//' + nextUri.host + '/'
84131
});
85132
});
@@ -132,4 +179,4 @@ function cookies(config) {
132179
}
133180

134181

135-
module.exports = cookies;
182+
module.exports = cookies;

0 commit comments

Comments
 (0)