当我们基于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->SetURL("http://xxx.net");
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() test
UrlRequestClient *client = new UrlRequestClient(new PrintUrlReqCallback);
std::string url("http://www.baidu.com");
client->Get(url);
 
// Request() test
CefRefPtr<cefrequest> req = CefRequest::Create();
req->SetMethod("GET");
req->SetURL("http://www.csdn.net");
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() test
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"));
(new UrlRequestClient(new PrintUrlReqCallback))->Post("http://xxx.com/hello", data, headers);
</cefpostdataelement></cefpostdata></cefrequest></code>

就这样吧。

使用CEF类库处理HTTP请求的更多相关文章

  1. [Java] 模拟HTTP的Get和Post请求

    在之前,写了篇Java模拟HTTP的Get和Post请求的文章,这篇文章起源与和一个朋友砍飞信诈骗网站的问题,于是动用了Apache的comments-net包,也实现了get和post的http请求 ...

  2. iOS开发-网络-合理封装请求接口

    概述 如今大多App都会与网络打交道,作为开发者,合理的对网络后台请求接口进行封装十分重要.本文要介绍的就是一种常见的采用回调函数(方法)的网络接口封装,也算的是一种构架吧. 这个构架主要的idea是 ...

  3. 从零学习Fluter(五):Flutter中手势滑动拖动已经网络请求

    从六号开始搞Flutter,到今天写这篇blog已经过了4天时间,文档初步浏览了一遍,写下了这个demo.demo源码分享在github上,现在对flutter有种说不出的喜欢了.大家一起搞吧! 废话 ...

  4. 前端通信:ajax设计方案(八)--- 设计请求池,复用请求,让前端通信快、更快、再快一点

    直接进入主题,本篇文章有点长,包括从设计阶段,到摸索阶段,再到实现阶段,最后全面覆盖测试阶段(包括数据搜集清洗),还有与主流前端通信框架进行对比PK阶段. 首先介绍一下一些概念: 1. 浏览器的并发能 ...

  5. 【ShoppingWebCrawler】-基于Webkit内核的爬虫蜘蛛引擎概述

    写在开头 在各个电商平台发展日渐成熟的今天.很多时候,我们需要一些平台上的基础数据.比如:商品分类,分类下的商品详细,甚至业务订单数据.电商平台大多数提供了相应的业务接口.允许ISV接入,用来扩展自身 ...

  6. Webkit内核开源爬虫蜘蛛引擎

    C#开发的基于Webkit内核开源爬虫蜘蛛引擎 https://www.cnblogs.com/micro-chen/p/9075590.html 概述 在各个电商平台发展日渐成熟的今天.很多时候,我 ...

  7. ABP理论之CSRF

    返回总目录 本篇目录 介绍 ASP.NET MVC ASP.NET WEB API ASP.NET Core[以后补上] 客户端类库 内部原理 介绍 CSRF[Cross-Site Request F ...

  8. 实现iOS图片等资源文件的热更新化(四): 一个最小化的补丁更新逻辑

    简介 以前写过一个补丁更新的文章,此处会做一个更精简的最小化实现,以便于集成.为了使逻辑具有通用性,将剥离对AFNetworking和ReativeCocoa的依赖.原来的文章,可以先看这里: htt ...

  9. 基于.net开发chrome核心浏览器【六】

    写在前面: 距离发这个系列的上一篇文章已经过去两个多月了 因为工作上不涉及这一部分的内容,兼且琐事缠身,一直无力动笔写这个系列的第六篇文章 然而,有很多朋友都关注这个系列,希望我能再写写. 写文章有人 ...

随机推荐

  1. fsck - 检查并修复Linux文件系统

    总览 SYNOPSIS fsck [ -sACVRTNP ] [ -t fstype ] [filesys ... ] [--] [ fs-specific-options ] 描述 DESCRIPT ...

  2. js中重载问题

    在js中是没有重载的  但是  Arguments对象(可以实现模拟重载的效果) 利用arguments对象的length属性,可以获取函数接收的参数的个数 例如: function add(){ i ...

  3. .net MVC下跨域Ajax请求(JSONP)

    一.JSONP(JSON with Padding) 客户端: <script type="text/javascript"> function TestJsonp() ...

  4. django 模板中{%for%}的使用

    1.{%for athlete in list reversed%}  reversed用于反向迭代 2.for 标签 支持一个可选的 empty 变量 3.forloop 模板变量 4.forloo ...

  5. ubuntu18.04server 真机无法自动获取IP解决方法

    输入命令ip a,查看自己网卡编号,比如我的就是ens33 因为此图为虚拟机搭建的,所以网卡名称为ens33,如果是真机的话则是enp0s**的名字 2.修改netwlpan文件 1 sudo vim ...

  6. ArrayList集合(JDK1.8)

    简述 List是继承于Collection接口,除了Collection通用的方法以外,扩展了部分只属于List的方法. 常用子类  ?ArrayList介绍 1.数据结构 其底层的数据结构是数组,数 ...

  7. hdu3376 Matrix Again

    最大费用最大流 咋写?取个相反数就可以了-- #include <iostream> #include <cstring> #include <cstdio> #i ...

  8. 大数据学习——安装zooleeper

    1 alt+p,上传zookeeper-3.4.5.tar.gz 2 解压安装包 ,安装在apps目录下 tar -zxvf zookeeper-3.4.5.tar.gz -C apps 3 删除zo ...

  9. &quot;转成"

    在java中这样转 StringEscapeUtils.unescapeHtml(soapResponseData); 在js中这样转 str.replace(""",& ...

  10. 【java 理论篇 2】J2EE的13种规范

    导读:看完了J2EE的视频,没有什么技术实践,现在就从理论上说明一下J2EE的13种规范,以及现在的自己对它的一个理解.可能会有偏差,但是,算是做为目前的一个记录. 一.13种规范 1.1.JDBC( ...