-
Notifications
You must be signed in to change notification settings - Fork 35
/
Copy pathindex.js
125 lines (100 loc) · 3.17 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
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
require('dotenv').config({silent : true});
var http = require('http');
var request = require('request');
var urlRegex = /^https?/;
var sizeLimit = process.env.SIZE_LIMIT || 512 * 1024;
var requestsLimit = process.env.REQ_LIMIT || 15;
var copyHeaders = ['user-agent', 'content-type'];
var reqIPs = [];
function createRequesHeaders(headers) {
var res = {};
Object.keys(headers).forEach(function(header) {
if (copyHeaders.indexOf(header) !== -1) {
res[header] = headers[header];
}
});
return res;
}
var getClientAddress = function (req) {
return (req.headers['x-forwarded-for'] || '').split(',')[0]
|| req.connection.remoteAddress;
}
function wrongURI(res) {
res.setHeader('Content-type', 'text/html');
res.writeHead(404);
res.end('<h1>Wrong request.</h1><p>For more info check out the spec:' +
' <a href="https://github.com/messier31/cors-proxy-spec">https://github.com/messier31/cors-proxy-spec</a></p>');
}
function banner(res) {
res.setHeader('Content-type', 'text/html');
res.writeHead(200);
res.end('<h1>CORS PROXY SERVER</h1><p><a href="https://github.com/messier31/cors-proxy-server">' +
'https://github.com/messier31/cors-proxy-server</a></p>');
}
function limitExceed(res) {
res.setHeader('Content-type', 'text/html');
res.writeHead(403);
res.end('<h1>Limit Exceed.</h1><p>Exceed limit of '+ sizeLimit + ' bytes.</p>');
}
function limitRequestsBanner(res) {
res.setHeader('Content-type', 'text/html');
res.writeHead(429);
res.end('<h1>Requests Limit.</h1><p>Exceed limit of '+ requestsLimit + ' requests per 10sec.</p>');
}
function limitRequests(req, time) {
var ip = getClientAddress(req);
reqIPs = reqIPs.filter(function(r) {
return r.time > (time - (10000));
});
if (reqIPs.filter(function(r) { return r.ip === ip; }).length >= requestsLimit) {
return true;
}
reqIPs.push({ ip : ip , time : time});
return false;
}
http.createServer(function (req, res) {
var url = req.url.slice(1);
if (!urlRegex.test(url)) {
if (url.length < 1) {
banner(res);
} else {
wrongURI(res);
}
return;
}
var size = 0;
var time = new Date();
if (limitRequests(req, time.getTime()) === true) {
limitRequestsBanner(res);
return;
}
res.setTimeout(25000);
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, HEAD, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-type');
res.setHeader('Access-Control-Allow-Credentials', false);
var options = {
url : url,
encoding: null,
headers : createRequesHeaders(req.headers)
}
var client = request(options, function(error, response, body) {
if (!error) {
res.setHeader('Content-type', response.headers['content-type'] || 'text/plain');
res.setHeader('Date', response.headers['date'] || time.toString());
res.writeHead(Number(response.statusCode));
res.write(body);
res.end();
} else {
res.writeHead(500);
res.end('err');
}
});
client.on('data', function(chunk) {
size += chunk.length;
if (size >= sizeLimit) {
limitExceed(res);
client.abort();
}
});
}).listen(process.env.PORT)