Skip to content

Allow running two IServer implementations side by side #58288

Open

Description

Is there an existing issue for this?

  • I have searched the existing issues

Is your feature request related to a problem? Please describe the problem.

I need to create an API that will allow two types of communication, a standard way using HTTP requests and a second using AMQP messages.
I've implemented a custom IServer and I was able to plug it into the default ASP.NET Core Web API (.NET8) project using:
builder.Services.AddSingleton<IServer, RabbitMqServer>();
but this disables the default communication via HTTP.

I've tried creating a composite server using https://github.com/stop-cran/AspNetCoreExtras.Solace.Server as a reference,

public class CompositeServer(RabbitMqServer rabbitMqServer, KestrelServer kestrelServer) : IServer
{
    public IFeatureCollection Features => kestrelServer.Features;

    public async Task StartAsync<TContext>(IHttpApplication<TContext> application, CancellationToken cancellationToken) where TContext : notnull
    {
        await rabbitMqServer.StartAsync(application, cancellationToken);
        await kestrelServer.StartAsync(application, cancellationToken);
    }

    public async Task StopAsync(CancellationToken cancellationToken)
    {
        await rabbitMqServer.StopAsync(cancellationToken);
        await kestrelServer.StopAsync(cancellationToken);
    }

    public void Dispose()
    {
        rabbitMqServer.Dispose();
        kestrelServer.Dispose();
    }
}

But when I try to start project from VS I get this errors:

