Ejemplo n.º 1
0
        public async Task NonSocketRequest_AgainstDifferentRoute_IsSkipped()
        {
            bool nextCalled = false;

            Task CallNext(HttpContext context)
            {
                nextCalled = true;
                return(Task.CompletedTask);
            }

            var next = new RequestDelegate(CallNext);

            var options    = new SubscriptionServerOptions <GraphSchema>();
            var server     = new Mock <ISubscriptionServer <GraphSchema> >();
            var middleware = new DefaultGraphQLHttpSubscriptionMiddleware <GraphSchema>(
                next,
                server.Object,
                options);

            var context = new DefaultHttpContext();

            context.RequestServices = new Mock <IServiceProvider>().Object;
            context.Request.Path    = "/stuff/data";

            // not a socket request aginst the route
            // should be skipped
            await middleware.InvokeAsync(context);

            Assert.IsTrue(nextCalled);
        }
        public async Task StartConnection_OnReadClose_IfConnectionIsOpen_CloseConnection()
        {
            // set the underlying connection to not auto close when it retrieves a close message
            // from the queue, leaving it up to the apollo client to do the close
            var socketClient = new MockClientConnection(autoCloseOnReadCloseMessage: false);
            var options      = new SubscriptionServerOptions <GraphSchema>();

            var provider     = new ServiceCollection().BuildServiceProvider();
            var apolloClient = new ApolloClientProxy <GraphSchema>(
                socketClient,
                options,
                new ApolloMessageConverterFactory(),
                null,
                false);

            var eventCalled = false;

            void ConnectionClosed(object sender, EventArgs e)
            {
                eventCalled = true;
            }

            apolloClient.ConnectionClosed += ConnectionClosed;

            // execute the connection sequence
            socketClient.QueueConnectionCloseMessage();
            await apolloClient.StartConnection();

            Assert.IsTrue(eventCalled, "Connection Closed Event Handler not called");
        }
