forked from truongsinh/node-evercookie
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
100 lines (100 loc) · 3 KB
/
index.js
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
/*jshint node:true*/
'use strict';
var connect;
try {
connect = require('connect');
} catch(e) {
try {
connect = require('express');
} catch(e) {
throw new Error('Neither express nor connect is available');
}
}
var cookieParser = connect.cookieParser();
var noop = function noop(){};
module.exports = {
backend: function evercookieMiddlewareBackendFactory(opts) {
opts = opts || {};
var defaultOptionMap = {
etagCookieName: 'evercookie_etag',
cacheCookieName: 'evercookie_cache',
authPath: '/evercookie_auth.php',
pngPath: '/evercookie_png.php',
etagPath: '/evercookie_etag.php',
cachePath: '/evercookie_cache.php'
};
var optionMap = {
};
for(var key in defaultOptionMap) {
var overidenValue = opts[key];
if(overidenValue) {
optionMap[key] = opts[key];
} else {
optionMap[key] = defaultOptionMap[key];
}
}
function evercookieMiddlewareBackend(req, res, next) {
var cookieValue;
switch(req.path) {
case optionMap.authPath:
try{
cookieValue = new Buffer(req.headers.authorization.split(' ')[1], 'base64').toString().split(':')[0];
} catch(e){}
if(cookieValue){
res.send(cookieValue);
return;
}
res.setHeader('WWW-Authenticate', 'Basic');
res.send(401);
return;
case optionMap.pngPath:
/**
* PNG cache is technically no difference than text cache, but adds much more overhead to encode and decode.
* Return 201 No content
*/
res.send(201);
return;
case optionMap.etagPath:
/**
* Port to NodeJS by TruongSinh <i@truongsinh.pro>
* Defined by samy kamkar, https://github.com/samyk/evercookie/blob/master/evercookie_etag.php
*
* This is the server-side ETag software which tags a user by
* using the Etag HTTP header, as well as If-None-Match to check
* if the user has been tagged before.
*/
// cookieParser is sync, and check req.cookies internally
cookieParser(req, res, noop);
cookieValue = req.cookies[optionMap.etagCookieName];
if(!cookieValue) {
cookieValue = req.get('If-None-Match');
}
if(cookieValue) {
res.set('Etag', cookieValue);
res.send(cookieValue);
return;
}
res.send(304);
return;
case optionMap.cachePath:
// cookieParser is sync, and check req.cookies internally
cookieParser(req, res, noop);
cookieValue = req.cookies[optionMap.cacheCookieName];
if(cookieValue) {
res.set({
'Content-Type': 'text/html',
'Expires': 'Tue, 31 Dec 2030 23:30:45 GMT',
'Cache-Control': 'private, max-age=630720000'
});
res.send(cookieValue);
return;
}
res.send(304);
return;
default:
next();
}
}
return evercookieMiddlewareBackend;
}
};