System.IO.IOException
  HResult=0x80131620
  Message=Failed to bind to address http://localhost:5016.
  Source=Microsoft.AspNetCore.Server.Kestrel.Core
  StackTrace:
   at Microsoft.AspNetCore.Server.Kestrel.Core.LocalhostListenOptions.<BindAsync>d__2.MoveNext() in /_/src/Servers/Kestrel/Core/src/LocalhostListenOptions.cs:line 63
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.AddressesStrategy.<BindAsync>d__3.MoveNext() in /_/src/Servers/Kestrel/Core/src/Internal/AddressBinder.cs:line 247
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.<BindAsync>d__0.MoveNext() in /_/src/Servers/Kestrel/Core/src/Internal/AddressBinder.cs:line 32
   at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.<BindAsync>d__31.MoveNext() in /_/src/Servers/Kestrel/Core/src/Internal/KestrelServerImpl.cs:line 309
   at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.<StartAsync>d__28`1.MoveNext() in /_/src/Servers/Kestrel/Core/src/Internal/KestrelServerImpl.cs:line 225
   at Tunnels.CompositeServer.<StartAsync>d__5`1.MoveNext() in C:\Users\tj\source\repos\Tunnels\Tunnels\CompositeServer.cs:line 15
   at Microsoft.AspNetCore.Hosting.GenericWebHostService.<StartAsync>d__40.MoveNext() in /_/src/Hosting/Hosting/src/GenericHost/GenericWebHostService.cs:line 161
   at Microsoft.Extensions.Hosting.Internal.Host.<<StartAsync>b__15_1>d.MoveNext() in /_/src/libraries/Microsoft.Extensions.Hosting/src/Internal/Host.cs:line 136
   at Microsoft.Extensions.Hosting.Internal.Host.<ForeachService>d__18`1.MoveNext() in /_/src/libraries/Microsoft.Extensions.Hosting/src/Internal/Host.cs:line 390
   at Microsoft.Extensions.Hosting.Internal.Host.<StartAsync>d__15.MoveNext() in /_/src/libraries/Microsoft.Extensions.Hosting/src/Internal/Host.cs:line 145
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.<RunAsync>d__4.MoveNext() in /_/src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/HostingAbstractionsHostExtensions.cs:line 67
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.<RunAsync>d__4.MoveNext() in /_/src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/HostingAbstractionsHostExtensions.cs:line 79
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost host) in /_/src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/HostingAbstractionsHostExtensions.cs:line 53
   at Tunnels.Program.Main(String[] args) in C:\Users\tj\source\repos\Tunnels\Tunnels\Program.cs:line 44

  This exception was originally thrown at this call stack:
    Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure.TransportManager.BindAsync(System.Net.EndPoint, Microsoft.AspNetCore.Connections.ConnectionDelegate, Microsoft.AspNetCore.Server.Kestrel.Core.Internal.EndpointConfig, System.Threading.CancellationToken) in TransportManager.cs
    Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.StartAsync.__OnBind|0(Microsoft.AspNetCore.Server.Kestrel.Core.ListenOptions, System.Threading.CancellationToken) in KestrelServerImpl.cs
    Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindEndpointAsync(Microsoft.AspNetCore.Server.Kestrel.Core.ListenOptions, Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBindContext, System.Threading.CancellationToken) in AddressBinder.cs
    Microsoft.AspNetCore.Server.Kestrel.Core.LocalhostListenOptions.BindAsync(Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBindContext, System.Threading.CancellationToken) in LocalhostListenOptions.cs

Inner Exception 1:
AggregateException: One or more errors occurred. (No registered IConnectionListenerFactory supports endpoint IPEndPoint: 127.0.0.1:5016) (No registered IConnectionListenerFactory supports endpoint IPEndPoint: [::1]:5016)

Inner Exception 2:
InvalidOperationException: No registered IConnectionListenerFactory supports endpoint IPEndPoint: 127.0.0.1:5016

I've tried configuring Kestrel via

builder.WebHost.ConfigureKestrel(options =>
{
    options.ListenAnyIP(5000); // Change to a different port if needed
});

but this gives me this error:

System.InvalidOperationException
  HResult=0x80131509
  Message=No registered IConnectionListenerFactory supports endpoint IPEndPoint: 0.0.0.0:5000
  Source=Microsoft.AspNetCore.Server.Kestrel.Core
  StackTrace:
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure.TransportManager.<BindAsync>d__10.MoveNext() in /_/src/Servers/Kestrel/Core/src/Internal/Infrastructure/TransportManager.cs:line 62
   at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.<>c__DisplayClass28_0`1.<<StartAsync>g__OnBind|0>d.MoveNext() in /_/src/Servers/Kestrel/Core/src/Internal/KestrelServerImpl.cs:line 199
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.<BindEndpointAsync>d__3.MoveNext() in /_/src/Servers/Kestrel/Core/src/Internal/AddressBinder.cs:line 90
   at Microsoft.AspNetCore.Server.Kestrel.Core.ListenOptions.<BindAsync>d__61.MoveNext() in /_/src/Servers/Kestrel/Core/src/ListenOptions.cs:line 224
   at Microsoft.AspNetCore.Server.Kestrel.Core.AnyIPListenOptions.<BindAsync>d__1.MoveNext() in /_/src/Servers/Kestrel/Core/src/AnyIPListenOptions.cs:line 42
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.EndpointsStrategy.<BindAsync>d__2.MoveNext() in /_/src/Servers/Kestrel/Core/src/Internal/AddressBinder.cs:line 219
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.<BindAsync>d__0.MoveNext() in /_/src/Servers/Kestrel/Core/src/Internal/AddressBinder.cs:line 32
   at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.<BindAsync>d__31.MoveNext() in /_/src/Servers/Kestrel/Core/src/Internal/KestrelServerImpl.cs:line 309
   at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.<StartAsync>d__28`1.MoveNext() in /_/src/Servers/Kestrel/Core/src/Internal/KestrelServerImpl.cs:line 225
   at Tunnels.CompositeServer.<StartAsync>d__5`1.MoveNext() in C:\Users\tj\source\repos\Tunnels\Tunnels\CompositeServer.cs:line 15
   at Microsoft.AspNetCore.Hosting.GenericWebHostService.<StartAsync>d__40.MoveNext() in /_/src/Hosting/Hosting/src/GenericHost/GenericWebHostService.cs:line 161
   at Microsoft.Extensions.Hosting.Internal.Host.<<StartAsync>b__15_1>d.MoveNext() in /_/src/libraries/Microsoft.Extensions.Hosting/src/Internal/Host.cs:line 136
   at Microsoft.Extensions.Hosting.Internal.Host.<ForeachService>d__18`1.MoveNext() in /_/src/libraries/Microsoft.Extensions.Hosting/src/Internal/Host.cs:line 390
   at Microsoft.Extensions.Hosting.Internal.Host.<StartAsync>d__15.MoveNext() in /_/src/libraries/Microsoft.Extensions.Hosting/src/Internal/Host.cs:line 145
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.<RunAsync>d__4.MoveNext() in /_/src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/HostingAbstractionsHostExtensions.cs:line 67
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.<RunAsync>d__4.MoveNext() in /_/src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/HostingAbstractionsHostExtensions.cs:line 79
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost host) in /_/src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/HostingAbstractionsHostExtensions.cs:line 53
   at Tunnels.Program.Main(String[] args) in C:\Users\tj\source\repos\Tunnels\Tunnels\Program.cs:line 49

Describe the solution you'd like

Ideally, we should be able to easily add additional IServer implementations to projects, so they can work side by side.

Additional context

I want to reuse as many features as I can, my idea is to configure authorization, cache, rate limiting, etc in my app and allow invoking requests via HTTP and AMQP.

If there is an easier way to "dispatch" a request from AMQP message and catch the response please let me know.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    Needs: Attention 👋This issue needs the attention of a contributor, typically because the OP has provided an update.area-networkingIncludes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions