- 1.网络层
- 1.1 自定义请求
- 1.2独立于浏览器的请求
- 2.请求处理
- 2.1 通用资源管理器
- 2.2 方案处理句柄
- 2.3 请求拦截
- 2.4 响应过滤
- 2.5 其他回调
- 3.代理解析
- 4.作者答疑
默认情况下,CEF3 中的网络请求将以对主机应用程序透明的方式处理。对于希望与网络层建立更密切关系的应用程序,CEF3 公开了一系列与网络相关的功能。与网络相关的回调可能发生在不同的线程上,因此请务必注意文档并正确保护您的数据成员。
1.1 自定义请求在浏览器框架中加载 URL 的最简单方法是通过 CefFrame::LoadURL() 方法。
browser->GetMainFrame()->LoadURL(some_url);
希望发送包含自定义请求标头或上传数据的更复杂请求的应用程序可以使用 CefFrame::LoadRequest() 方法。此方法接受CefRequest对象作为单个参数。
// Create a CefRequest object.
CefRefPtr request = CefRequest::Create();
// Set the request URL.
request->SetURL(some_url);
// Set the request method. Supported methods include GET, POST, HEAD, DELETE and PUT.
request->SetMethod(“POST”);
// Optionally specify custom headers.
CefRequest::HeaderMap headerMap;
headerMap.insert(std::make_pair("X-My-Header", "My Header Value"));
request->SetHeaderMap(headerMap);
// Optionally specify upload content.
// The default “Content-Type” header value is "application/x-www-form-urlencoded".
// Set “Content-Type” via the HeaderMap if a different value is desired.
const std::string& upload_data = “arg1=val1&arg2=val2”;
CefRefPtr postData = CefPostData::Create();
CefRefPtr element = CefPostDataElement::Create();
element->SetToBytes(upload_data.size(), upload_data.c_str());
postData->AddElement(element);
request->SetPostData(postData);
1.2独立于浏览器的请求
应用程序可以通过CefURLRequest类发送与特定浏览器无关的网络请求。实现CefURLRequestClient接口来处理结果响应。CefURLRequest 可以在浏览器和渲染进程中使用。
class MyRequestClient : public CefURLRequestClient
{
public:
MyRequestClient()
: upload_total_(0),
download_total_(0) {}
void OnRequestComplete(CefRefPtr request) OVERRIDE
{
CefURLRequest::Status status = request->GetRequestStatus();
CefURLRequest::ErrorCode error_code = request->GetRequestError();
CefRefPtr response = request->GetResponse();
// Do something with the response...
}
void OnUploadProgress(CefRefPtr request,
int64 current,
int64 total) OVERRIDE
{
upload_total_ = total;
}
void OnDownloadProgress(CefRefPtr request,
int64 current,
int64 total) OVERRIDE
{
download_total_ = total;
}
void OnDownloadData(CefRefPtr request,
const void *data,
size_t data_length) OVERRIDE
{
download_data_ += std::string(static_cast(data), data_length);
}
bool GetAuthCredentials(bool isProxy,
const CefString &host,
int port,
const CefString &realm,
const CefString &scheme,
CefRefPtr callback) OVERRIDE
{
return false; // Not handled.
}
private:
int64 upload_total_;
int64 download_total_;
std::string download_data_;
private:
IMPLEMENT_REFCOUNTING(MyRequestClient);
};
发送请求:
// Set up the CefRequest object.
CefRefPtr request = CefRequest::Create();
// Populate |request| as shown above...
// Create the client instance.
CefRefPtr client = new MyRequestClient();
// Start the request. MyRequestClient callbacks will be executed asynchronously.
CefRefPtr url_request = CefURLRequest::Create(request, client.get(), nullptr);
// To cancel the request: url_request->Cancel();
使用 CefURLRequest 发出的请求还可以通过 CefRequest::SetFlags() 方法指定自定义行为。支持的位标志包括:
- UR_FLAG_SKIP_CACHE如果设置,则在处理请求时将跳过缓存。
- UR_FLAG_ALLOW_CACHED_CREDENTIALS如果设置 cookie 可以与请求一起发送并从响应中保存。还必须设置 UR_FLAG_ALLOW_CACHED_CREDENTIALS。
- UR_FLAG_REPORT_UPLOAD_PROGRESS如果设置了当请求有正文时将生成上传进度事件。
- UR_FLAG_NO_DOWNLOAD_DATA如果设置 CefURLRequestClient::OnDownloadData 方法将不会被调用。
- UR_FLAG_NO_RETRY_ON_5XX如果设置 5XX 重定向错误将传播到观察者而不是自动重试。这目前仅适用于源自浏览器进程的请求。
例如,跳过缓存而不报告下载数据:
request->SetFlags(UR_FLAG_SKIP_CACHE | UR_FLAG_NO_DOWNLOAD_DATA);
2.请求处理
CEF3 支持两种处理应用程序内部网络请求的方法。方案处理程序方法允许为针对特定来源(方案 + 域)的请求注册处理程序。请求拦截方法允许应用程序自行处理任意请求。使用 HTTP 方案而不是自定义方案来避免一系列潜在问题。 如果您选择使用自定义方案(除“HTTP”、“HTTPS”等之外的任何方案),您必须向 CEF 注册它,以便它按预期运行。如果您希望自定义方案的行为类似于 HTTP(支持 POST 请求并强制执行HTTP 访问控制 (CORS)限制),则应将其注册为“标准”方案。如果您计划对其他方案执行跨域请求或通过 XMLHttpRequest 将 POST 请求发送到您的方案处理程序,那么您应该使用 HTTP 方案而不是自定义方案以避免潜在问题。如果您希望使用自定义方案,则通过必须在所有进程中实现的 CefApp::OnRegisterCustomSchemes() 回调注册属性。
void MyApp::OnRegisterCustomSchemes(CefRefPtr registrar)
{
// Register "client" as a standard scheme.
registrar->AddCustomScheme("client", true, ...);
}
2.1 通用资源管理器
CEF 提供了一种用于管理来自一个或多个数据源的资源请求的通用实现。此用户为不同的数据源(例如磁盘上的目录、zip 存档或自定义实现)注册处理程序,然后由管理器处理请求。应用程序通过向路由器传递来自标准 CEF C++ 回调(OnBeforeResourceLoad、GetResourceHandler)的数据与路由器交互。有关演示 CefResourceManager 用法的独立示例应用程序,请参阅resource_manager 示例。有关完整的使用文档,请参阅include/wrapper/cef_resource_manager.h。
2.2 方案处理句柄方案处理句柄通过 CefRegisterSchemeHandlerFactory() 函数注册。调用这个函数的一个好地方是 CefBrowserProcessHandler::OnContextInitialized()。例如,您可以为“client://myapp/”请求注册一个处理句柄:
CefRegisterSchemeHandlerFactory("client", “myapp”, new MySchemeHandlerFactory());
处理程序可以与内置方案(HTTP、HTTPS 等)和自定义方案一起使用。使用内置方案时,请选择您的应用程序独有的域名(如“myapp”或“internal”)。实现CefSchemeHandlerFactory和CefResourceHandler类来处理请求并提供响应数据。如果使用自定义方案,请不要忘记实现上述 CefApp::OnRegisterCustomSchemes 方法。有关演示 CefSchemeHandlerFactory 用法的独立示例应用程序,请参阅scheme_handler 示例。有关完整的使用文档,请参阅include/cef_scheme.h。
如果在请求时响应数据是已知的,CefStreamResourceHandler类提供了一个方便的 CefResourceHandler 的默认实现。
// CefStreamResourceHandler is part of the libcef_dll_wrapper project.
#include “include/wrapper/cef_stream_resource_handler.h”
const std::string &html_content = “Hello! ”;
// Create a stream reader for |html_content|.
CefRefPtr stream =
CefStreamReader::CreateForData(
static_cast(const_cast(html_content.c_str())),
html_content.size());
// Constructor for HTTP status code 200 and no custom response headers.
// There’s also a version of the constructor for custom status code and response headers.
return new CefStreamResourceHandler("text/html", stream);
2.3 请求拦截
CefRequestHandler::GetResourceHandler() 方法支持拦截任意请求。它使用与方案处理程序方法相同的 CefResourceHandler 类。如果使用自定义方案,请不要忘记实现上述 CefApp::OnRegisterCustomSchemes 方法。
CefRefPtr MyHandler::GetResourceHandler(
CefRefPtr browser,
CefRefPtr frame,
CefRefPtr request)
{
// Evaluate |request| to determine proper handling...
if (...)
return new MyResourceHandler();
// Return NULL for default handling of the request.
return NULL;
}
2.4 响应过滤
CefRequestHandler::GetResourceResponseFilter() 方法支持过滤请求响应数据。有关工作示例,请参见cefclient/browser/response_filter_test.cc(可通过测试菜单 > 其他测试 > 响应过滤从 cefclient 示例应用程序内部访问)。
2.5 其他回调该CefRequestHandler接口提供了各种网络相关的事件incuding验证,cookie处理,外部协议处理,证书错误等回调。
3.代理解析代理设置在 CEF3 中使用与 Google Chrome 相同的命令行标志进行配置。
--proxy-server=host:port
Specify the HTTP/SOCKS4/SOCKS5 proxy server to use for requests. An individual proxy
server is specified using the format:
[://][:]
Where is the protocol of the proxy server, and is one of:
"http", "socks", "socks4", "socks5".
If the is omitted, it defaults to "http". Also note that "socks" is equivalent to
"socks5".
Examples:
--proxy-server="foopy:99"
Use the HTTP proxy "foopy:99" to load all URLs.
--proxy-server="socks://foobar:1080"
Use the SOCKS v5 proxy "foobar:1080" to load all URLs.
--proxy-server="sock4://foobar:1080"
Use the SOCKS v4 proxy "foobar:1080" to load all URLs.
--proxy-server="socks5://foobar:66"
Use the SOCKS v5 proxy "foobar:66" to load all URLs.
It is also possible to specify a separate proxy server for different URL types, by prefixing
the proxy server specifier with a URL specifier:
Example:
--proxy-server="https=proxy1:80;http=socks4://baz:1080"
Load https://* URLs using the HTTP proxy "proxy1:80". And load http://*
URLs using the SOCKS v4 proxy "baz:1080".
--no-proxy-server
Disables the proxy server.
--proxy-auto-detect
Autodetect proxy configuration.
--proxy-pac-url=URL
Specify proxy autoconfiguration URL.
如果代理需要身份验证,CefRequestHandler::GetAuthCredentials() 回调将使用 |isProxy| 执行。值为 true 以检索用户名和密码。
bool MyHandler::GetAuthCredentials(
CefRefPtr browser,
CefRefPtr frame,
bool isProxy,
const CefString &host,
int port,
const CefString &realm,
const CefString &scheme,
CefRefPtr callback)
{
if (isProxy)
{
// Provide credentials for the proxy server connection.
callback->Continue("myuser", "mypass");
return true;
}
return false;
}
由于网络代理解析(例如,如果在 Windows 上选中“自动检测代理设置”),应用程序启动期间的 Web 内容加载可能会延迟。为了获得最佳用户体验,请考虑将您的应用程序设计为首先显示静态启动页面,然后使用元刷新重定向到实际网站——重定向将被阻止,直到代理解析完成。出于测试目的,可以使用“–no-proxy-server”命令行标志禁用代理解析。通过从命令行运行“chrome --url=…”,也可以在 Google Chrome 中复制代理解析延迟。
4.作者答疑如有疑问,请留言。