예제 #1
0
        /// <summary>
        /// Maps incoming requests with the specified path to the provided connection pipeline.
        /// </summary>
        /// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add the route to.</param>
        /// <param name="pattern">The route pattern.</param>
        /// <param name="options">Options used to configure the connection.</param>
        /// <param name="configure">A callback to configure the connection.</param>
        /// <returns>An <see cref="ConnectionEndpointRouteBuilder"/> for endpoints associated with the connections.</returns>
        public static ConnectionEndpointRouteBuilder MapConnections(this IEndpointRouteBuilder endpoints, string pattern, HttpConnectionDispatcherOptions options, Action <IConnectionBuilder> configure)
        {
            var dispatcher = endpoints.ServiceProvider.GetRequiredService <HttpConnectionDispatcher>();

            var connectionBuilder = new ConnectionBuilder(endpoints.ServiceProvider);

            configure(connectionBuilder);
            var connectionDelegate = connectionBuilder.Build();

            // REVIEW: Consider expanding the internals of the dispatcher as endpoint routes instead of
            // using if statements we can let the matcher handle

            var conventionBuilders = new List <IEndpointConventionBuilder>();

            // Build the negotiate application
            var app = endpoints.CreateApplicationBuilder();

            app.UseWebSockets();
            app.Run(c => dispatcher.ExecuteNegotiateAsync(c, options));
            var negotiateHandler = app.Build();

            var negotiateBuilder = endpoints.Map(pattern + "/negotiate", negotiateHandler);

            conventionBuilders.Add(negotiateBuilder);
            // Add the negotiate metadata so this endpoint can be identified
            negotiateBuilder.WithMetadata(new NegotiateMetadata());
            negotiateBuilder.WithMetadata(options);

            // build the execute handler part of the protocol
            app = endpoints.CreateApplicationBuilder();
            app.UseWebSockets();
            app.Run(c => dispatcher.ExecuteAsync(c, options, connectionDelegate));
            var executehandler = app.Build();

            var executeBuilder = endpoints.Map(pattern, executehandler);

            conventionBuilders.Add(executeBuilder);

            var compositeConventionBuilder = new CompositeEndpointConventionBuilder(conventionBuilders);

            // Add metadata to all of Endpoints
            compositeConventionBuilder.Add(e =>
            {
                // Add the authorization data as metadata
                foreach (var data in options.AuthorizationData)
                {
                    e.Metadata.Add(data);
                }
            });

            return(new ConnectionEndpointRouteBuilder(compositeConventionBuilder));
        }
예제 #2
0
        /// <summary>
        /// Maps incoming requests with the specified path to the provided connection pipeline.
        /// </summary>
        /// <param name="endpoints">The <see cref="IEndpointBuilder"/> to add the route to.</param>
        /// <param name="pattern">The route pattern.</param>
        /// <param name="options">Options used to configure the connection.</param>
        /// <param name="configure">A callback to configure the connection.</param>
        /// <returns>An <see cref="ConnectionEndpointRouteBuilder"/> for endpoints associated with the connections.</returns>
        public static ConnectionEndpointRouteBuilder MapConnections(this IEndpointBuilder endpoints, string pattern, HttpConnectionDispatcherOptions options, Action <IConnectionBuilder> configure)
        {
            var dispatcher = endpoints.ServiceProvider.GetRequiredService(_httpConnectionDispatcherType);

            var ExecuteNegotiateAsync = (Func <HttpContext, HttpConnectionDispatcherOptions, Task>)
                                        _httpConnectionDispatcherType
                                        .GetMethod("ExecuteNegotiateAsync") !
                                        .CreateDelegate(typeof(Func <HttpContext, HttpConnectionDispatcherOptions, Task>), dispatcher);

            var ExecuteAsync = (Func <HttpContext, HttpConnectionDispatcherOptions, ConnectionDelegate, Task>)
                               _httpConnectionDispatcherType
                               .GetMethod("ExecuteAsync") !
                               .CreateDelegate(typeof(Func <HttpContext, HttpConnectionDispatcherOptions, ConnectionDelegate, Task>), dispatcher);

            var connectionBuilder = new ConnectionBuilder(endpoints.ServiceProvider);

            configure(connectionBuilder);
            var connectionDelegate = connectionBuilder.Build();

            // REVIEW: Consider expanding the internals of the dispatcher as endpoint routes instead of
            // using if statements we can let the matcher handle

            var conventionBuilders = new List <IEndpointConventionBuilder>();

            // Build the negotiate application
            var app = endpoints.CreateApplicationBuilder();

            app.UseWebSockets();
            app.Run(c => ExecuteNegotiateAsync(c, options));
            var negotiateHandler = app.Build();

            var negotiateBuilder = endpoints.MapRequestDelegate(pattern + "/negotiate", negotiateHandler);

            conventionBuilders.Add(negotiateBuilder);
            // Add the negotiate metadata so this endpoint can be identified
            negotiateBuilder.WithMetadata(new NegotiateMetadata());

            // build the execute handler part of the protocol
            app = endpoints.CreateApplicationBuilder();
            app.UseWebSockets();
            app.Run(c => ExecuteAsync(c, options, connectionDelegate));
            var executehandler = app.Build();

            var executeBuilder = endpoints.MapRequestDelegate(pattern, executehandler);

            conventionBuilders.Add(executeBuilder);

            var compositeConventionBuilder = new CompositeEndpointConventionBuilder(conventionBuilders);

            // Add metadata to all of Endpoints
            compositeConventionBuilder.Add(e =>
            {
                // Add the authorization data as metadata
                foreach (var data in options.AuthorizationData)
                {
                    e.Metadata.Add(data);
                }
            });

            return((ConnectionEndpointRouteBuilder)
                   typeof(ConnectionEndpointRouteBuilder)
                   .GetTypeInfo().DeclaredConstructors
                   .Single()
                   .Invoke(new object[] { compositeConventionBuilder }));
        }