使用CEF类库处理HTTP请求

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

                       

当我们基于CEF开发应用时,可能会有URL请求处理的需求,比如HTTP下载或上传,此时可以利用CEF提供的类库来完成,而不必自己实现或引入其它第三方的类库。

在CEF里为URL Request设计了两组类,一组用于执行网络请求,一组代表请求数据。

 

foruok原创,转载请保留出处或关注foruok的微信订阅号“程序视界”来联系foruok。

URLRequest

CefURLRequest是执行URL请求的类(接口),对应的头文件是cef_urlrequest.h,实现则在libcef/common/urlrequest_impl.cc文件中。

CefURLRequest类的静态方法Create()可以创建并执行一个URL请求。它的原型如下:

static CefRefPtr<CefURLRequest> Create(      CefRefPtr<CefRequest> request,      CefRefPtr<CefURLRequestClient> client,      CefRefPtr<CefRequestContext> request_context);
   
   
  • 1
  • 2
  • 3
  • 4

第一个参数,类型是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 对象:

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);
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

与一个请求相关的类和接口,都在cef_request.h中,实现在request_impl.cc中。这些类都有静态的Create方法,可以返回一个代表具体实例的接口,然后就可以接口的方法来定制实例对象,定制后的对象就可以用于URL请求了。

刚才的代码片段演示了如何构造一个CefRequest对象,其中用到了下面的类(接口):

  • CefRequest,代表了一个URL请求
  • CefPostData,管理要通过请求发送的数据,它内部维护了多个CefPostDataElement,每个CefPostDataElement代表了一个要发送的数据元素
  • CefPostDataElement,代表发送的数据,提供了一些接口,可以关联到文件,也可以直接发送字节

想了解至于这些类的接口,打开头文件看看吧。

实现CefURLRequestClient接口

CefURLRequestClient接口的实现可以很简单,我实现了一个简单的UrlRequestClient类。

UrlRequestClient.h如下:

#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
   
   
  • 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

UrlRequestClient.cpp内容如下:

#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 char*>(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;}
   
   
  • 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

UrlRequestClient类可以发起URL请求并处理响应。它的用法类似下面这样(注意要在Browser进程的UI线程使用):

// Get() testUrlRequestClient *client = new UrlRequestClient(new PrintUrlReqCallback);std::string url("http://www.baidu.com");client->Get(url);// Request() testCefRefPtr<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() 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"));(new UrlRequestClient(new PrintUrlReqCallback))->Post("http://xxx.com/hello", data, headers);
   
   
  • 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

就这样吧。

关于CEF里的线程,可以参考:http://blog.csdn.net/foruok/article/details/50674141

关于进程,可以参考:http://blog.csdn.net/foruok/article/details/50621751

其他参考文章详见我的专栏:【CEF与PPAPI开发】。

           

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

这里写图片描述

猜你喜欢

转载自blog.csdn.net/jfdfhh/article/details/84195656
今日推荐