CEF与代理
此文已由作者王荣涛授权网易云社区发布。
欢迎访问网易云社区,了解更多网易技术产品运营经验。
CEF(Chromium Embedded Framework)如今已经广泛被应用于客户端软件,网易内部就有网易云音乐、有道云笔记等重要产品在深度使用。有时候我们需要让CEF在加载页面的时候走代理,比如科学上网,本文就以C++版的CEF为例,对CEF如何实现代理浏览作下简单介绍。
Chromium的代理
众所周知,CEF和Google Chrome都基于开源的Chromium浏览器项目。
固定代理
在Chromium中,你可以在启动时加入
--proxy-server="myproxy:808"
或
--proxy-server="http://myproxy:808"
开关用以显式告诉它走myproxy这台主机上808端口的HTTP代理(如果装了SwitchyOmega之类的代理控制软件,这种方式将不一定会按预期工作)。除此之外,Chromium还支持SOCKS4
--proxy-server="socks4://myproxy:1080"
以及SOCKS5方式的代理:
--proxy-server="socks://myproxy:1080"--proxy-server="socks5://myproxy:1080"
以及按不同URL类型指定不同的代理方式:
--proxy-server="https=http://myproxy:808;http=socks://myproxy:1080"
除此之外,结合--proxy-server开关,还可以使用--proxy-bypass-list开关来讲某些指定站点或者IP排除在使用代理的名单之外,例如:
--proxy-server="myproxy:808" --proxy-bypass-list="127.0.0.1;*.netease.com"
PAC
PAC(Proxy auto-config)文件本质上是一个包含FindProxyForURL函数的JS脚本,浏览器根据这个函数的返回结果来决定某个URL执行何种代理方式,一个例子如下:
function FindProxyForURL(url, host) { if (isInNet(host, "10.240.0.0", "255.255.0.0")) return "DIRECT"; return "SOCKS myproxy:1080";
}
Chromium支持PAC文件,开关如下:
--proxy-pac-url=URL
其中URL是你存放PAC文件的地方。大家熟悉的GoAgent等翻墙利器就只带这个文件,有兴趣的不妨可以翻出来看看。
其他开关
强制不使用代理
--no-proxy-server
自动探测代理
--proxy-auto-detect
CEF全局代理
CEF当然也支持Chromium方式的代理,我们只要选择但不限于以下二者之一:
1、在CEF初始化的时候将以上开关作为参数传入CefInitialize、CefExecuteProcess等之中;
2、实现自己的CefApp派生类,然后重载OnBeforeCommandLineProcessing方法:
class MyCefApp final : public CefApp {public: void OnBeforeCommandLineProcessing( const CefString& process_type,
CefRefPtr<CefCommandLine> command_line) { if (process_type.empty()) {
command_line->AppendSwitch("--proxy-server=\"myproxy:808\"");
}
}private:
IMPLEMENT_REFCOUNTING(MyCefApp)
};
但是以上方式都是一次性的,也就是你只有一次机会对命令行进行修改,之后所有请求都遵循这种代理方式,这种方式我们暂且称为全局代理。
全局代理的方式有很多局限性,比如有时候我只想对某个页面的内容使用代理,这种就完全不适用了,因为第一我们需要重启CEF,第二一旦设置了代理将会影响所有页面。
CEF任意请求代理
幸运的是,最新版(准确说是2015年10月7日之后)的CEF加入另一种更加灵活的方式,即任意请求代理。
这种方式的原理是在进行每次请求的时候CEF给应用一次机会让应用可以修改请求相关的参数。要实现这一点,我们需要自己的CefRequestHandler,然后重载OnBeforeBrowse和GetAuthCredentials(不一定需要)两个方法,定义如下:
class MyRequestHandler final : public CefRequestHandler {public:
virtual bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request, bool is_redirect); // 可选,根据是否需要认证
virtual bool GetAuthCredentials(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame, bool isProxy, const CefString& host, int port, const CefString& realm, const CefString& scheme,
CefRefPtr<CefAuthCallback> callback);private:
IMPLEMENT_REFCOUNTING(MyRequestHandler);
};
具体实现示例:
bool MyRequestHandler::OnBeforeBrowse(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
bool is_redirect) {
CefRefPtr<CefRequestContext> context =
browser->GetHost()->GetRequestContext(); CefString error;
CefRefPtr<CefDictionaryValue> dict = CefDictionaryValue::Create();
dict->SetString("mode", "fixed_servers");
dict->SetString("server", "myproxy:808");
CefRefPtr<CefValue> value = CefValue::Create();
value->SetDictionary(dict); context->SetPreference("proxy", value, error); return false;
}
其中mode可以取值以下任一:
fixed_servers
pac_script
auto_detect
system
direct
而当mode为fixed_servers时需要指定server参数,当mode为pac_script时需要指定pac_url参数。
如果代理需要认证,那么需要同时实现:
bool MyRequestHandler::GetAuthCredentials(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame, bool isProxy, const CefString& host, int port, const CefString& realm, const CefString& scheme,
CefRefPtr<CefAuthCallback> callback) { if (isProxy) {
callback->Continue("myuser", "mypass"); return true;
} return false;
}
题外话
CefRequestHandler::OnBeforeBrowse中可以干的还有很多,比如控制拼写检查等,大家可以好好去发掘。
网易云免费体验馆,0成本体验20+款云产品!
更多网易技术、产品、运营经验分享请点击。
相关文章:
【推荐】 微服务化的基石——持续集成
【推荐】 一招搞定短信验证码服务不稳定
CEF与代理的更多相关文章
- 使用CEF(二)— 基于VS2019编写一个简单CEF样例
使用CEF(二)- 基于VS2019编写一个简单CEF样例 在这一节中,本人将会在Windows下使用VS2019创建一个空白的C++Windows Desktop Application项目,逐步进 ...
- KVM halt-polling机制分析
本文由作者朱益军授权网易云社区发布. 简介 在实际业务中,guest执行HLT指令是导致虚拟化overhead的一个重要原因.如[1]. KVM halt polling特性就是为了解决这一个问题被引 ...
- 使用C#在CEF中拦截并响应请求
一.前言 忙里偷闲,研究了一下如何在CEF中拦截请求,并作出响应.这个功能对某些需要修改服务器响应的需求来说必不可少,可以直接读取本地文件作为响应内容. C#的CEF封装项目有很多,我使用的是Chro ...
- Cef 架构
cef支持各种语言和多种操作系统.在设计的时候充分考虑了性能和易用性.cef核心功能提供了c和c++的接口.cef提供了和主程序之间的通信能力(利用 custom plugins, protocols ...
- 初识CEF
介绍 CEF全称Chromium Embedded Framework,是一个基于Google Chromium 的开源项目.Google Chromium项目主要是为Google Chrome应用开 ...
- 刨根究底字符编码之十——Unicode字符集的字符编码方式CEF
Unicode字符集的字符编码方式CEF 一.字符编码方式CEF的选择 1. 由于Unicode字符集非常大,有些字符的编号(码点值)需要两个或两个以上字节来表示,而要对这样的编号进行编码,也必须使用 ...
- CEF解决加载慢问题
转载:http://blog.csdn.net/weolar/article/details/51994895 CEF加载慢的时候,加上以下代码,通过命令行的方式: CefRefPtr<CefC ...
- webrower + CEF
理解WebKit和Chromium: Content API和CEF3 标签: apiAPIAPibrowserchromeChromehtml5HTML5Html5web ...
- CEF General Usage(CEF3预览)
CEF General Usage(CEF3预览) 介绍 CEF全称Chromium Embedded Framework,是一个基于Google Chromium 的开源项目.Google Chro ...
随机推荐
- HTML入门与基础 —— 标签《一》
一.标签概述 1.HTML(英文Hyper Text Markup Language的缩写)中文译为“超文本标签语言”,主要是通过HTML标签对网页中的文本.图片.声音等内容进行描述. 2.标签分为嵌 ...
- ACM_X章求和(数学)
X章求和 Time Limit: 2000/1000ms (Java/Others) Problem Description: X章最喜欢求和了,他一看到什么鬼就什么鬼都加起来.one day,他得到 ...
- req.getParameter()无法获取参数(附前端json序列化)
问题:前端用Ajax的post方式想servlet传递参数,servlet的getParameter()方法无法获取参数. 前端代码: $.ajax({ url: '/TestWeb/addBook' ...
- 【经验总结】关于使用某些第三方插件库元素设置display:none后重新show不显示的问题;(display、opacity、宽高0的使用场景)
display:none 直接取消元素所占用的位置(但是元素还是存在的),后面元素看他就相当于不存在了: opacity:0 隐藏,但是其依旧占用位置: height.width:0 和displa ...
- Android 使用GridView+仿微信图片上传功能(附源代码)
由于工作要求最近在使用GridView完成图片的批量上传功能,我的例子当中包含仿微信图片上传.拍照.本地选择.相片裁剪等功能,如果有需要的朋友可以看一下,希望我的实际经验能对您有所帮助. 直接上图,下 ...
- 【HEVC帧间预测论文】P1.5 Fast Coding Unit Size Selection for HEVC based on Bayesian Decision Rule
Fast Coding Unit Size Selection for HEVC based on Bayesian Decision Rule <HEVC标准介绍.HEVC帧间预测论文笔记&g ...
- 【C++】双边滤波器(bilateral filter)
Bilateral Filtering for Gray and Color Images 双边滤波器:保留边界的平滑滤波器. 在局部上,就是在灰度值差异不大的区域平滑,在灰度值差异比较大的边界地区保 ...
- vue :class 可以接收 字符串 数组 和 对象 对象里面的key值 根据true或false 显示不显示
vue :class 可以接收 字符串 数组 和 对象 对象里面的key值 根据true或false 显示不显示 https://cn.vuejs.org/v2/guide/class-and-sty ...
- while循环(break、continue)
while循环 流程:判断条件是否为真,如果条件为真,执行代码块,然后再次判断条件是否为真,如果为真,执行代码块,直到条件判断为假,结束循环 格式 while 条件: 代码块(循环体) else:- ...
- Asp.Net Core 入门(三) —— 自定义中间件
上一篇我们讲了Startup文件,其中着重介绍了中间件,现在我们就来自定义我们自己的中间件吧. 中间件通常封装在一个类中,并使用扩展方法进行暴露.它需要拥有一个类型为RequestDelegate的成 ...