« index
Coverage for /Users/kris/q-io/http-apps/cookie.js : 86%
152 lines |
131 run |
21 missing |
2 partial |
33 blocks |
24 blocks run |
9 blocks missing
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | var Q = require("q"); var Cookie = require("../http-cookie"); exports.CookieJar = function (app) { var hostCookies = {}; // to {} of pathCookies to [] of cookies return function (request) { var hosts = allHostsContaining(request.headers.host); var now = new Date(); var requestCookies = concat(hosts.map(function (host) { // delete expired cookies for (var host in hostCookies) { var pathCookies = hostCookies[host]; for (var path in pathCookies) { var cookies = pathCookies[path]; for (var name in cookies) { var cookie = cookies[name]; if (cookie.expires && cookie.expires > now) { delete cookie[name]; } } } } // collect applicable cookies return concat( Object.keys(hostCookies) .map(function (host) { if (!hostContains(host, request.headers.host)) return []; var pathCookies = hostCookies[host]; return concat( Object.keys(pathCookies) .map(function (path) { if (!pathContains(path, request.path)) return []; var cookies = pathCookies[path]; return ( Object.keys(cookies) .map(function (name) { return cookies[name]; }) .filter(function (cookie) { return cookie.secure ? request.ssl : true; }) ); }) ) }) ); })); if (requestCookies.length) { request.headers["cookie"] = ( requestCookies .map(function (cookie) { return Cookie.stringify( cookie.key, cookie.value, cookie ); }) .join("; ") ); } return Q.when(app.apply(this, arguments), function (response) { response.headers = response.headers || {}; if (response.headers["set-cookie"]) { var requestHost = ipRe.test(request.headers.host) ? request.headers.host : "." + request.headers.host; // normalize to array if (!Array.isArray(response.headers["set-cookie"])) { response.headers["set-cookie"] = [response.headers["set-cookie"]]; } response.headers["set-cookie"].forEach(function (cookie) { var date = response.headers["date"] ? new Date(response.headers["date"]) : new Date(); cookie = Cookie.parse(cookie, date); // ignore illegal host if (cookie.host && !hostContains(requestHost, cookie.host)) delete cookie.host; var host = requestHost || cookie.host; var path = cookie.path || "/"; var pathCookies = hostCookies[host] = hostCookies[host] || {}; var cookies = pathCookies[path] = pathCookies[path] || {}; cookies[cookie.key] = cookie; }) delete response.headers["set-cookie"]; } return response; }); }; }; var ipRe = /^\d+\.\d+\.\d+\.\d+$/; function allHostsContaining(content) { if (ipRe.test(content)) { return [content]; } if (content === "localhost") { return [content]; } else { var parts = content.split("."); var hosts = []; while (parts.length > 1) { hosts.push("." + parts.join(".")); parts.shift(); } return hosts; } } function hostContains(container, content) { if (ipRe.test(container) || ipRe.test(content)) { return container === content; } else if (/^\./.test(container)) { return ( content.lastIndexOf(container) === content.length - container.length ) || ( container.slice(1) === content ); } else { return container === content; } }; function pathContains(container, content) { if (/^\/$/.test(container)) { return content.indexOf(container) === 0; } else { return ( content === container || content.indexOf(container + "/") === 0 ); } } function concat(arrays) { return [].concat.apply([], arrays); } |