.Net框架Owin测试服务器不适用于WebSocket

问题描述:

我的项目是Owin自托管的,它提供了Web API终结点和Web套接字终结点. 这是项目启动类中的相关配置代码 此处使用Owin WebSocket

My project is Owin self-hosted, it provides Web API endpoints and web socket endpoints. Here is the relevant config code in the project's startup class Owin WebSocket is used here

using Owin;
using Owin.WebSocket.Extensions;
public void Configuration(IAppBuilder app)
    {
        HttpConfiguration config = new HttpConfiguration();
        config.MapHttpAttributeRoutes();
        config.Routes.MapHttpRoute(
           name: "api",
           routeTemplate: "api/{version}/{controller}"
       );
        config.EnsureInitialized();
        app.MapWebSocketRoute<WebSocket>("/api/v1/socket/test");
        app.UseWebApi(config);
    }

顺利运行,启动应用程序后,我可以通过"http://{host}/api/v1/test"使用网络api.并通过以下方式使用网络套接字:"ws://{host}/api/v1/socket/test"

Works smoothly, when the app is launched I can consume the web api via "http://{host}/api/v1/test" and use the websockets by: "ws://{host}/api/v1/socket/test"

然后,我决定添加一些集成测试.我在这里使用 Owin测试服务器.在TestServer.Create中,配置是相同的:

Then I decided to add some integration tests. I use Owin Test Server here. In TestServer.Create the config is identical:

        HttpConfiguration config = new HttpConfiguration();
        config.MapHttpAttributeRoutes();
        config.Routes.MapHttpRoute(
           name: "api",
           routeTemplate: "api/{version}/{controller}"
       );
        config.EnsureInitialized();
        app.MapWebSocketRoute<WebSocket>("/api/v1/socket/test");
        app.UseWebApi(config);

api的测试方法

        var url = new UriBuilder()
        {
            Scheme = "http",
            Path = "/api/v1/test"
        }.Uri;;
        var result = client.GetAsync(url).Result;

效果很好.但是不适用于Web套接字:

Works nicely. But does not work for web socket:

       var wsUri = new UriBuilder()
        {
            Scheme = "ws",
            Path = "/api/v1/socket/test"
        }.Uri;

        //create websocket client, connect it and to server 
        var wsc = new ClientWebSocket();

        Task.Run(async () =>
        {
            await wsc.ConnectAsync(wsUri, CancellationToken.None);
            var a = wsc.State; // Here error thrown: No connection could be made because the target machine actively refused it 127.0.0.1:80
        }).GetAwaiter().GetResult();

为什么在这里No connection could be made?似乎测试服务器只能支持常规的HTTP请求,而不能支持websocket.但是在使用相同设置和框架的主应用程序中情况并非如此.我在这里想念什么?我已经摆弄了几个小时无济于事...

Why No connection could be made here? It seems like the testing server can only support regular http request not websocket. But this is not the case in the main app where the identical setting and framework is used. What am I missing here? I have been fiddling with this for hours to no avail...

找到了答案. TestServer.Create<Startup>()仅在URL不可用的内存实例中启动.但是,Web套接字客户端依靠url来工作.因此,解决方案是使用超载WebApp.Start<Startup>(Settings.WebApiUrl)(它会在您提供的网址上启动网络应用)

Found the answer. The TestServer.Create<Startup>() only starts just the in-memory instance where the url is not available. The web socket client however relies on the url to work. So the solution is to user the overload WebApp.Start<Startup>(Settings.WebApiUrl) (it starts a web app on the url you provide)

       WebApp.Start(new StartOptions("http://localhost:8989"), startup =>
        {
            startup.MapWebSocketRoute<TestConnection>();
            startup.MapWebSocketRoute<TestConnection>("/ws", sResolver);
            startup.MapWebSocketPattern<TestConnection>("/captures/(?<capture1>.+)/(?<capture2>.+)", sResolver);
        });

参考