chromium - send custom header info on initial page load c#

13,739

Solution 1

Updated to reflect major Chromium changes

Updated to reflect changes made in version 75 (should work in 75 and newer)

The method you're after should be OnBeforeResourceLoad, a basic example should look like:

public class CustomResourceRequestHandler : ResourceRequestHandler
{
    protected override CefReturnValue OnBeforeResourceLoad(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback)
    {
        var headers = request.Headers;
        headers["User-Agent"] = "My User Agent";
        request.Headers = headers;

        return CefReturnValue.Continue;
    }
}

public class CustomRequestHandler : RequestHandler
{
    protected override IResourceRequestHandler GetResourceRequestHandler(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool isNavigation, bool isDownload, string requestInitiator, ref bool disableDefaultHandling)
    {
        return new CustomResourceRequestHandler();
    }
}

browser.RequestHandler = new CustomRequestHandler();

Using the IRequest.Headers property you must read the headers property, make changes then reassign it. It's now possible to use the SetHeaderByName/GetHeaderByName functions to get/set a single header.

Solution 2

You should create a class that implement IRequestHandler then set an instance of that class as RequestHandler in your browser object.

With version 53, that class should look like:

class ChromeBrowserRequestHandler: IRequestHandler
    {
        public bool GetAuthCredentials(IWebBrowser browserControl, IBrowser browser, IFrame frame, bool isProxy, string host, int port, string realm, string scheme, IAuthCallback callback)
        {
            return false;
        }

        public bool OnBeforeBrowse(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, bool isRedirect)
        {
            return false;
        }

        public bool OnBeforePluginLoad(IWebBrowser browser, string url, string policyUrl, WebPluginInfo info)
        {
            return false;
        }

        public CefReturnValue OnBeforeResourceLoad(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback)
        {
            var headers = request.Headers;
            headers["Custom-Header"] = "My Custom Header";
            request.Headers = headers;

            return CefReturnValue.Continue;
        }

        public bool OnCertificateError(IWebBrowser browser, CefErrorCode errorCode, string requestUrl)
        {
            return false;
        }

        public void OnPluginCrashed(IWebBrowser browser, string pluginPath)
        {
        }

        public void OnRenderProcessTerminated(IWebBrowser browserControl, IBrowser browser, CefTerminationStatus status)
        {
        }

        public IResponseFilter GetResourceResponseFilter(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response) 
        { 
            return null; 
        }

        public bool OnCertificateError(IWebBrowser browserControl, IBrowser browser, CefErrorCode errorCode, string requestUrl, ISslInfo sslInfo, IRequestCallback callback) 
        {
            return false; 
        }

        public bool OnOpenUrlFromTab(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl, WindowOpenDisposition targetDisposition, bool userGesture) 
        {
            return false; 
        }

        public void OnPluginCrashed(IWebBrowser browserControl, IBrowser browser, string pluginPath) 
        {
        }

        public bool OnProtocolExecution(IWebBrowser browserControl, IBrowser browser, string url) 
        {
            return false;
        }

        public bool OnQuotaRequest(IWebBrowser browserControl, IBrowser browser, string originUrl, long newSize, IRequestCallback callback) 
        {
            return false;
        }

        public void OnRenderViewReady(IWebBrowser browserControl, IBrowser browser) 
        { 
        }

        public void OnResourceLoadComplete(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response, UrlRequestStatus status, long receivedContentLength)
        { 
        }

        public void OnResourceRedirect(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, ref string newUrl) 
        { 
        }

        public bool OnResourceResponse(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response) 
        {
            return false;
        }
    }

Then, while creating your browser object:

ChromiumWebBrowser myBrowser = new ChromiumWebBrowser("whatever.com")
{
    RequestHandler = new ChromeBrowserRequestHandler()
};

Note that the request handler must be set before loading the page. If you can't set the request handler during instanctiaction, you can still set it later a reload the page with myBrowser.Load("whatever.com") .

Solution 3

In the one of the latest versions some callbacks have been moved from IRequestHandler to IResourceRequestHandler interface. Simplest way is to override default implementations RequestHandler & ResourceRequestHandler, for example:

