Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.Net HttpListener.GetContext() gives "503 Service Unavailable" to the client

I am trying to write a very very simple custom Http server in C#.

The code to achieve a connection is as simple as .Net offers it:

 // get our IPv4 address
 IPAddress[] localIPs = Dns.GetHostAddresses(Dns.GetHostName());
 IPAddress theAddress = localIPs.Where(ip => ip.AddressFamily == AddressFamily.InterNetwork).FirstOrDefault();

 // Create a http listener.
 var listener = new HttpListener();
 string myUrlPrefix = $"http://{theAddress.ToString()}:{port}/MyService/";
 listener.Prefixes.Add(myUrlPrefix);
 Console.WriteLine($"Trying to listen on {myUrlPrefix}");
 listener.Start();
 Console.WriteLine("Listening...");
 HttpListenerContext context = null;
 try
 {
     context = listener.GetContext();
 }
 catch(Exception ex)
 {
     Console.WriteLine(ex.Message);
 }

 HttpListenerRequest request = context.Request;

When running this, GetContext() blocks, never returns and does not throw an exception.

listener.Start() works -- the URL is properly reserved for the correct user with 'netsh http add urlacl...'., else Start() would throw. The URL is also only reserved once.

I can see with netstat -na that the port is being listened on.

I am trying to access this with either a browser or with the cygwin implementation of wget. Both give me "ERROR 503: Service Unavailable.".

Here is the wget output:

$ wget http://127.0.0.1:45987/MyService/
--2016-03-06 14:54:37--  http://127.0.0.1:45987/MyService/
Connecting to 127.0.0.1:45987... connected.
HTTP request sent, awaiting response... 503 Service Unavailable
2016-03-06 14:54:37 ERROR 503: Service Unavailable.

This means that the TCP connection gets established, yet HttpListener.GetContext() does not bother to service the request and give me the context, it also doesn't bother to at least throw an exception to tell me what's wrong. It just closes the connection. From the debug output, it doesn't even have a First-Chance exception inside that it would catch itself.

I have searched the Net and Stackoverflow up and down and don't find anything useful.

There are no errors in the Windows Event log.

This is Windows 10 Pro and Microsoft Visual Studio Community 2015 Version 14.0.23107.0 D14REL with Microsoft .NET Framework Version 4.6.01038.

It may be worth mentioning that I have also tested this with all firewalls off, still the same result.

Does anyone have any idea what could be going wrong in the GetContext() and how I could debug or solve this?

======

EDIT: I have enabled .Net Framework source stepping and have stepped into GetContext(). The blocking and refusal to service http requests happens in something called "UnsafeNclNativeMethods.HttpApi.HttpReceiveHttpRequest" which, I guess, might be the native HttpReceiveHttpRequest method documented at https://msdn.microsoft.com/en-us/library/windows/desktop/aa364495(v=vs.85).aspx . So it's the native API that is refusing my request.

like image 288
J S Avatar asked Mar 06 '16 04:03

J S


1 Answers

I just had the same problem, and it was caused by a URL ACL.

From an elevated command prompt

netsh http show urlacl will show all URL ACLs

netsh http delete urlacl http://+:1234/ will delete the URL ACL with the URL http://+:1234/

netsh http add urlacl url=http://+:1234/ user=Everyone will add a URL ACL that any local user can listen on (normally this should use the network service account)

This URL needs to match the prefix in your HttpListener.

If you're only listening on localhost, you don't need a URL ACL.

Normally not having the correct the URL ACL results in a permissions error when starting the listener. I'm not sure what the specific situation is that causes it to get past this but then return 503 Service Unavailable on GetContext.

like image 120
George Helyar Avatar answered Oct 13 '22 00:10

George Helyar