Ejemplo n.º 3
0
        public async Task SocketRequest_AgainstListeningRoute_ExceptionOnClientCreation_ResultsInBadRequest()
        {
            bool nextCalled = false;

            Task CallNext(HttpContext context)
            {
                nextCalled = true;
                return(Task.CompletedTask);
            }

            var next   = new RequestDelegate(CallNext);
            var server = new Mock <ISubscriptionServer <GraphSchema> >();

            server.Setup(x => x.RegisterNewClient(It.IsAny <IClientConnection>())).Throws(new InvalidOperationException("failed"));

            var options    = new SubscriptionServerOptions <GraphSchema>();
            var middleware = new DefaultGraphQLHttpSubscriptionMiddleware <GraphSchema>(
                next,
                server.Object,
                options);

            var context = new FakeWebSocketHttpContext();

            context.RequestServices = new Mock <IServiceProvider>().Object;
            context.Request.Path    = options.Route;

            // not a socket request aginst the route
            // next middleware component should not be invoked
            await middleware.InvokeAsync(context);

            Assert.IsFalse(nextCalled);

            Assert.AreEqual((int)HttpStatusCode.InternalServerError, context.Response.StatusCode);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="DefaultGraphQLHttpSubscriptionMiddleware{TSchema}" /> class.
 /// </summary>
 /// <param name="next">The delegate pointing to the next middleware component
 /// in the pipeline.</param>
 /// <param name="subscriptionServer">The subscription server configured for
 /// this web host.</param>
 /// <param name="options">The options.</param>
 public DefaultGraphQLHttpSubscriptionMiddleware(
     RequestDelegate next,
     ISubscriptionServer <TSchema> subscriptionServer,
     SubscriptionServerOptions <TSchema> options)
 {
     _next               = next;
     _options            = Validation.ThrowIfNullOrReturn(options, nameof(options));
     _subscriptionServer = Validation.ThrowIfNullOrReturn(subscriptionServer, nameof(subscriptionServer));
     _routePath          = Validation.ThrowIfNullOrReturn(_options.Route, nameof(_options.Route));
 }
Ejemplo n.º 5
0
        public void GeneralPropertyCheck()
        {
            // ensure no funny business with retrieving set values
            var options = new SubscriptionServerOptions <GraphSchema>();

            Assert.IsFalse(options.DisableDefaultRoute);
            options.DisableDefaultRoute = true;
            Assert.IsTrue(options.DisableDefaultRoute);

            options.Route = "bob";
            Assert.AreEqual("bob", options.Route);

            options.MessageBufferSize = 15;
            Assert.AreEqual(15, options.MessageBufferSize);
        }
Ejemplo n.º 6
0
        public void GeneralPropertyCheck()
        {
            using var restorePoint = new GraphQLProviderRestorePoint();

            GraphQLProviders.TemplateProvider = null;

            var primaryOptions      = new SchemaOptions <GraphSchema>();
            var subscriptionOptions = new SubscriptionServerOptions <GraphSchema>();

            var extension = new SubscriptionPublisherSchemaExtension <GraphSchema>();

            extension.Configure(primaryOptions);

            Assert.IsTrue(primaryOptions.DeclarationOptions.AllowedOperations.Contains(GraphCollection.Subscription));
            Assert.IsTrue(GraphQLProviders.TemplateProvider is SubscriptionEnabledTemplateProvider);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Adds subscription server support to the test server builder.
        /// </summary>
        /// <typeparam name="TSchema">The type of the schema the builder supports.</typeparam>
        /// <param name="serverBuilder">The server builder.</param>
        /// <param name="options">The options to configure the schema with.</param>
        /// <returns>TestServerBuilder&lt;TSchema&gt;.</returns>
        public static TestServerBuilder <TSchema> AddSubscriptionServer <TSchema>(
            this TestServerBuilder <TSchema> serverBuilder,
            Action <SubscriptionServerOptions <TSchema> > options = null)
            where TSchema : class, ISchema
        {
            var subscriptionsOptions = new SubscriptionServerOptions <TSchema>();

            options?.Invoke(subscriptionsOptions);

            serverBuilder.AddSchemaBuilderAction(schemaBuilder =>
            {
                DefaultSubscriptionBuilderExtensions
                .AddSubscriptionServer(schemaBuilder, options);
            });

            return(serverBuilder);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ApolloClientProxy{TSchema}" /> class.
        /// </summary>
        /// <param name="clientConnection">The underlying client connection for apollo to manage.</param>
        /// <param name="options">The options used to configure the registration.</param>
        /// <param name="messageConverter">The message converter factory that will generate
        /// json converters for the various <see cref="ApolloMessage" /> the proxy shuttles to the client.</param>
        /// <param name="logger">The logger to record client level events to, if any.</param>
        /// <param name="enableMetrics">if set to <c>true</c> any queries this client
        /// executes will have metrics attached.</param>
        public ApolloClientProxy(
            IClientConnection clientConnection,
            SubscriptionServerOptions <TSchema> options,
            ApolloMessageConverterFactory messageConverter,
            IGraphEventLogger logger = null,
            bool enableMetrics       = false)
        {
            _connection         = Validation.ThrowIfNullOrReturn(clientConnection, nameof(clientConnection));
            _options            = Validation.ThrowIfNullOrReturn(options, nameof(options));
            _messageConverter   = Validation.ThrowIfNullOrReturn(messageConverter, nameof(messageConverter));
            _reservedMessageIds = new ClientTrackedMessageIdSet();
            _subscriptions      = new ApolloSubscriptionCollection <TSchema>();
            _enableKeepAlive    = options.KeepAliveInterval != TimeSpan.Zero;

            _logger        = logger != null ? new ApolloClientEventLogger <TSchema>(this, logger) : null;
            _enableMetrics = enableMetrics;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ApolloSubscriptionServer{TSchema}" /> class.
        /// </summary>
        /// <param name="schema">The schema instance this sever will use for various comparisons.</param>
        /// <param name="options">The user configured options for this server.</param>
        /// <param name="eventRouter">The listener watching for new events that need to be communicated
        /// to clients managed by this server.</param>
        /// <param name="logger">The logger to record server events to, if any.</param>
        public ApolloSubscriptionServer(
            TSchema schema,
            SubscriptionServerOptions <TSchema> options,
            ISubscriptionEventRouter eventRouter,
            IGraphEventLogger logger = null)
        {
            _schema             = Validation.ThrowIfNullOrReturn(schema, nameof(schema));
            _serverOptions      = Validation.ThrowIfNullOrReturn(options, nameof(options));
            _eventRouter        = Validation.ThrowIfNullOrReturn(eventRouter, nameof(eventRouter));
            _clients            = new HashSet <ApolloClientProxy <TSchema> >();
            _eventSendSemaphore = new SemaphoreSlim(_serverOptions.MaxConcurrentClientNotifications);

            _logger         = logger != null ? new ApolloServerEventLogger <TSchema>(this, logger) : null;
            _subCountByName = new Dictionary <SubscriptionEventName, HashSet <ApolloClientProxy <TSchema> > >(
                SubscriptionEventNameEqualityComparer.Instance);

            this.Id = Guid.NewGuid().ToString();
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Adds a subscription server to this instance that will accept connected clients and
        /// process subscription requests from those clients. This extension will attempt to inject subscription related
        /// middleware into the primary query excution pipeline and replace it. Call this method before injecting or
        /// adding your own query execution middleware items.
        /// </summary>
        /// <typeparam name="TSchema">The type of the schema being built.</typeparam>
        /// <param name="schemaBuilder">The schema builder.</param>
        /// <param name="options">An action function to configure the subscription options.</param>
        /// <returns>ISchemaBuilder&lt;TSchema&gt;.</returns>
        public static ISchemaBuilder <TSchema> AddSubscriptionServer <TSchema>(
            this ISchemaBuilder <TSchema> schemaBuilder,
            Action <SubscriptionServerOptions <TSchema> > options = null)
            where TSchema : class, ISchema
        {
            var subscriptionsOptions = new SubscriptionServerOptions <TSchema>();

            options?.Invoke(subscriptionsOptions);

            var extension = new ApolloSubscriptionServerSchemaExtension <TSchema>(schemaBuilder, subscriptionsOptions);

            // register the default router type to the service collection
            var defaultRouter = CreateDefaultSubscriptionRouterDescriptor();

            extension.OptionalServices.Add(defaultRouter);

            schemaBuilder.Options.RegisterExtension(extension);

            return(schemaBuilder);
        }
Ejemplo n.º 11
0
        public async Task SocketRequest_AgainstListeningRoute_SocketIsInvoked()
        {
            bool nextCalled = false;

            Task CallNext(HttpContext context)
            {
                nextCalled = true;
                return(Task.CompletedTask);
            }

            var next = new RequestDelegate(CallNext);

            var connection = new Mock <ISubscriptionClientProxy>();

            connection.Setup(x => x.StartConnection()).Returns(Task.CompletedTask);

            var server = new Mock <ISubscriptionServer <GraphSchema> >();

            server.Setup(x => x.RegisterNewClient(It.IsAny <IClientConnection>())).ReturnsAsync(connection.Object);

            var options    = new SubscriptionServerOptions <GraphSchema>();
            var middleware = new DefaultGraphQLHttpSubscriptionMiddleware <GraphSchema>(
                next,
                server.Object,
                options);

            var context = new FakeWebSocketHttpContext();

            context.RequestServices = new Mock <IServiceProvider>().Object;
            context.Request.Path    = options.Route;

            // not a socket request aginst the route
            // next middleware component should not be invoked
            await middleware.InvokeAsync(context);

            Assert.IsFalse(nextCalled);
        }
Ejemplo n.º 12
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ApolloSubscriptionServerSchemaExtension{TSchema}" /> class.
 /// </summary>
 /// <param name="schemaBuilder">The schema builder created when adding graphql to the server
 /// originally.</param>
 /// <param name="options">The options.</param>
 public ApolloSubscriptionServerSchemaExtension(ISchemaBuilder <TSchema> schemaBuilder, SubscriptionServerOptions <TSchema> options)
 {
     _schemaBuilder           = Validation.ThrowIfNullOrReturn(schemaBuilder, nameof(schemaBuilder));
     this.SubscriptionOptions = Validation.ThrowIfNullOrReturn(options, nameof(options));
     this.RequiredServices    = new List <ServiceDescriptor>();
     this.OptionalServices    = new List <ServiceDescriptor>();
 }
        public void GeneralPropertyCheck()
        {
            using var restorePoint = new GraphQLProviderRestorePoint();

            GraphQLProviders.TemplateProvider = null;

            var primaryOptions      = new SchemaOptions <GraphSchema>();
            var subscriptionOptions = new SubscriptionServerOptions <GraphSchema>();

            (var builder, var queryPipeline, var fieldPipeline) = CreateSchemaBuilderMock();

            var extension = new ApolloSubscriptionServerSchemaExtension <GraphSchema>(builder.Object, subscriptionOptions);

            extension.Configure(primaryOptions);

            Assert.IsTrue(primaryOptions.DeclarationOptions.AllowedOperations.Contains(GraphCollection.Subscription));

            Assert.AreEqual(2, extension.RequiredServices.Count);
            Assert.IsNotNull(extension.RequiredServices.SingleOrDefault(x => x.ServiceType == typeof(SubscriptionServerOptions <GraphSchema>)));
            Assert.IsNotNull(extension.RequiredServices.SingleOrDefault(x => x.ServiceType == typeof(ApolloMessageConverterFactory)));

            Assert.AreEqual(1, extension.OptionalServices.Count);
            Assert.IsNotNull(extension.OptionalServices.SingleOrDefault(x => x.ServiceType == typeof(ISubscriptionServer <GraphSchema>)));

            Assert.IsTrue(GraphQLProviders.TemplateProvider is SubscriptionEnabledTemplateProvider);

            // 9 middleware components in the subscription-swapped primary query pipeline registered by type
            // 1 middleware component registered by instance
            queryPipeline.Verify(x => x.Clear());
            queryPipeline.Verify(
                x =>
                x.AddMiddleware <IGraphMiddlewareComponent <GraphQueryExecutionContext> >(
                    It.IsAny <ServiceLifetime>(),
                    It.IsAny <string>()),
                Times.Exactly(9));

            queryPipeline.Verify(
                x =>
                x.AddMiddleware(
                    It.IsAny <IGraphMiddlewareComponent <GraphQueryExecutionContext> >(),
                    It.IsAny <string>()),
                Times.Exactly(1));

            // ensur query level authorzation component was added
            queryPipeline.Verify(
                x =>
                x.AddMiddleware <AuthorizeQueryOperationMiddleware <GraphSchema> >(
                    It.IsAny <ServiceLifetime>(),
                    It.IsAny <string>()),
                Times.Exactly(1));

            // four components in the sub swaped field pipeline
            fieldPipeline.Verify(x => x.Clear());
            fieldPipeline.Verify(
                x =>
                x.AddMiddleware <IGraphMiddlewareComponent <GraphFieldExecutionContext> >(It.IsAny <ServiceLifetime>(), It.IsAny <string>()),
                Times.Exactly(4));

            // ensure field authroization component was NOT added
            // to the field pipeline
            fieldPipeline.Verify(
                x =>
                x.AddMiddleware <AuthorizeFieldMiddleware <GraphSchema> >(It.IsAny <ServiceLifetime>(), It.IsAny <string>()),
                Times.Exactly(0));
        }