使用CEF类库处理HTTP请求
2016-02-17 12:39
615 查看
当我们基于CEF开发应用时,可能会有URL请求处理的需求,比如HTTP下载或上传,此时可以利用CEF提供的类库来完成,而不必自己实现或引入其它第三方的类库。
在CEF里为URL Request设计了两组类,一组用于执行网络请求,一组代表请求数据。
foruok原创,转载请保留出处或关注foruok的微信订阅号“程序视界”来联系foruok。
CefURLRequest类的静态方法Create()可以创建并执行一个URL请求。它的原型如下:
第一个参数,类型是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请求处理对象
与一个请求相关的类和接口,都在cef_request.h中,实现在request_impl.cc中。这些类都有静态的Create方法,可以返回一个代表具体实例的接口,然后就可以接口的方法来定制实例对象,定制后的对象就可以用于URL请求了。
刚才的代码片段演示了如何构造一个CefRequest对象,其中用到了下面的类(接口):
CefRequest,代表了一个URL请求
CefPostData,管理要通过请求发送的数据,它内部维护了多个CefPostDataElement,每个CefPostDataElement代表了一个要发送的数据元素
CefPostDataElement,代表发送的数据,提供了一些接口,可以关联到文件,也可以直接发送字节
想了解至于这些类的接口,打开头文件看看吧。
UrlRequestClient.h如下:
UrlRequestClient.cpp内容如下:
UrlRequestClient类可以发起URL请求并处理响应。它的用法类似下面这样(注意要在Browser进程的UI线程使用):
就这样吧。
关于CEF里的线程,可以参考:/article/3660479.html。
关于进程,可以参考:/article/3644508.html。
其他参考文章详见我的专栏:【CEF与PPAPI开发】。
在CEF里为URL Request设计了两组类,一组用于执行网络请求,一组代表请求数据。
foruok原创,转载请保留出处或关注foruok的微信订阅号“程序视界”来联系foruok。
URLRequest
CefURLRequest是执行URL请求的类(接口),对应的头文件是cef_urlrequest.h,实现则在libcef/common/urlrequest_impl.cc文件中。CefURLRequest类的静态方法Create()可以创建并执行一个URL请求。它的原型如下:
[code]static CefRefPtr<CefURLRequest> Create( CefRefPtr<CefRequest> request, CefRefPtr<CefURLRequestClient> client, CefRefPtr<CefRequestContext> request_context);
第一个参数,类型是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 对象:[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);
与一个请求相关的类和接口,都在cef_request.h中,实现在request_impl.cc中。这些类都有静态的Create方法,可以返回一个代表具体实例的接口,然后就可以接口的方法来定制实例对象,定制后的对象就可以用于URL请求了。
刚才的代码片段演示了如何构造一个CefRequest对象,其中用到了下面的类(接口):
CefRequest,代表了一个URL请求
CefPostData,管理要通过请求发送的数据,它内部维护了多个CefPostDataElement,每个CefPostDataElement代表了一个要发送的数据元素
CefPostDataElement,代表发送的数据,提供了一些接口,可以关联到文件,也可以直接发送字节
想了解至于这些类的接口,打开头文件看看吧。
实现CefURLRequestClient接口
CefURLRequestClient接口的实现可以很简单,我实现了一个简单的UrlRequestClient类。UrlRequestClient.h如下:
[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
UrlRequestClient.cpp内容如下:
[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 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线程使用):
[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);
就这样吧。
关于CEF里的线程,可以参考:/article/3660479.html。
关于进程,可以参考:/article/3644508.html。
其他参考文章详见我的专栏:【CEF与PPAPI开发】。
相关文章推荐
- Python 17.1 HTTP协议简介
- HttpServlet
- http基础知识01
- 机器学习中的神经网络Neural Networks for Machine Learning:Lecture 3 Quiz
- 机器学习中的神经网络Neural Networks for Machine Learning:Programming Assignment 1: The perceptron learning alg
- web.config add handlers and httpmodule to System.Web section.
- oracle 11g 发信需要赋予权限 ORA-24247: 网络访问被访问控制列表 (ACL) 拒绝
- 机器学习中的神经网络Neural Networks for Machine Learning:Lecture 2 Quiz
- 机器学习中的神经网络Neural Networks for Machine Learning:Lecture 1 Quiz
- 关闭不安全的HTTP方法
- Android 使用Picasso加载网络图片等比例缩放
- ZOJ 1542 POJ 1861 Network 网络 最小生成树,求最长边,Kruskal算法
- Psping四大功能介绍:ICMP Ping/TCP Ping/延迟测试/带宽测试
- 服务器不能设置内容类型HTTP头信息后发送
- TCP/UDP 协议介绍
- netstat获得TCP连接信息的分类统计
- 【codevs1993】草地排水,网络流入门(dinic+ispa)
- 使用HttpURLConnection发送Post/Get请求
- Linux(Centos6.5)下安装svn服务器,并通过http访问-- 测试可用
- HTTP协议详解