博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用CEF类库处理HTTP请求
阅读量:6359 次
发布时间:2019-06-23

本文共 8038 字,大约阅读时间需要 26 分钟。

当我们基于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(
""
);
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(
""
);
client->Get(url);
 
// Request() test
CefRefPtr<cefrequest> req = CefRequest::Create();
req->SetMethod(
"GET"
);
req->SetURL(
""
);
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(
""
, data, headers);
</cefpostdataelement></cefpostdata></cefrequest></code>

就这样吧。

转载地址:http://eubma.baihongyu.com/

你可能感兴趣的文章
解决获取IP地址时出现“在一个非套…
查看>>
osx的终端软件iterm2 之 修改外观 和 常用快捷键小结
查看>>
Android自动化测试01-环境安装连接问题及解决
查看>>
九度 题目1523:从上往下打印二叉树 题目1521:二叉树的镜像
查看>>
ZOJ - 3703 Happy Programming Contest
查看>>
csa Round #66 (Div. 2 only)
查看>>
Get open Popups
查看>>
c#中两种不同的存储过程调用与比较
查看>>
设计模式-责任链模式(17)
查看>>
数论 + 公式 - HDU 4335 What is N?
查看>>
Public Prize
查看>>
生成 39 条形码
查看>>
抽象工厂理解
查看>>
计网第四章网络层(二)
查看>>
vs 行数
查看>>
nodejs下的express安装
查看>>
表单中的单文件点击和拖拽上传
查看>>
BZOJ1396 识别子串
查看>>
【转】numpy中 meshgrid 和 mgrid 的区别和使用
查看>>
【转】python中的闭包
查看>>