Main Site Documentation

How to map root path with the WebServer class


#1

I am trying to map the root path ("/") of a HTTP request to a WebEventReceived handler using the .NET Gadgeteer WebServer class. I want to display a custom HTML page when the user enters just the IP address of my device into the browser (e. g. http://192.168.1.208).

Tried all of the following without success.

WebServer.SetupWebEvent(null); // throws exception
WebServer.SetupWebEvent("");
WebServer.SetupWebEvent("/");

I am using Gadgeteer version 2.42.600


#2

Welcome to the forum!

Can you show more of your code where you setup the event and the handler?


#3

Sure. Here’s my code:

void ProgramStarted()
{
  ....

  WebServer.StartLocalServer("0.0.0.0", 80);
  var webEvent = WebServer.SetupWebEvent("");
  webEvent.WebEventReceived += OnWebEventReceived;
  webEvent = WebServer.SetupWebEvent("/");
  webEvent.WebEventReceived += OnWebEventReceived;
  webEvent = WebServer.SetupWebEvent("test");
  webEvent.WebEventReceived += OnWebEventReceived;
}

private void OnWebEventReceived(string path, WebServer.HttpMethod method, Responder responder)
{
  _log.Debug("WebEventReceived: path=" + path + ", method=" + method);
  responder.Respond("WebEventReceived: path=" + path + ", method=" + method);
}

Only when I browse to “http://…/test” it enters the OnWebEventReceived method.


#4

Try setting it for default document. Index.htm or Index.html.


#5

OK, hooking up “index.html” made it work. Hooking up “index.htm” on the other hand didn’t make a difference. I reduced all my code to a single WebEvent subscription:

var webEvent = WebServer.SetupWebEvent(“index.html”);
webEvent.WebEventReceived += OnWebEventReceived;

With that in place my OnWebEventReceived handler is called for any(!) URL path (empty, index.htm, index.html, test/1/2, whatever).

Weird! I expected to have the event handler called only for /index.html.

Another strange observation is that the OnWebEventReceived method is called twice(!) for each HTTP request. On the second call the “path” parameter is null.

Seems like the mapping of URL paths to WebEvent handlers in the WebServer class is a bit messy.

But at least I do have a workaround now. Thank you a lot!


#6

One more thing: The second call to OnWebEventReceived with path=null is a result of the browser requesting the “favicon.ico” file for the site.

Why is path=null? It should be “favicon.ico”.

The same happens when you explicitly request http://…/favicon.ico. In this case path is also null.

For all other .ico filenames (e. g. “favicon2.ico”) it works as expected.


#7

In my past experience we called that an undocumented feature.


#8

I have checked the code and it looks like there is a bug in the implementation of the internal Responder class.

inside ProcessHeader() method of the Responder class:

string Path = httpFirstLineParameters[1];

// ignore favicon ico and stop processing 
if (Path.Equals("/favicon.ico"))
{
      break;
}
else
{
       // get the path and check for parameters 
       Path = Path.Substring(1, Path.Length - 1);
       ....
       this.Path = Path;
}

as you can see in the case when favicon is requested the Responder Path property is not set. That property is used later to find the proper WebEvent object. And since it is not set the default WebEvent is used and the path is null.

It is a bug for sure.


#9

@ Architect - NETMF bug?


#10

Nope - Gadgeteer.

Main/GadgeteerCore/Libraries/Core/WebServer42/Responder.cs (line 395)


#11

Yep, the favicon.ico bug is indeed located in Responder.cs.

There’s another bug in WebServerManager.cs which “kills” support for the empty root path:

                if (responder.Path != null && responder.Path.Length > 1)
                {
                    webevent = serverManager.GetWebEventById(responder.Path);
                }             

responder.Path.Length > 1 should be omitted.


#12

please vote https://gadgeteer.codeplex.com/workitem/1565


#13

Done!

Not really a HTTP bug, but that is ok.


#14

Honestly, I don’t see any benefit of using the Gadgeteer WebServer class. I reverted my code back to the old HttpListener implementation (part of NETMF) which is much more concise in my opinion.