我正在尝试创建一个代理服务器,以便将HTTP GET
请求从客户端传递到第三方网站(比如google)。我的代理只需要将传入的请求镜像到目标站点上的相应路径,所以如果我的客户端请求的URL是:
127.0.0.1/images/srpr/logo11w.png
应提供以下资源:
http://www.google.com/images/srpr/logo11w.png
这是我想出的:
http.createServer(onRequest).listen(80);
function onRequest (client_req, client_res) {
client_req.addListener("end", function() {
var options = {
hostname: 'www.google.com',
port: 80,
path: client_req.url,
method: client_req.method
headers: client_req.headers
};
var req=http.request(options, function(res) {
var body;
res.on('data', function (chunk) {
body += chunk;
});
res.on('end', function () {
client_res.writeHead(res.statusCode, res.headers);
client_res.end(body);
});
});
req.end();
});
}
它适用于html页面,但对于其他类型的文件,它只返回一个空白页面或来自目标站点的一些错误消息(在不同的站点中有所不同)。
答案 0 :(得分:78)
我认为处理从第三方服务器收到的响应不是一个好主意。这只会增加代理服务器的内存占用量。此外,这也是您的代码无法正常工作的原因。
而是尝试将响应传递给客户端。请考虑以下代码段:
var http = require('http');
http.createServer(onRequest).listen(3000);
function onRequest(client_req, client_res) {
console.log('serve: ' + client_req.url);
var options = {
hostname: 'www.google.com',
port: 80,
path: client_req.url,
method: client_req.method,
headers: client_req.headers
};
var proxy = http.request(options, function (res) {
client_res.writeHead(res.statusCode, res.headers)
res.pipe(client_res, {
end: true
});
});
client_req.pipe(proxy, {
end: true
});
}
答案 1 :(得分:18)
这是使用来自nodejitsu的node-http-proxy
的实现。
var http = require('http');
var httpProxy = require('http-proxy');
var proxy = httpProxy.createProxyServer({});
http.createServer(function(req, res) {
proxy.web(req, res, { target: 'http://www.google.com' });
}).listen(3000);
答案 2 :(得分:9)
这是使用request处理重定向的代理服务器。通过点击代理网址http://domain.com:3000/?url=[your_url]
来使用它var http = require('http');
var url = require('url');
var request = require('request');
http.createServer(onRequest).listen(3000);
function onRequest(req, res) {
var queryData = url.parse(req.url, true).query;
if (queryData.url) {
request({
url: queryData.url
}).on('error', function(e) {
res.end(e);
}).pipe(res);
}
else {
res.end("no url found");
}
}
答案 3 :(得分:4)
您的代码不适用于二进制文件,因为它们无法转换为数据事件处理程序中的字符串。如果您需要操作二进制文件,则需要使用buffer。对不起,我没有使用缓冲区的示例,因为在我的情况下我需要操作HTML文件。我只是检查内容类型,然后根据需要更新文本/ html文件:
app.get('/*', function(clientRequest, clientResponse) {
var options = {
hostname: 'google.com',
port: 80,
path: clientRequest.url,
method: 'GET'
};
var googleRequest = http.request(options, function(googleResponse) {
var body = '';
if (String(googleResponse.headers['content-type']).indexOf('text/html') !== -1) {
googleResponse.on('data', function(chunk) {
body += chunk;
});
googleResponse.on('end', function() {
// Make changes to HTML files when they're done being read.
body = body.replace(/google.com/gi, host + ':' + port);
body = body.replace(
/<\/body>/,
'<script src="http://localhost:3000/new-script.js" type="text/javascript"></script></body>'
);
clientResponse.writeHead(googleResponse.statusCode, googleResponse.headers);
clientResponse.end(body);
});
}
else {
googleResponse.pipe(clientResponse, {
end: true
});
}
});
googleRequest.end();
});
答案 4 :(得分:3)
以下是Mike回答的一个更优化的版本,它可以正确获取网站的Content-Type,支持POST和GET请求,并使用您的浏览器User-Agent,以便网站可以将您的代理识别为浏览器。您只需更改url =
即可设置URL,它将自动设置HTTP和HTTPS内容,而无需手动进行操作。
var express = require('express')
var app = express()
var https = require('https');
var http = require('http');
const { response } = require('express');
app.use('/', function(clientRequest, clientResponse) {
var url;
url = 'https://www.google.com'
var parsedHost = url.split('/').splice(2).splice(0, 1).join('/')
var parsedPort;
var parsedSSL;
if (url.startsWith('https://')) {
parsedPort = 443
parsedSSL = https
} else if (url.startsWith('http://')) {
parsedPort = 80
parsedSSL = http
}
var options = {
hostname: parsedHost,
port: parsedPort,
path: clientRequest.url,
method: clientRequest.method,
headers: {
'User-Agent': clientRequest.headers['user-agent']
}
};
var serverRequest = parsedSSL.request(options, function(serverResponse) {
var body = '';
if (String(serverResponse.headers['content-type']).indexOf('text/html') !== -1) {
serverResponse.on('data', function(chunk) {
body += chunk;
});
serverResponse.on('end', function() {
// Make changes to HTML files when they're done being read.
body = body.replace(`example`, `Cat!` );
clientResponse.writeHead(serverResponse.statusCode, serverResponse.headers);
clientResponse.end(body);
});
}
else {
serverResponse.pipe(clientResponse, {
end: true
});
clientResponse.contentType(serverResponse.headers['content-type'])
}
});
serverRequest.end();
});
app.listen(3000)
console.log('Running on 0.0.0.0:3000')
答案 5 :(得分:1)
超级简单易读,以下是如何使用Node.js(在 v8.1.0 上测试)为本地HTTP服务器创建本地代理服务器。我发现它对集成测试特别有用,所以这是我的共享:
/**
* Once this is running open your browser and hit http://localhost
* You'll see that the request hits the proxy and you get the HTML back
*/
'use strict';
const net = require('net');
const http = require('http');
const PROXY_PORT = 80;
const HTTP_SERVER_PORT = 8080;
let proxy = net.createServer(socket => {
socket.on('data', message => {
console.log('---PROXY- got message', message.toString());
let serviceSocket = new net.Socket();
serviceSocket.connect(HTTP_SERVER_PORT, 'localhost', () => {
console.log('---PROXY- Sending message to server');
serviceSocket.write(message);
});
serviceSocket.on('data', data => {
console.log('---PROXY- Receiving message from server', data.toString();
socket.write(data);
});
});
});
let httpServer = http.createServer((req, res) => {
switch (req.url) {
case '/':
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('<html><body><p>Ciao!</p></body></html>');
break;
default:
res.writeHead(404, {'Content-Type': 'text/plain'});
res.end('404 Not Found');
}
});
proxy.listen(PROXY_PORT);
httpServer.listen(HTTP_SERVER_PORT);
https://gist.github.com/fracasula/d15ae925835c636a5672311ef584b999
答案 6 :(得分:0)
我juste在nodejs中编写了一个代理,它通过可选的消息解码来处理HTTPS。 此代理还可以添加proxy-authentification标头以通过公司代理。您需要提供url作为参数来查找proxy.pac文件,以便配置公司代理的使用。
答案 7 :(得分:0)
这是我制作的:
var http = require("http")
var Unblocker = require("unblocker")
var unblocker = Unblocker({})
http.createServer(function(req,res){
unblocker(req,res,function(err){
var headers = {"content-type": "text/html"}
if(err){
res.writeHead(500, headers)
return res.end(err.stack || err)
}
if(req.url == "/"){
res.writeHead(200, headers)
return res.end(
`
<title>Seventh Grade by Gary Soto</title>
<embed src="https://www.cforks.org/Downloads/7.pdf" width="1500" height="1500"/>
`
)
}else{
res.writeHead(404, headers)
return res.end("ERROR 404: File Not Found.");
}
})
})
.listen(8080)