使用CEF类库处理HTTP请求
当我们基于CEF开发应用时,可能会有URL请求处理的需求,比如HTTP下载或上传,此时可以利用CEF提供的类库来完成,而不必自己实现或引入其它第三方的类库。
在CEF里为URL Request设计了两组类,一组用于执行网络请求,一组代表请求数据。
URLRequest
CefURLRequest是执行URL请求的类(接口),对应的头文件是cef_urlrequest.h,实现则在libcef/common/urlrequest_impl.cc文件中。
CefURLRequest类的静态方法Create()可以创建并执行一个URL请求。它的原型如下:
|
1
2
3
4
5
|
<code>static CefRefPtr<cefurlrequest> Create( CefRefPtr<cefrequest> request, CefRefPtr<cefurlrequestclient> client, CefRefPtr<cefrequestcontext> request_context);</cefrequestcontext></cefurlrequestclient></cefrequest></cefurlrequest></code> |
第一个参数,类型是CefRequest,代表一个URL请求,CEF库内部已经实现了,后面会讲到。
第二个参数,类型是CefURLRequestClient,用于接收服务器返回的状态和数据,需要我们自己继承CefURLRequestClient接口实现一个非抽象类。后面有了。
第三个参数,CefRequestContext,为NULL时内部会自己创建一个合适的Context,不为NULL时就用传入的Context。
Create方法会根据当前是Browser进程还是Renderer进程来创建对应的URLRequest类,CefBrowserURLRequest(browser_urlrequest_impl.h/.cc)或CefRenderURLRequest(render_urlrequest_impl.h/.cc)。
这么分析下来,我们要进行URL请求,实际上要做的工作就是:
构造一个CefRequest,代表我们的请求 写一个类实现CefURLRequestClient接口来处理响应。 调用CefURLRequest::Create()创建一个URL请求处理对象
构造Request
CefRequest类代表了一个URL请求,它里面可以配置方法、URL、头部、上传的数据等。下面的代码片段演示了如何构造一个 CefRequest 对象:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<code>CefRefPtr<cefpostdata> data = CefPostData::Create();CefRefPtr<cefpostdataelement> element = CefPostDataElement::Create();const char szData[] = "Hello World!";element->SetToBytes(sizeof(szData) - 1, (const void*)szData);data->AddElement(element);CefRequest::HeaderMap headers;headers.insert(std::make_pair("Content-Type", "text/plain"));headers.insert(std::make_pair("Accept", "text/plain"));CefRefPtr<cefrequest> req = CefRequest::Create();req->SetMethod("POST");req->SetHeaderMap(headers);req->SetPostData(data);</cefrequest></cefpostdataelement></cefpostdata></code> |
与一个请求相关的类和接口,都在cef_request.h中,实现在request_impl.cc中。这些类都有静态的Create方法,可以返回一个代表具体实例的接口,然后就可以接口的方法来定制实例对象,定制后的对象就可以用于URL请求了。
刚才的代码片段演示了如何构造一个CefRequest对象,其中用到了下面的类(接口):
CefRequest,代表了一个URL请求 CefPostData,管理要通过请求发送的数据,它内部维护了多个CefPostDataElement,每个CefPostDataElement代表了一个要发送的数据元素 CefPostDataElement,代表发送的数据,提供了一些接口,可以关联到文件,也可以直接发送字节
想了解至于这些类的接口,打开头文件看看吧。
实现CefURLRequestClient接口
CefURLRequestClient接口的实现可以很简单,我实现了一个简单的UrlRequestClient类。
UrlRequestClient.h如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
<code>#ifndef URL_REQUEST_CLIENT_H#define URL_REQUEST_CLIENT_H#include <string>#include "include/cef_urlrequest.h"#include "include/wrapper/cef_helpers.h"class UrlRequestCompletionCallback{public: virtual ~UrlRequestCompletionCallback(){} virtual void OnCompletion(CefURLRequest::ErrorCode errorCode, const std::string& data) = 0;};class UrlRequestClient : public CefURLRequestClient{public: UrlRequestClient() : m_callback(0) { CEF_REQUIRE_UI_THREAD(); } UrlRequestClient(UrlRequestCompletionCallback *callback) : m_callback(callback) { CEF_REQUIRE_UI_THREAD(); } // //interfaces of CefURLRequestClient // void OnRequestComplete(CefRefPtr<cefurlrequest> request) OVERRIDE; void OnUploadProgress(CefRefPtr<cefurlrequest> request, int64 current, int64 total) OVERRIDE; void OnDownloadProgress(CefRefPtr<cefurlrequest> request, int64 current, int64 total) OVERRIDE; void OnDownloadData(CefRefPtr<cefurlrequest> request, const void* data, size_t data_length) OVERRIDE; bool GetAuthCredentials(bool isProxy, const CefString& host, int port, const CefString& realm, const CefString& scheme, CefRefPtr<cefauthcallback> callback) OVERRIDE{ return false; } void Request(CefRefPtr<cefrequest> cef_request); void Get(const std::string &url, const CefRequest::HeaderMap &headers = CefRequest::HeaderMap()); void Post(const std::string &url, const CefRefPtr<cefpostdata> data, const CefRequest::HeaderMap &headers = CefRequest::HeaderMap()); void SetCompletionCallback(UrlRequestCompletionCallback *callback) { m_callback = callback; }private: UrlRequestCompletionCallback *m_callback; CefRefPtr<cefurlrequest> m_urlRequest; std::string m_data; IMPLEMENT_REFCOUNTING(UrlRequestClient); DISALLOW_COPY_AND_ASSIGN(UrlRequestClient);};class PrintUrlReqCallback : public UrlRequestCompletionCallback{public: void OnCompletion(CefURLRequest::ErrorCode errorCode, const std::string& data);};#endif</cefurlrequest></cefpostdata></cefrequest></cefauthcallback></cefurlrequest></cefurlrequest></cefurlrequest></cefurlrequest></string></code> |
UrlRequestClient.cpp内容如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
<code>#include "UrlRequestClient.h"#include <windows.h>void UrlRequestClient::OnRequestComplete(CefRefPtr<cefurlrequest> request){ CEF_REQUIRE_UI_THREAD(); if (m_callback) { m_callback->OnCompletion(request->GetRequestError(), m_data); }}void UrlRequestClient::OnUploadProgress(CefRefPtr<cefurlrequest> request, int64 current, int64 total){}void UrlRequestClient::OnDownloadProgress(CefRefPtr<cefurlrequest> request, int64 current, int64 total){ char szLog[128] = { 0 }; sprintf_s(szLog, 128, "UrlRequestClient::OnDownloadProgress, current-%lld, total-%lld\r\n", current, total); OutputDebugStringA(szLog);}void UrlRequestClient::OnDownloadData(CefRefPtr<cefurlrequest> request, const void* data, size_t data_length){ m_data += std::string(static_cast<const>(data), data_length);}void UrlRequestClient::Request(CefRefPtr<cefrequest> cef_request){ m_urlRequest = CefURLRequest::Create(cef_request, this, NULL);}void UrlRequestClient::Get(const std::string &url, const CefRequest::HeaderMap &headers /*= CefRequest::HeaderMap()*/){ CefRefPtr<cefrequest> req = CefRequest::Create(); req->SetURL(url); req->SetMethod("GET"); req->SetHeaderMap(headers); Request(req);}void UrlRequestClient::Post(const std::string &url, const CefRefPtr<cefpostdata> data, const CefRequest::HeaderMap &headers /*= CefRequest::HeaderMap()*/){ CefRefPtr<cefrequest> req = CefRequest::Create(); req->SetURL(url); req->SetMethod("POST"); req->SetHeaderMap(headers); req->SetPostData(data); Request(req);}//// for test//void PrintUrlReqCallback::OnCompletion(CefURLRequest::ErrorCode errorCode, const std::string& data){ char szLog[128] = { 0 }; sprintf_s(szLog, 128, "PrintUrlReqCallback::OnCompletion, errorCode = %d, data.len = %d, data:\r\n", errorCode, data.length()); OutputDebugStringA(szLog); delete this;}</cefrequest></cefpostdata></cefrequest></cefrequest></const></cefurlrequest></cefurlrequest></cefurlrequest></cefurlrequest></windows.h></code> |
UrlRequestClient类可以发起URL请求并处理响应。它的用法类似下面这样(注意要在Browser进程的UI线程使用):
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
<code>// Get() testUrlRequestClient *client = new UrlRequestClient(new PrintUrlReqCallback);client->Get(url);// Request() testCefRefPtr<cefrequest> req = CefRequest::Create();req->SetMethod("GET");CefRequest::HeaderMap headers;headers.insert(std::make_pair("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"));headers.insert(std::make_pair("Accept-Encoding", "gzip,deflate,sdch"));headers.insert(std::make_pair("Accept-Language", "en,zh"));req->SetHeaderMap(headers);(new UrlRequestClient(new PrintUrlReqCallback))->Request(req);// Post() testCefRefPtr<cefpostdata> data = CefPostData::Create();CefRefPtr<cefpostdataelement> element = CefPostDataElement::Create();const char szData[] = "Hello World!";element->SetToBytes(sizeof(szData) - 1, (const void*)szData);data->AddElement(element);CefRequest::HeaderMap headers;headers.insert(std::make_pair("Content-Type", "text/plain"));headers.insert(std::make_pair("Accept", "text/plain"));</cefpostdataelement></cefpostdata></cefrequest></code> |
就这样吧。
使用CEF类库处理HTTP请求的更多相关文章
- [Java] 模拟HTTP的Get和Post请求
在之前,写了篇Java模拟HTTP的Get和Post请求的文章,这篇文章起源与和一个朋友砍飞信诈骗网站的问题,于是动用了Apache的comments-net包,也实现了get和post的http请求 ...
- iOS开发-网络-合理封装请求接口
概述 如今大多App都会与网络打交道,作为开发者,合理的对网络后台请求接口进行封装十分重要.本文要介绍的就是一种常见的采用回调函数(方法)的网络接口封装,也算的是一种构架吧. 这个构架主要的idea是 ...
- 从零学习Fluter(五):Flutter中手势滑动拖动已经网络请求
从六号开始搞Flutter,到今天写这篇blog已经过了4天时间,文档初步浏览了一遍,写下了这个demo.demo源码分享在github上,现在对flutter有种说不出的喜欢了.大家一起搞吧! 废话 ...
- 前端通信:ajax设计方案(八)--- 设计请求池,复用请求,让前端通信快、更快、再快一点
直接进入主题,本篇文章有点长,包括从设计阶段,到摸索阶段,再到实现阶段,最后全面覆盖测试阶段(包括数据搜集清洗),还有与主流前端通信框架进行对比PK阶段. 首先介绍一下一些概念: 1. 浏览器的并发能 ...
- 【ShoppingWebCrawler】-基于Webkit内核的爬虫蜘蛛引擎概述
写在开头 在各个电商平台发展日渐成熟的今天.很多时候,我们需要一些平台上的基础数据.比如:商品分类,分类下的商品详细,甚至业务订单数据.电商平台大多数提供了相应的业务接口.允许ISV接入,用来扩展自身 ...
- Webkit内核开源爬虫蜘蛛引擎
C#开发的基于Webkit内核开源爬虫蜘蛛引擎 https://www.cnblogs.com/micro-chen/p/9075590.html 概述 在各个电商平台发展日渐成熟的今天.很多时候,我 ...
- ABP理论之CSRF
返回总目录 本篇目录 介绍 ASP.NET MVC ASP.NET WEB API ASP.NET Core[以后补上] 客户端类库 内部原理 介绍 CSRF[Cross-Site Request F ...
- 实现iOS图片等资源文件的热更新化(四): 一个最小化的补丁更新逻辑
简介 以前写过一个补丁更新的文章,此处会做一个更精简的最小化实现,以便于集成.为了使逻辑具有通用性,将剥离对AFNetworking和ReativeCocoa的依赖.原来的文章,可以先看这里: htt ...
- 基于.net开发chrome核心浏览器【六】
写在前面: 距离发这个系列的上一篇文章已经过去两个多月了 因为工作上不涉及这一部分的内容,兼且琐事缠身,一直无力动笔写这个系列的第六篇文章 然而,有很多朋友都关注这个系列,希望我能再写写. 写文章有人 ...
随机推荐
- 制作SD更新系统时和用mfgtool工具烧录时,文件如何替换?
制作SD更新系统时和用mfgtool工具烧录时,文件如何替换? 答:制作SD更新系统时,请按照需求选择不同mfgimages-myd*文件夹.每个文件夹里面有一个Manifest文件, 里面规定了ub ...
- Moebius for SQLServer负载均衡
搞数据库的都知道:在Oracle上有RAC集群,MySQL也有对应的方案,而SQL Server上直到SQL Server 2012版本的AlwaysOn到来,微软都没有提供一个负载均衡方案,在网上看 ...
- 微信小程序:this code is a mock one
问题 微信小程序调用wx.login() 的 success 函数带的code 提示this code is a mock one 解决方法 appid和微信小程序开发工具所登陆用户管理的小程序清单不 ...
- es6(三set和map数据结构)
es6中提供了一个新的数据结构Set,他有点类似数组,但和数组不同的是,在里面你如果写入重复的值的话,他不会显示重复值. const s =new Set(); [2,3,4,5,6,6,6,7,8, ...
- Puppeteer-常规操作一
这里不讲 Puppeteer 怎么使用,主要讲一些常规操作在这里如何通过另类方法实现.等实现后,你就会感觉,嗯~~ 真香! 场景一 已经找出要的元素,现在有需求再继续寻找他的子元素 第一种.将父元素带 ...
- Spoj8093 Sevenk Love Oimaster
题目描述 题解: 对于所有n串建广义后缀自动机. (广义后缀自动机唯一区别就是每次将las附成1,并不需要在插入时特判) 建完后再建出parent树,然后用dfs序+树状数组搞区间不同种类. 其实就是 ...
- layui二次封装
最近一直用layui进行页面的重构,这个框架十分适合我们后台人员开发.简单易用,但是layui本身不支持双向绑定,所以很多情况下,我们在支持动态的控件加载时,需要反复刷新.这里我自己封装了一个comm ...
- tornado框架基础09-cookie和session
01 cookie 在上节,我们简单了解了登录过程,但是很明显,每次都需要登录,但是在平常逛网站的只需要登录一次,那么网站是如何记录登录信息的呢? 有没有什么办法可以让浏览器记住登录信息,下次再次打开 ...
- tornado框架基础02-输入和输出
01 输出 write bytes类型 class IndexHandler(tornado.web.RequestHandler): def get(self): self.write(b'Torn ...
- centos7 ftp 500 OOPS: cannot change directory:/var/ftp/xutong/
在设置多用户登录的时候 该指定的用户xutong对于上级目录/var/ftp 没有访问权限 修改一下上级目录的权限 chmod /var/ftp 对于ftp多用户访问的配置修改也做一个记录 以是设置F ...