使用CEF类库处理HTTP请求「建议收藏」

使用CEF类库处理HTTP请求

大家好,又见面了,我是全栈君。

当我们基于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);

第一个參数,类型是CefRequest,代表一个URL请求。CEF库内部已经实现了,后面会讲到。

第二个參数。类型是CefURLRequestClient,用于接收server返回的状态和数据,须要我们自己继承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);

与一个请求相关的类和接口,都在cef_request.h中,实如今request_impl.cc中。

这些类都有静态的Create方法。能够返回一个代表详细实例的接口。然后就能够接口的方法来定制实例对象,定制后的对象就能够用于URL请求了。

刚才的代码片段演示了怎样构造一个CefRequest对象。当中用到了以下的类(接口):

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

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

实现CefURLRequestClient接口

CefURLRequestClient接口的实现能够非常easy。我实现了一个简单的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

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;
}

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

// 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);

就这样吧。

关于CEF里的线程,能够參考:http://blog.csdn.net/foruok/article/details/50674141

关于进程,能够參考:http://blog.csdn.net/foruok/article/details/50621751

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/108236.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • hadoop namenode热备切换过程和secondarynamenode的作用

    hadoop namenode热备切换过程和secondarynamenode的作用hadoop namenode热备切换过程和secondarynamenode的作用

    2022年4月23日
    58
  • 用命令行进入目录_在命令行如何进入子目录

    用命令行进入目录_在命令行如何进入子目录CD命令是更改目录命令如果要进入D盘不用这个命令直接输入D:回车即可要是你非要使用CD命令那要加参数/D你图中输入的CD D:系统只是认为你想在系统中记忆一下D盘所以还是返回原先目录例:D盘下有一个目录叫AD下面还有一个目录叫AE 我想在你图中的位置直接进入AE目录命令如下CD/DD:\AD\AE一定要加参数(/D)如果不加参数只写CDD:\AD\AE系统还是…

    2022年10月15日
    4
  • 树莓派基于QT实现利用USB转485模块进行串口通讯「建议收藏」

    树莓派基于QT实现利用USB转485模块进行串口通讯「建议收藏」本文的QT版本为5.3.2,是树莓派可直接下载安装的QT版本,不用自己编译。树莓派为3B+。树莓派利用自带的硬件串口是3.3V的ttl电平,在做测试的时候会遇到很多485的设备,在使用232转485的模块遇到了一些乱码问题,所以准备直接利用USB转485模块插在树莓派的USB口上进行通讯。不过这个版本的QT没有Qserialport模块,需要安装,通过命令安装sudoapt-getinstal…

    2022年5月3日
    73
  • 三菱modbusRTU通讯实例_PLC编程入门梯形图实例讲解[通俗易懂]

    三菱modbusRTU通讯实例_PLC编程入门梯形图实例讲解[通俗易懂]点击箭头处“工业之家”,选择“关注公众号”!PLC编程入门梯形图实例讲解■上升沿下降沿梯形图解析上升沿:上升沿就是此点从不通到通的过程,在PLC里面表现就是只通一次。举例:如上图,当按钮1未按下的时候按钮1是断开的,此点不通,当按钮1被按下,按钮1导通,上面上升沿指令表示当按钮1按下去后,PLC只通一次,后面不管按钮1是否按下,整条线路都不通。下降沿:下降沿就是此点从通到不通的过程,在…

    2025年10月23日
    2
  • PhotoShop算法实现进阶-浮雕滤镜-灰度浮雕(三十一)

    PhotoShop算法实现进阶-浮雕滤镜-灰度浮雕(三十一)PhotoShop算法实现进阶-浮雕滤镜-灰度浮雕(三十一)kezunhai@gmail.comhttp://blog.csdn.net/kezunhai    浮雕效果可谓花样百出,但他们主要是基于图像相邻像素的差值来实现的。对于大多数图像而

    2022年6月20日
    33
  • CSS面试题

    CSS面试题1.有哪些方式(CSS)可以隐藏页面元素?1.opacity:0本质是将元素的透明度降为0,看起来是隐藏了,但是依然占据空间2.visibility:hidden占据空间3.display:none彻底隐藏元素,元素从文档流中消失,不占据空间4.z-index:-9999原理是将层级放到底部,看起来是隐藏了5.overflow:hidden这个只是隐藏元素溢出的部分6.transform:scale(0,0)将元素缩放为0,但是依然占据空间2.em\px\rem区别?Px:绝对

    2022年5月31日
    40

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号