2

An internal webserver requires me to supply a custom http header in order to access the webpages. This works fine the most part but if the html or javascript starts a redirect or uses an AJAX request it doesn't use my headers anymore.

Is there some way to change this behaviour so it always sends my custom header?

    private void Form1_Load(object sender, EventArgs e)
    {
        webBrowser1.Navigate("http://localhost/test.php", null, null, "User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36\r\nSomething-Custom: TestValue");
    }

Javascript code in the php file:

<script>
window.location="?redirect";
</script>

The first requests received my header 'Something-Custom', while the second request with ?redirect doesn't. I also added the user-agent to verify that it indeed resets all headers.

1 Answers1

1

There are several possible ways to do this. Really wide field for research.

Overwrite headers for each navigation

Hook Navigating event, cancel it and call Navigate with required headers (and do not cancel this event:)

You can even load data outside of WebBrowser control.

Change headers before navigation

If you don't like the idea of cancelling requests and then reissuing them, then you can try to hook Navigating event and update headers.

Here is the problem: IWebBrower2 control itself provides headers as an argument for BeforeNavigate event. But when .NET code handles this event, headers are not exposed in WebBrowserNavigatingEventArgs for a client code.

Possible solution is that you create own version of WebBrowserEvent, subclass WebBrowser control, override CreateSink method to connect your version of WebBrowserEvent. This version should handle headers correctly.

So you'd be able to change headers before navigation.

Adjust Javascript side - somewhat fuzzier.

You can connect browser application with client-side via WebBrowser.ObjectForScripting property - it is available for Javascript objects as window.external.

You can hook links click events, or build own approach about how to notify external object about navigation need.

Then you'll be able to perform all navigations from .NET side, specifying headers as needed.

System Proxy

Set up local proxy (you can experiment with Fiddler). You'll be able to make any headers manipulation you wish. The only issue that WebBrowser control would use proxy from IE configuration.

Community
  • 1
  • 1
mikalai
  • 1,746
  • 13
  • 23
  • Great answer!! with many approaches. My problem was solved by using your first solution, cancling each navigating event and call them with my own header. Little tip if you only want to change the user-agent or set a proxy [UrlMkSetSessionOption](http://msdn.microsoft.com/en-us/library/ie/ms775125%28v=vs.85%29.aspx) – Jack Winters Dec 12 '14 at 20:26
  • Can you please elaborate more on "Change headers before navigation"? I do override already the CreateSink and I would like to add an header to each signe navigation. – Simone May 25 '17 at 13:47
  • @Simone - that's something like https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.webbrowser.createsink?view=netframework-4.7 Custom class "WebBrowser2EventHelper" can receive headers in BeforeNavigate method (not implemented in this sample) and here you can change them before passing to web browser. – mikalai May 25 '17 at 17:03
  • @mikalai - do you mean changing the headers in the event itself inside BeforeNavigate or handling the navigation inside it and starting a new navigation calling Navigate with the correct headers? From my tests the first has no effect and the second creates problems with IFrames... But maybe I am doing it wrong. Thanks. – Simone May 26 '17 at 18:22
  • @Simone Yes, first way looks more consistent. – mikalai May 27 '17 at 20:04
  • @mikalai tried the 1st without success.I would really apreciate if you can check the following: I Inherit from Form WebBrowser and override `protected override void CreateSink() { base.CreateSink(); this._events = new MyWebBrowserEvents(this);}` then in MyWebBrowserEvents (which inherit from StandardOleMarshalObject,DWebBrowserEvents2) I implement `public void BeforeNavigate2(object pDisp, ref object url, ref object flags, ref object targetFrameName, ref object postData, ref object headers, ref bool cancel) { headers += "myHeader: myValue" }` I Check with fiddler,no track of myHeader – Simone May 30 '17 at 02:34
  • @mikalai - Yes, sure. As a test You can use a modified version from this project https://www.codeproject.com/Articles/13598/Extended-NET-2-0-WebBrowser-Control here is the link: https://1drv.ms/u/s!AnRJvoBpV1lOg4cU4TD9q0hBmmjIvw Clicking on the "test url" button and note button1_Click and BeforeNavigate2. Background: I was using user:pass@ in the url but it gets printed out so trying to embed authentication headers in each request... Originally I was expecting header passed in the original Navigate to be passed over automatically to following requests but it was not the case. Thanks! – Simone Jun 02 '17 at 16:31
  • @Simone Looks like you're right - browser control provides headers as "in" and over-writing them has no effect. – mikalai Jun 05 '17 at 19:33