Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 427
JackJack Avatar asked Jul 06 '15 16:07

JackJack


People also ask

Can the user create his own custom header files in C?

Yes, the user can create his/her own custom header files in C. It helps you to manage the user-defined methods, global variables, and structures in a separate file, which can be used in different modules. Let’s see an example of how to create and access custom header files −

How to send headers to URL pattern in Chrome Developer Tools?

Select URL pattern and enter the desired domain pattaern (e.g. *://infoheap.com/). You can also enter multiple patterns. In that case headers will be sent to url matching any pattern. Open Chrome developer tools and load a url which matches with above pattern.

How do I send custom headers to outgoing requests?

One can also use HttpContext to access required headers and verify. Adding HeaderPropogation Middleware is also a very simple way of adding the headers and propagating them to the next request. Please see here below article on how to use HeaderPropogation Middleware to send custom headers to outgoing requests.

How to add custom headers to a request for debugging?

At times we may need to add custom headers to a request for debugging purpose. e.g. You may want to display debugging messages when specific header is present in request (e.g. debug with value 1). This can be done using Modify header chrome plugin. Here are quick steps: Install the Modify header plugin in Chrome browser.


3 Answers

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.

  • RequestHandler API Doc
  • ResourceRequestHandler API Doc
  • IRequest.GetHeaderByName API Doc
  • IRequest.SetHeaderByName API Doc
like image 82
amaitland Avatar answered Oct 19 '22 13:10

amaitland


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") .

like image 6
Psddp Avatar answered Oct 19 '22 11:10

Psddp


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);
like image 5
Evgeniy Vaganov Avatar answered Oct 19 '22 13:10

Evgeniy Vaganov