Файл index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Proxy Server</title>
</head>
<body>
<form method="GET" action="proxy">
<input name="proxyreq" type="text" value="http://127.0.0.2:80/" />
<input type="submit" value="Показать" />
</form>
</body>
</html>
Файл proxy.js (загружает также картинку favicon.png)
var http = require('http')
, url = require('url')
, querystring = require('querystring')
, path = require('path')
, fs = require('fs')
, replaceHTML = require('./replaceHTML')
, replaceCSS = require('./replaceCSS')
, replaceJavaScript = require('./replaceJavaScript');
var proxyHost = '127.0.0.1'
, proxyPort = 80;
var proxyServer = http.createServer();
proxyServer.on('request', function (proxyRequest, proxyResponse) {
var reqUrl = url.parse(proxyRequest.url)
, pathname = reqUrl.pathname;
if (pathname === '/' || pathname === 'index.html') {
fs.readFile(path.resolve(path.join(__dirname, 'index.html')), function (error, data) {
if (error) {throw error;}
proxyResponse.writeHead(200, 'OK', {'Content-Type': 'text/html'});
proxyResponse.write(data);
proxyResponse.end();
});
} else if (pathname === '/favicon.ico') {
fs.readFile('./favicon.png', function (error, data) {
if (error) {throw error;}
response.writeHead(200, 'OK', {'Content-Type': 'image/png', 'Content-Length': Buffer.byteLength(data)});
response.write(data);
response.end();
});
} else if (pathname.indexOf('/proxyform/') === 0) {
var proxyreq = pathname.slice('/proxyform/'.length);
proxyreq = querystring.unescape(proxyreq);
proxyreq = path.posix.normalize(proxyreq);
proxyreq = proxyreq.replace('http:/', 'http://');
var proxyUrl = url.parse(proxyreq);
var requestOptions = {
method: proxyRequest.method
, protocol: proxyUrl.protocol
, hostname: proxyUrl.hostname
, port: proxyUrl.port
, path: proxyUrl.pathname + (proxyRequest.method === 'GET' ? url.parse(proxyRequest.url).search : '')
, headers: proxyRequest.headers
};
var requestToOutterServer = http.request(requestOptions);
requestToOutterServer.on('response', function (outterServerResponse) {
var outterServerResponseData = [];
outterServerResponse.on('data', function (chunk) {outterServerResponseData.push(chunk);});
outterServerResponse.on('end', function () {
if (outterServerResponse.headers['content-type'] === 'text/html') {
outterServerResponseData = replaceHTML(
outterServerResponseData.join('')
, 'http://' + proxyHost + ':' + proxyPort + '/proxy/?proxyreq='
, proxyUrl.protocol + '//' + proxyUrl.hostname + ':' + proxyUrl.port
);
outterServerResponse.headers['content-length'] = Buffer.byteLength(outterServerResponseData);
proxyResponse.writeHead(outterServerResponse.statusCode, outterServerResponse.statusMessage, outterServerResponse.headers);
proxyResponse.end(outterServerResponseData);
} else if (outterServerResponse.headers['content-type'] === 'text/css') {
outterServerResponseData = replaceCSS(
outterServerResponseData.join('')
, 'http://' + proxyHost + ':' + proxyPort + '/proxy/?proxyreq='
, proxyUrl.protocol + '//' + proxyUrl.hostname + ':' + proxyUrl.port
, path.parse(proxyUrl.pathname).dir
);
outterServerResponse.headers['content-length'] = Buffer.byteLength(outterServerResponseData);
proxyResponse.writeHead(outterServerResponse.statusCode, outterServerResponse.statusMessage, outterServerResponse.headers);
proxyResponse.end(outterServerResponseData);
} else if (outterServerResponse.headers['content-type'] === 'text/javascript') {
outterServerResponseData = replaceJavaScript(
outterServerResponseData.join('')
, 'http://' + proxyHost + ':' + proxyPort + '/proxy/?proxyreq='
, proxyUrl.protocol + '//' + proxyUrl.hostname + ':' + proxyUrl.port
);
outterServerResponse.headers['content-length'] = Buffer.byteLength(outterServerResponseData);
proxyResponse.writeHead(outterServerResponse.statusCode, outterServerResponse.statusMessage, outterServerResponse.headers);
proxyResponse.end(outterServerResponseData);
} else {
proxyResponse.writeHead(outterServerResponse.statusCode, outterServerResponse.statusMessage, outterServerResponse.headers);
outterServerResponseData.forEach(function (chunk) {
proxyResponse.write(chunk);
});
proxyResponse.end();
}
});
});
requestToOutterServer.on('error', function (error) {
console.log(requestOptions);
/*
console.error(error);
proxyResponse.writeHead(500, 'Internal Server Error', {'Content-Type': 'text/html'});
proxyResponse.write('500 Internal Server Error');
proxyResponse.end();
*/
throw error;
});
if (proxyRequest.method === 'GET') {
requestToOutterServer.end();
} else if (proxyRequest.method === 'POST') {
proxyRequest.on('data', function (chunk) {requestToOutterServer.write(chunk);});
proxyRequest.on('end', function () {requestToOutterServer.end();});
}
} else if (pathname.indexOf('/proxy') === 0) {
if (reqUrl.search) {
var searchData = reqUrl.search.slice(1);
searchData = querystring.parse(searchData);
var proxyreq = searchData.proxyreq;
proxyreq = querystring.unescape(proxyreq);
proxyreq = path.posix.normalize(proxyreq);
proxyreq = proxyreq.replace('http:/', 'http://');
var proxyUrl = url.parse(proxyreq);
delete searchData.proxyreq;
var requestOptions = {
method: proxyRequest.method
, protocol: proxyUrl.protocol
, hostname: proxyUrl.hostname
, port: proxyUrl.port
, path: proxyUrl.pathname + (proxyRequest.method === 'GET' ? querystring.stringify(searchData) : '')
, headers: proxyRequest.headers
};
var requestToOutterServer = http.request(requestOptions);
requestToOutterServer.on('response', function (outterServerResponse) {
var outterServerResponseData = [];
outterServerResponse.on('data', function (chunk) {outterServerResponseData.push(chunk);});
outterServerResponse.on('end', function () {
if (outterServerResponse.headers['content-type'] === 'text/html') {
outterServerResponseData = replaceHTML(
outterServerResponseData.join('')
, 'http://' + proxyHost + ':' + proxyPort + '/proxy/?proxyreq='
, proxyUrl.protocol + '//' + proxyUrl.hostname + ':' + proxyUrl.port
);
outterServerResponse.headers['content-length'] = Buffer.byteLength(outterServerResponseData);
proxyResponse.writeHead(outterServerResponse.statusCode, outterServerResponse.statusMessage, outterServerResponse.headers);
proxyResponse.end(outterServerResponseData);
} else if (outterServerResponse.headers['content-type'] === 'text/css') {
outterServerResponseData = replaceCSS(
outterServerResponseData.join('')
, 'http://' + proxyHost + ':' + proxyPort + '/proxy/?proxyreq='
, proxyUrl.protocol + '//' + proxyUrl.hostname + ':' + proxyUrl.port
, path.parse(proxyUrl.pathname).dir
);
outterServerResponse.headers['content-length'] = Buffer.byteLength(outterServerResponseData);
proxyResponse.writeHead(outterServerResponse.statusCode, outterServerResponse.statusMessage, outterServerResponse.headers);
proxyResponse.end(outterServerResponseData);
} else if (outterServerResponse.headers['content-type'] === 'text/javascript') {
outterServerResponseData = replaceJavaScript(
outterServerResponseData.join('')
, 'http://' + proxyHost + ':' + proxyPort + '/proxy/?proxyreq='
, proxyUrl.protocol + '//' + proxyUrl.hostname + ':' + proxyUrl.port
);
outterServerResponse.headers['content-length'] = Buffer.byteLength(outterServerResponseData);
proxyResponse.writeHead(outterServerResponse.statusCode, outterServerResponse.statusMessage, outterServerResponse.headers);
proxyResponse.end(outterServerResponseData);
} else {
proxyResponse.writeHead(outterServerResponse.statusCode, outterServerResponse.statusMessage, outterServerResponse.headers);
outterServerResponseData.forEach(function (chunk) {
proxyResponse.write(chunk);
});
proxyResponse.end();
}
});
});
requestToOutterServer.on('error', function (error) {
console.log(requestOptions);
/*
console.error(error);
proxyResponse.writeHead(500, 'Internal Server Error', {'Content-Type': 'text/html'});
proxyResponse.write('500 Internal Server Error');
proxyResponse.end();
*/
throw error;
});
if (proxyRequest.method === 'GET') {
requestToOutterServer.end();
} else if (proxyRequest.method === 'POST') {
proxyRequest.on('data', function (chunk) {requestToOutterServer.write(chunk);});
proxyRequest.on('end', function () {requestToOutterServer.end();});
}
} else {
proxyResponse.writeHead(200, 'OK', {'Content-Type': 'text/html'});
proxyResponse.write('<p>Адрес не задан.</p>');
proxyResponse.write('<a href="/">Вернуться на страницу ввода адреса.</a>');
proxyResponse.end();
}
} else {
proxyResponse.writeHead(404, 'Not Found', {'Content-Type': 'text/html'});
proxyResponse.write('404 Not Found');
proxyResponse.end();
}
});
proxyServer.on('error', function (error) {throw error;});
proxyServer.listen(proxyPort, proxyHost, function () {
console.log('Proxy server started at ' + proxyHost + ':' + proxyPort);
});
Файл replaceHTML.js
var querystring = require('querystring');
function replacePath (htmlString, regexp, proxyServerAddress, outterServerAddress) {
return htmlString.replace(regexp, function (match, $1, $2, $3) {
var newPath;
if ($2.indexOf('http') === 0) {
newPath = proxyServerAddress + querystring.escape($2);
} else if ($2.indexOf('/') === 0) {
newPath = proxyServerAddress + querystring.escape(outterServerAddress + $2);
} else {
newPath = proxyServerAddress + querystring.escape(outterServerAddress + '/' + $2);
}
return $1 + newPath + $3;
});
}
function replaceHref (htmlString, proxyServerAddress, outterServerAddress) {
return replacePath(htmlString, /(href=")([^"]+)(")/gi, proxyServerAddress, outterServerAddress)
}
/*
console.log(replaceHref([
'<link href="style1.css" rel="stylesheet" type="text/css" />'
, '<link href="/style2.css" rel="stylesheet" type="text/css" />'
, '<link href="http://www.google.com/style3.css" rel="stylesheet" type="text/css" />'
].join(' | '), 'http://127.0.0.1:80/?proxyreq=', 'http://127.0.0.2:80'));
*/
function replaceSrc (htmlString, proxyServerAddress, outterServerAddress) {
return replacePath(htmlString, /(src=")([^"]+)(")/gi, proxyServerAddress, outterServerAddress)
}
/*
console.log(replaceSrc([
'<img src="image1.png" />'
, '<img src="/image2.png" />'
, '<img src="http://www.google.com/image3.png" />'
].join(' | '), 'http://127.0.0.1:80/?proxyreq=', 'http://127.0.0.2:80'));
*/
function replaceAction (htmlString, proxyServerAddress, outterServerAddress) {
proxyServerAddress = proxyServerAddress.replace('/proxy/?proxyreq=', '/proxyform/');
return htmlString.replace(/(action=")([^"]+)(")/gi, function (match, $1, $2, $3) {
var newPath;
if ($2.indexOf('http') === 0) {
newPath = proxyServerAddress + querystring.escape($2);
} else if ($2.indexOf('/') === 0) {
newPath = proxyServerAddress + querystring.escape(outterServerAddress + $2);
} else {
newPath = proxyServerAddress + querystring.escape(outterServerAddress + '/' + $2);
}
return $1 + newPath + $3;
});
// return replacePath(htmlString, /(action=")([^"]+)(")/gi, proxyServerAddress, outterServerAddress)
}
/*
console.log(replaceAction([
'<form action="submit" method="GET"><input name= "a" type="texy" value="1" /><input type="submit" value="Submit 1" /></form>'
, '<form action="/submit" method="GET"><input name= "b" type="texy" value="2" /><input type="submit" value="Submit 2" /></form>'
, '<form action="http://127.0.0.2:80/submit" method="GET"><input name= "c" type="texy" value="3" /><input type="submit" value="Submit 3" /></form>'
].join(' | '), 'http://127.0.0.1:80/?proxyreq=', 'http://127.0.0.2:80'));
*/
function replaceData (htmlString, proxyServerAddress, outterServerAddress) {
return replacePath(htmlString, /(data=")([^"]+)(")/gi, proxyServerAddress, outterServerAddress)
}
/*
console.log(replaceData([
'<object data="video.mp4" />'
, '<object data="/video.mp4" />'
, '<object data="http://www.google.com/video.mp4" />'
].join(' | '), 'http://127.0.0.1:80/?proxyreq=', 'http://127.0.0.2:80'));
*/
function replaceXMLHttpRequest (htmlString, proxyServerAddress, outterServerAddress) {
return htmlString.replace(/<head>/gi, function () {
return '<head>' + [
'<script type="text/javascript">'
+ ';(function (open) {'
+ 'window.XMLHttpRequest.prototype.open = function (method, url, async) {'
+ 'var newUrl;'
+ 'if (url.indexOf("http") === 0) {'
+ 'newUrl = "' + proxyServerAddress + '" + window.encodeURIComponent(url);'
+ '} else if (url.indexOf("/") === 0) {'
+ 'newUrl = "' + proxyServerAddress + '" + window.encodeURIComponent("' + outterServerAddress + '" + url);'
+ '} else {'
+ 'newUrl = "' + proxyServerAddress + '" + window.encodeURIComponent("' + outterServerAddress + '" + "/" + url);'
+ '}'
+ 'open.call(this, method, newUrl, async);'
+ '};'
+ '})(window.XMLHttpRequest.prototype.open);'
+ '</script>'
].join('');
});
}
/*
console.log(replaceXMLHttpRequest([
'<!DOCTYPE html>'
+ '<html>'
+ '<head>'
+ '<link href="favicon.png" rel="icon" type="image/png" />'
+ '<link href="static/css/style1.css" rel="stylesheet" type="text/css" />'
+ '<link href="/static/css/style2.css" rel="stylesheet" type="text/css" />'
+ '<link href="http://127.0.0.2:80/static/css/style3.css" rel="stylesheet" type="text/css" />'
+ '<script src="static/js/script1.js"></script>'
+ '<script src="/static/js/script2.js"></script>'
+ '<script src="http://127.0.0.2:80/static/js/script3.js"></script>'
+ '<meta charset="utf-8" />'
+ '<title>Test page</title>'
+ '</head>'
].join('\n'), 'http://127.0.0.1:80/?proxyreq=', 'http://127.0.0.2:80'));
*/
module.exports = function replaceHTML (htmlString, proxyServerAddress, outterServerAddress) {
htmlString = replaceHref(htmlString, proxyServerAddress, outterServerAddress);
htmlString = replaceSrc(htmlString, proxyServerAddress, outterServerAddress);
htmlString = replaceAction(htmlString, proxyServerAddress, outterServerAddress);
htmlString = replaceData(htmlString, proxyServerAddress, outterServerAddress);
htmlString = replaceXMLHttpRequest(htmlString, proxyServerAddress, outterServerAddress);
return htmlString;
};
Файл replaceCSS.js
function replaceUrl (cssString, proxyServerAddress, outterServerAddress, rootPath) {
return cssString.replace(/url\([^\)]+\)/gi, function (match) {
match = match.replace(/url\(/gi, '');
match = match.replace(/\)/gi, '');
match = match.replace(/"/gi, '');
match = match.replace(/'/gi, '');
match = match.replace(/^\s+/, '');
match = match.replace(/\s+$/, '');
if (!(match.indexOf('/') === 0 || match.indexOf('http') === 0)) {
match = joinPaths(rootPath, match);
}
var newPath;
if (match.indexOf('http') === 0) {
newPath = proxyServerAddress + match;
} else if (match.indexOf('/') === 0) {
newPath = proxyServerAddress + outterServerAddress + match;
} else {
newPath = proxyServerAddress + outterServerAddress + '/' + match;
}
return 'url("' + newPath + '")';
});
}
function joinPaths (root, path) {
if (path.indexOf('../') === 0) {
if (root.indexOf('/') === root.lastIndexOf('/')) {
if (root[root.length - 1] === '/') {root = root.slice(0, root.length - 1);}
if (path[0] === '/') {path = path.slice(1);}
return root + '/' + path;
} else {
path = path.slice(3);
root = root.slice(0, root.lastIndexOf('/'));
return joinPaths(root, path);
}
} else {
if (root[root.length - 1] === '/') {root = root.slice(0, root.length - 1);}
if (path[0] === '/') {path = path.slice(1);}
return root + '/' + path;
}
}
/*
console.log(replaceUrl([
'body {background: url(image.png) repeat-x repeat-y;}'
, 'div {background: url(/image.png) repeat-x repeat-y;}'
, 'p {background: url(http://www.google.com/image.png) repeat-x repeat-y;}'
, 'body {background: url("image.png") repeat-x repeat-y;}'
, 'div {background: url("/image.png") repeat-x repeat-y;}'
, 'p {background: url("http://www.google.com/image.png") repeat-x repeat-y;}'
, '@import url(\'style2.css\');'
, '@import url("/style2.css");'
, '@import url("http://www.google.com/style2.css");'
].join(' | '), 'http://127.0.0.1:80/?proxyreq=', 'http://127.0.0.2:80'));
*/
module.exports = function replaceCSS (cssString, proxyServerAddress, outterServerAddress, rootPath) {
cssString = replaceUrl(cssString, proxyServerAddress, outterServerAddress, rootPath);
return cssString;
};
Файл replaceJavaScript.js
var querystring = require('querystring');
function replacePath (javascriptString, regexp, proxyServerAddress, outterServerAddress) {
return javascriptString.replace(regexp, function (match, $1, $2, $3, $4) {
var newPath;
if ($3.indexOf('http') === 0) {
newPath = proxyServerAddress + querystring.escape($3);
} else if ($3.indexOf('/') === 0) {
newPath = proxyServerAddress + querystring.escape(outterServerAddress + $3);
} else {
newPath = proxyServerAddress + querystring.escape(outterServerAddress + '/' + $3);
}
return $1 + $2 + newPath + $4;
});
}
function replaceVarPath (javascriptString, regexp, proxyServerAddress, outterServerAddress) {
return javascriptString.replace(regexp, function (match, $1, $2) {
return $1 + '"' + proxyServerAddress + querystring.escape(outterServerAddress) + '/" + ' + $2;
});
}
function replaceVarSrc (javascriptString, proxyServerAddress, outterServerAddress) {
return replaceVarPath(javascriptString, /(\.\s*src\s*=\s*)([a-zA-Z$_]+)/gi, proxyServerAddress, outterServerAddress);
}
/*
console.log(replaceVarSrc([
'img . src = someVar'
, 'img.src = someVar + "/path"'
].join(' | '), 'http://127.0.0.1:80/?proxyreq=', 'http://127.0.0.2:80'));
*/
function replaceSrc (javascriptString, proxyServerAddress, outterServerAddress) {
return replacePath(javascriptString, /(\.\s*src\s*=\s*)('|")([^'"]+)('|")/gi, proxyServerAddress, outterServerAddress);
}
/*
console.log(replaceSrc([
'img . src = \'path\''
, 'img.src = "/path"'
, 'img.src="http://www.google.com/path"'
].join(' | '), 'http://127.0.0.1:80/?proxyreq=', 'http://127.0.0.2:80'));
*/
function replaceHref (javascriptString, proxyServerAddress, outterServerAddress) {
return replacePath(javascriptString, /(\.\s*href\s*=\s*)('|")([^'"]+)('|")/gi, proxyServerAddress, outterServerAddress);
}
/*
console.log(replaceHref([
'location . href = \'path\''
, 'location.href = "/path"'
, 'location.href="http://www.google.com/path"'
, 'a . href = \'path\''
, 'a.href = "/path"'
, 'a.href="http://www.google.com/path"'
].join(' | '), 'http://127.0.0.1:80/?proxyreq=', 'http://127.0.0.2:80'));
*/
function replaceVarHref (javascriptString, proxyServerAddress, outterServerAddress) {
return replaceVarPath(javascriptString, /(\.\s*href\s*=\s*)([a-zA-Z$_]+)/gi, proxyServerAddress, outterServerAddress);
}
/*
console.log(replaceVarSrc([
'img . href = someVar'
, 'img.href = someVar + "/path"'
].join(' | '), 'http://127.0.0.1:80/?proxyreq=', 'http://127.0.0.2:80'));
*/
module.exports = function replaceJavaScript (javascriptString, proxyServerAddress, outterServerAddress) {
javascriptString = replaceSrc(javascriptString, proxyServerAddress, outterServerAddress);
javascriptString = replaceVarSrc(javascriptString, proxyServerAddress, outterServerAddress);
javascriptString = replaceHref(javascriptString, proxyServerAddress, outterServerAddress);
javascriptString = replaceVarHref(javascriptString, proxyServerAddress, outterServerAddress);
return javascriptString;
};
среда, 25 апреля 2018 г.
пятница, 6 апреля 2018 г.
Node.js Socket Client HTTP Request example
var net = require('net');
var clientSocket = new net.Socket();
clientSocket.on('connect', function () {
console.log('Connected to Google.');
});
clientSocket.on('data', function (data) {
console.log(data.toString());
});
clientSocket.on('end', function () {
console.log('Google sent all data.');
});
clientSocket.on('close', function () {
console.log('Connection closed.');
});
clientSocket.on('error', function (error) {
throw error;
});
clientSocket.connect(80, 'google.com', function (error) {
if (error) {throw error;}
});
clientSocket.write('GET /index.html HTTP/1.0'); // Передаем тип запроса GET или POST и какую страницу хотим загрузить - index.html
clientSocket.write('Accept-Encoding: gzip, compress');
// clientSocket.write('Host: 127.0.0.1');
// clientSocket.write('User-Agent: My programm');
// clientSocket.write('Accept-Language: en');
clientSocket.write(''); // Обязательно должна в конце отправлять пустая строка.
clientSocket.end();
var clientSocket = new net.Socket();
clientSocket.on('connect', function () {
console.log('Connected to Google.');
});
clientSocket.on('data', function (data) {
console.log(data.toString());
});
clientSocket.on('end', function () {
console.log('Google sent all data.');
});
clientSocket.on('close', function () {
console.log('Connection closed.');
});
clientSocket.on('error', function (error) {
throw error;
});
clientSocket.connect(80, 'google.com', function (error) {
if (error) {throw error;}
});
clientSocket.write('GET /index.html HTTP/1.0'); // Передаем тип запроса GET или POST и какую страницу хотим загрузить - index.html
clientSocket.write('Accept-Encoding: gzip, compress');
// clientSocket.write('Host: 127.0.0.1');
// clientSocket.write('User-Agent: My programm');
// clientSocket.write('Accept-Language: en');
clientSocket.write(''); // Обязательно должна в конце отправлять пустая строка.
clientSocket.end();
Подписаться на:
Сообщения (Atom)