CEF 修改请求 header 与单独处理 header 中的 referer

有些时候利用 CEF 内嵌的页面加载某些资源的时候需要附带一些头信息,比如里面的图片需要携带一些校验和信息才能正常访问的,这个时候就需要在发起请求前对 HTTP Request 的 Header 部分进行修改。CEF 提供了两个接口用于读写 Request Header,分别是 CefLifeSpanHandler::OnAfterCreatedCefRequestHandler::OnBeforeResourceLoad 方法。两个都是虚函数,需要继承并重写两个方法来实现对 Request Header 的读取和修改。

区别

OnAfterCreatedOnBeforeResourceLoad 的区别是,OnAfterCreated 中传递的 request 参数是只读的, 这里只能对数据进行读取而不能修改。而 OnBeforeResourceLoad 中 request 参数是可以修改的。所以如果你需要添加或修改一些头信息需要在这里进行处理。

修改

修改的过程十分简单,只需要先把原来的 Header 信息读取出来,然后将你需要修改的信息删除再添加进去就可以了,如果只是新增内容,直接 emplace 就可以了。要注意的是,header 是一个 multimap 结构,允许有重复值,所以修改要么是基于原来修改,要么是删除再添加。

CefRequestHandler::ReturnValue ProfileMine::OnBeforeLoadResource(CefRefPtr<CefRequest> request, bool is_redirect)
{
    if (app_sdk::AppSDKInterface::IsSafeUrl(request->GetURL().ToString()))
    {
        // backup headers
        CefRequest::HeaderMap headers;
        request->GetHeaderMap(headers);

        // .... do something

        // add new headers
        headers.emplace("AppKey", appkey);
        headers.emplace("Nonce", nonce);
        headers.emplace("CurTime", curtime);
        headers.emplace("CheckSum", checksum);

        // reset headers
        request->SetHeaderMap(headers);

        // referer 要单独设置,不允许使用 SetHeaderMap 接口设置 referer 内容见 SetHeaderMap 注释
        request->SetReferrer(referer, REFERRER_POLICY_ALWAYS);

        QLOG_APP(L"ProfileMine::OnBeforeLoadResource short URL = {0}") << request->GetURL().ToString16();
    }

    return RV_CONTINUE;
}

注意事项

上面代码大家也注意到了,我没有将 referer 的值通 SetHeaderMap 方法来修改,而是后面调用单独的 SetReferrer 方法来修改,这源于 CEF 内部的限制,看一下 SetHeaderMap 的注释:

///
// Set the header values. If a Referer value exists in the header map it will
// be removed and ignored.
///
/–cef()–/
virtual void SetHeaderMap(const HeaderMap& headerMap) =0;

另外要注意的是,修改了 header 内容以后,通过 CEF 内置的调试工具抓包是看不到修改后的内容的,如果是 https 协议,你只能去服务器看一下接收到的参数中是否有你携带的 headers。这个要注意,我们在这个上面花费了很长时间,最后才发现调试工具是看不到的。

发表评论