用node-http-proxy搭建代理
程序员三大必备网站是:Google、Github、StackOverflow。如果你还在用Baidu搜索技术文章的话,我想说的是,少年你已经被鄙视很多年了,赶紧换成谷歌吧,不要再被鄙视了!Github、StackOverflow在国内能够正常访问,但是Google由于众所周知的原因,国内无法访问,所以我们需要翻墙访问Google。个人觉得shadowsocks的是目前最好用的代理,没有之一!shadowsocks有多牛?前段时间shadowsocks的作者被约谈了,还被要求删除在Github上的源码,你说有多牛!可以自己在vps上利用shadowsocks搭建自己的专属代理,如果你懒的话,也可以直接去买个shadowsocks账号,网上卖家多的是。后面我会写相关的文章介绍如何在vps上搭建服务器,敬请关注。今天先介绍一下用node-http-proxy搭建谷歌代理,小试牛刀一下。
node-http-proxy是一个用于Node.js的HTTP可编程代理库,支持 websockets。它是适用于实现例如代理服务器和负载均衡这样的组件。node-http-proxy使用起来很简单,下面简单介绍一下。
核心概念
通过createProxyServer函数创建代理,同时你也可选的传入options对象
var httpProxy = require('http-proxy');
var proxy = httpProxy.createProxyServer(options);
createProxyServer函数返回的proxy对象包含四个方法
- web
req, res, [options]
用来代理http(s)请求 - ws
req, socket, head, [options]
用来代理WS(S)请求 - listen
port
该函数把对象包装成webserver,方便使用 - close
[callback]
该函数关闭内部的webserver并且停止监听给定的端口
然后可以如下调用函数代理请求
http.createServer(function(req, res) {
proxy.web(req, res, { target: 'http://mytarget.com:8080' });
});
错误处理可以通过监听error事件
proxy.on('error', function(e) {
...
});
或者使用回调API
proxy.web(req, res, { target: 'http://mytarget.com:8080' }, function(e) { ... });
Use Cases
下面的例子显示如何用你自己的http服务器代理请求,你也可以加入自己的业务逻辑处理请求
var http = require('http'),
httpProxy = require('http-proxy'); //
// Create a proxy server with custom application logic
//
var proxy = httpProxy.createProxyServer({}); //
// Create your custom server and just call `proxy.web()` to proxy
// a web request to the target passed in the options
// also you can use `proxy.ws()` to proxy a websockets request
//
var server = http.createServer(function(req, res) {
// You can define here your custom logic to handle the request
// and then proxy the request.
proxy.web(req, res, { target: 'http://127.0.0.1:5060' });
}); console.log("listening on port 5050")
server.listen(5050);
更多例子请查看官方文档
Options
httpProxy.createProxyServer
支持下列options:
- target: url字符串
- forward: url字符串
- agent: 传给http(s).request的对象
- ssl: 密钥,HTTPS使用
- ws: true/false, 是否代理websockets
- xfwd: true/false, 是否加上x-forward头字段
- secure: true/false, 是否校验ssl证书
- toProxy: 传递绝对URL作为
path
- prependPath: true/false, 默认值为true,是否在proxy path前面加上target的path
- ignorePath: true/false, 默认值为false,是否忽略传入的请求的proxy path
- localAddress: 本地地址
- changeOrigin: true/false, 默认值为false, 是否更改原始的host头字段为target URL
- auth: 基本身份认证,比如:‘用户名:密码’来计算Authorization header
- hostRewrite: 重写重定向(301/302/307/308)的location hostname
- autoRewrite: 是否自动重写重定向(301/302/307/308)的location host/port,默认值为false
- protocolRewrite: 重写重定向(301/302/307/308)的location的协议,http或者https,默认值为null
谷歌代理
'use strict'; var http = require('http');
var https = require('https');
var httpProxy = require('http-proxy');
var url = require('url'); var PROXY_PORT = 8000;
var proxy, server; // Create a proxy server with custom application logic
proxy = httpProxy.createProxy({}); proxy.on('error', function (err) {
console.log('ERROR');
console.log(err);
}); server = http.createServer(function (req, res) {
//var finalUrl = req.url,
var finalUrl = 'https://www.google.com';
var finalAgent = null;
var parsedUrl = url.parse(finalUrl); if (parsedUrl.protocol === 'https:') {
finalAgent = https.globalAgent;
} else {
finalAgent = http.globalAgent;
} proxy.web(req, res, {
target: finalUrl,
agent: finalAgent,
headers: { host: parsedUrl.hostname },
prependPath: false,
xfwd : true,
hostRewrite: finalUrl.host,
protocolRewrite: parsedUrl.protocol
});
}); console.log('listening on port ' + PROXY_PORT);
server.listen(PROXY_PORT);
你没看错,就是这么点代码就能代理谷歌了,前提是你要有个墙外的vps哈!首先设置浏览器的http代理为你的vps,然后再vps上运行上面的代理程序,最后在浏览器中访问www.google.com,然后就是见证奇迹的时候了。有些小伙伴可能迫不及待的拿去试了试,结果发现博主骗人,根本不能代理谷歌。别急,这是因为node-http-proxy有一个小小的bug,不能怪博主,博主也是受害者之一。博主开始也卡在这里很久,最后去阅读源代码才发现问题所在!在node-http-proxy的web-outgoing.js里有个setRedirectHostRewrite函数,该函数的功能就是重定向时重写header中location的host地址,函数代码如下:
function setRedirectHostRewrite(req, res, proxyRes, options) {
if ((options.hostRewrite || options.autoRewrite || options.protocolRewrite)
&& proxyRes.headers['location']
&& redirectRegex.test(proxyRes.statusCode)) {
var target = url.parse(options.target);
var u = url.parse(proxyRes.headers['location']); // make sure the redirected host matches the target host before rewriting
if (target.host != u.host) {
return;
} if (options.hostRewrite) {
u.host = options.hostRewrite;
} else if (options.autoRewrite) {
u.host = req.headers['host'];
}
if (options.protocolRewrite) {
u.protocol = options.protocolRewrite;
} proxyRes.headers['location'] = u.format();
}
}
问题出在以下代码:
// make sure the redirected host matches the target host before rewriting
if (target.host != u.host) {
return;
}
作者的意图是确保重定向的host跟target的host的匹配,不匹配就直接返回。代理谷歌时就会发生不匹配的情况直接返回了。
比如,博主来自中国,当我curl www.google.com
时会重定向到www.google.com.hk:
[root@iZu1fmzgm3iZ ~]# curl www.google.com
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="http://www.google.com.hk/url?sa=p&hl=zh-CN&pref=hkredirect&pval=yes&q=http://www.google.com.hk/%3Fgws_rd%3Dcr&ust=1448378903186576&usg=AFQjCNHtMfRNndvgHHMAzipRzC9NpycwGw">here</A>.
</BODY></HTML>
如果你来自日本,当你curl www.google.com
时会重定向到www.google.co.jp:
[ec2-user@ip-172-31-27-165 ~]$ curl www.google.com
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="http://www.google.co.jp/?gfe_rd=cr&ei=toJUVubpIcem8wfGirqQDw">here</A>.
</BODY></HTML>
因为重定向的host跟target的host不匹配,程序直接返回,hostRewrite无效,所以我们应该去掉以下代码:
// make sure the redirected host matches the target host before rewriting
if (target.host != u.host) {
return;
}
当我们注释掉以上代码,重新运行程序,发现已经可以上谷歌了,是不是很神奇!
用node-http-proxy搭建代理的更多相关文章
- 使用node.js实现反向代理
一. 反向代理的应用场景 1. 静态资源与动态资源分离 e.g. 图片服务器 2. AJAX跨域访问 3. 搭建统一服务网关接口 二. 使用node.js实现反向代理 1. 安装http-proxy模 ...
- paip.最好的脚本语言node js 环境搭建连接mysql
paip.最好的脚本语言node js 环境搭建连接mysql #====下载node...走十一个exe..容易的.. 1 #0----Hello world .js 2 #---------模 ...
- 【Python3爬虫】教你怎么利用免费代理搭建代理池
一.写在前面 有时候你的爬虫刚开始的时候可以正常运行,能够正常的爬取数据,但是过了一会,却出现了一个“403 Forbidden",或者是”您的IP访问频率太高“这样的提示,这就意味着你的I ...
- Node.js环境搭建&&npm安装
Node.js环境搭建 什么使Node.js呢?我们知道JavaScript开始作为客户端语言,但早已在浏览器端一统江湖,这时,野心越来越大,它就想向服务器端拓展了,于是Node.js就是这样的,我们 ...
- 进程线程协程补充、docker-compose一键部署项目、搭建代理池、requests超时设置、认证设置、异常处理、上传文件
今日内容概要 补充:进程,线程,协程 docker-compose一键部署演示 搭建代理池 requests超时设置 requests认证设置 requests异常处理 requests上传文件 内容 ...
- nodejs,node原生服务器搭建实例
nodejs,node原生服务器搭建实例
- 用Node.JS+MongoDB搭建个人博客(页面模板)(五)(结束)
<差不多先生> 我是差不多先生,我的差不多是天生.也代表我很天真,也代表我是个闲人.这差不多的人生,总是见缝插针. 求学的道路上总是孤独的,即使别人不理解我,认为我是奇葩!但没关系,我会坚 ...
- Centos 7 上使用nginx为Node.js配置反向代理时错误:(13: Permission denied) while connecting to upstream
错误来源:Centos 7 上使用nginx为Node.js配置反向代理时产生(13: Permission denied) while connecting to upstream的错误 nginx ...
- 设计模式之Proxy(代理)(转)
理解并使用设计模式,能够培养我们良好的面向对象编程习惯,同时在实际应用中,可以如鱼得水,享受游刃有余的乐趣. Proxy是比较有用途的一种模式,而且变种较多,应用场合覆盖从小结构到整个系统的大结构,P ...
- Node.js环境搭建和学习(windwos环境)
Node.js环境搭建和学习 一.环境搭建 1.下载安装文件 下载地址http://nodejs-org.qiniudn.com/下载Node.js环境安装包,根据操作系统下载对应的安装包 下载地址 ...
随机推荐
- python中输入多个数字(代码实现)
不多说,直接上代码: list1 = [] #定义一个空列表 str1 = input("请输入数值,用空格隔开:") # list2 = str1.split(" &q ...
- JavaScript类型和语法
JavaScript类型和语法 一.类型 1.内置类型(null.undefined.boolean.number.string.object.symbol(es6中新增))(除对象之外,其它统称为基 ...
- raid 10
首先先创建五个新的硬盘,步骤参照 raid 5 建好硬盘以后开启虚拟机 打开终端,更改好主机名以后,重新打开终端 输入命令:fdisk -l 查看有没有加入进来 我们发现已经加入进来 然后开始分 ...
- 04、python的基础-->列表跟元组
一.列表list 1.列表的新增元素(三种方法) >>>第1种方法(append 增加到最后): li = ['Peter','Henrry','Wode','鸭子','xiaoxi ...
- javascript常用经典算法实例详解
javascript常用经典算法实例详解 这篇文章主要介绍了javascript常用算法,结合实例形式较为详细的分析总结了JavaScript中常见的各种排序算法以及堆.栈.链表等数据结构的相关实现与 ...
- Dubbo 微服务系列(03)服务注册
Dubbo 微服务系列(03)服务注册 [TOC] Spring Cloud Alibaba 系列目录 - Dubbo 篇 1. 背景介绍 图1 Dubbo经典架构图 注:本图来源 Dubbo官方架构 ...
- 利用docker搭建WordPress
步骤一 创建mysql的容器 步骤二 创建wordpress的容器并链接mysql容器的数据库 创建mysql的容器 docker run -d --name mysql -v mysql-data: ...
- 跨域篇--JSONP原理
一篇文章让你明白 jsonp原理详解 什么是JSONP? 先说说JSONP是怎么产生的: 其实网上关于JSONP的讲解有很多,但却千篇一律,而且云里雾里,对于很多刚接触的人来讲理解起来有些困难,着用自 ...
- MySQL字符集不一致导致查询SQL性能问题
今天做了一个MySQL数据库中的SQL优化. 结论是关联字段字符集不同,导致索引不可用. 查询的SQL如下: select `Alias`.`Grade`, `Alias`.`id`, `Alias` ...
- ionic node-sass安装或编译失败:MSBUILD : error MSB3428: 未能加载 Visual C++ 组件“VCBuild.exe”
错误原因:缺少windows构建插件 解决方法:npm install --global --production windows-build-tools (如果目录在C盘下,需要管理员权限运行,全 ...