class BearerAuthResourceRequestHandler : ResourceRequestHandler
    {
        public BearerAuthResourceRequestHandler(string token)
        {
            _token = token;
        }

        private string _token;

        protected override CefReturnValue OnBeforeResourceLoad(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback)
        {
            if (!string.IsNullOrEmpty(_token))
            {
                var headers = request.Headers;
                headers["Authorization"] = $"Bearer {_token}";
                request.Headers = headers;
                return CefReturnValue.Continue;
            }
            else return base.OnBeforeResourceLoad(chromiumWebBrowser, browser, frame, request, callback);
        }

    }
    class BearerAuthRequestHandler : RequestHandler
    {
        public BearerAuthRequestHandler(string token)
        {
            _token = token;
        }

        private string _token;

        protected override IResourceRequestHandler GetResourceRequestHandler(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool isNavigation, bool isDownload, string requestInitiator, ref bool disableDefaultHandling)
        {
            if (!string.IsNullOrEmpty(_token)) return new BearerAuthResourceRequestHandler(_token);
            else return base.GetResourceRequestHandler(chromiumWebBrowser, browser, frame, request, isNavigation, isDownload, requestInitiator, ref disableDefaultHandling);
        }
    }

Then, assign it to browser RequestHandler:

Browser.RequestHandler = new BearerAuthRequestHandler(token);
Share:
13,739
Admin
Author by

Admin

Updated on June 05, 2022

Comments

  • Admin
    Admin almost 2 years

    Or How to inject a custom header into the initial request to a site when new-ing up an instance of the ChromiumWebBrowser.

    I'm a noob with Chromium and could really use some help. I have a winforms app with a CEF window. K, no prob so far. What I need to do is to call/load the initial url with a custom http-header that contains authentication info. Is this possible?

    The following is essentially what is at play and all parts work except the custom header (Doh!)

    Winform(CEF httpRequest(with custom header)) [never gets past this point]=> C# MVC web app => Owin_Authentication_Pipeline segment => MVC Response with populated Razor view => Shows up in Winform Chromium app.

    Maybe this will help as well:

    using CefSharp;
    using CefSharp.WinForms;
    ...
    private void Form1_Load(object sender, EventArgs e)
    {
        Cef.Initialize();
        ChromiumWebBrowser myBrowser = new ChromiumWebBrowser("whatever.com");
        // ??How do i get a custom header be sent with the above line??
    
        myBrowser.Dock = DockStyle.Fill;
        //myBrowser.ShowDevTools();
        //myBrowser.RequestHandler = new DSRequestHander();
        //myBrowser.FrameLoadStart += myBrowser_FrameLoadStart;
        this.Controls.Add(myBrowser);
    }
    

    I Groggled this to death, looked, tried all the tricks in my toolbox and then some.

    Any ideas, help or hints on how I might be able to solve or get around this boggler is greatly appreciated. Thanks in advance.

  • CodingYourLife
    CodingYourLife almost 8 years
    I created a CustomChromeBrowser class inheriting from ChromiumWebBrowser and assign a RequestHandler class (comes with demo project) via Initialized event of the CustomChromeBrowser class.
  • amaitland
    amaitland almost 8 years
    All the Handlers are simple properties, assigning them in the constructor would be sufficient.
  • Psddp
    Psddp over 7 years
    Can we have more details please, I've the same issue and I'm not sure to understand how to do what you suggest.
  • scatter
    scatter almost 6 years
    This isn't working for me. The Headers property of the request just isn't changing. No exception is being thrown, it just won't update. Headers.IsReadOnly is false.
  • Carter
    Carter almost 4 years
    @amaitland Will this automatically apply to page requests and ajax requests? I am mainly wondering about changing the ajax requests and how to accomplish that. It looks like it should because i don't see other ways to accomplish scanning the API Doc. Anyway a word from you will kind of make my design decision and keep me from going other directions.
  • amaitland
    amaitland almost 4 years
    All requests directly related to the browser should flow through here. You can use cefsharp.github.io/api/81.3.x/html/… for RequestContext level handling. If you are having trouble isolating just the Ajax requests please ask a new question.
  • amaitland
    amaitland almost 4 years
    See github.com/cefsharp/CefSharp/wiki/… for background details for RequestContext. From memory requests from Service workers will only be accessible through the RequestContext level handling as they aren't necessarily directly associated with a browser.
  • Carter
    Carter almost 4 years
    @amaitland Thanks! you do a great job on CefSharp. Working like a charm thanks for all you do. +3
  • Josh Noe
    Josh Noe over 3 years
    Using version 47.0.2.0, I'm not seeing any change to the request headers in dev tools.