zoukankan      html  css  js  c++  java
  • 使用CEF类库处理HTTP请求

    当我们基于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 ",
            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: ",
            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>

    就这样吧。

  • 相关阅读:
    Intellij Idea免费激活方法
    算法中的 log 到底是什么?
    java 历史版本下载
    IntelliJ远程调试教程
    【转载】 tensorflow batch_normalization的正确使用姿势
    【转载】 Tensorflow如何直接使用预训练模型(vgg16为例)
    某宝购入牙膏厂U后其售后事宜的思虑
    【转载】 tensorflow: 怎样找到对应的bazel 版本和安装
    【转载】 优必选悉尼 AI 研究院何诗怡:基于课程学习的强化多标签图像分类算法 | 分享总结
    【转载】 科研工作者的哪些「新手常见错误」
  • 原文地址:https://www.cnblogs.com/h2zZhou/p/7068231.html
Copyright © 2011-2022 走看看