Search code examples
c#.netiisasp.net-corekestrel

EADDRINUSE when using subdomains


Assume you have 2 ASP.NET core projects; an API and a website. I want to approach these locally (and simultaneously, since the website uses the api) using the following url's: devapi.website.com and dev.website.com.

Currently, I can only get this to work when I specify a different port number for both projects in the Program.cs file (and by using said port numbers in my browser):

API

var host = new WebHostBuilder()
     .UseUrls("http://devapi.website.com:81")
     .UseKestrel()
     .UseContentRoot(Directory.GetCurrentDirectory())
     .UseIISIntegration()
     .UseStartup<Startup>()
     .Build();

Website

var host = new WebHostBuilder()
     .UseUrls("http://dev.website.com:82")
     .UseKestrel()
     .UseContentRoot(Directory.GetCurrentDirectory())
     .UseIISIntegration()
     .UseStartup<Startup>()
     .Build();

And in my hosts file:

127.0.0.1 devapi.website.com
127.0.0.1 dev.website.com

If I specify the same port number (or, as a matter of fact, none at all - I want to use port 80) in Program.cs, one project will run and the other will throw

Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvException: Error -4091 EADDRINUSE address already in use

on startup.

How can I run these 2 projects simultaneously without specifying different port numbers?


Solution

  • What you're trying to do isn't possible, at least not without a workaround. Here's why:

    Binding Kestrel to a DNS name like dev.website.com doesn't make any difference to how Kestrel is listening to requests. It still has to tie up a port (80 by default). If you try to have two instances of Kestrel bind to 80, whichever one is launched first actually gets the port, and the other will error.

    Adding the names to your hosts file doesn't matter; all that does is make both devapi.website.com and dev.website.com resolve to 127.0.0.1. You only have one port 80 to bind to. The only way to run two HTTP servers on your machine is to bind them to separate ports.

    You could achieve the same functionality a slightly different way:

    1. Bind your instances of Kestrel to separate ports - 80/81, or 50080/50080, etc.
    2. Use a tunneling tool like ngrok or localtunnel to create separate tunnels that terminate at those ports.

    For example, with localtunnel,

    lt --port 50080
    lt --port 50081
    

    You'll get two URLs like https://gqgh.localtunnel.me and https://fydh.localtunnel.me, which will point to your separate Kestrel servers. They aren't on your domain (which may be a non-starter, depending on your situation), but at least they're separate public URLs.