Example #1
0
        public async void ItGetsUserAgentInfo()
        {
            // Arrange
            var expectation = new Regex("{\"userAgent\":\"Microsoft-BotFramework\\/[0-9.]+\\s.*BotBuilder\\/[0-9.]+\\s+\\(.*\\)\".*}");

            // Act
            var handler  = new StreamingRequestHandler(new MockBot(), new BotFrameworkHttpAdapter(), Guid.NewGuid().ToString());
            var activity = new Schema.Activity()
            {
                Type = "message",
                Text = "received from bot",
                From = new Schema.ChannelAccount()
                {
                    Id   = "bot",
                    Name = "bot",
                },
                Conversation = new Schema.ConversationAccount(null, null, Guid.NewGuid().ToString(), null, null, null, null),
            };

            var payload             = new MemoryStream(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(activity, SerializationSettings.DefaultDeserializationSettings)));
            var fakeContentStreamId = Guid.NewGuid();
            var fakeContentStream   = new FakeContentStream(fakeContentStreamId, "application/json", payload);
            var testRequest         = new ReceiveRequest();

            testRequest.Path = "/api/version";
            testRequest.Verb = "GET";
            testRequest.Streams.Add(fakeContentStream);
            var response = await handler.ProcessRequestAsync(testRequest);

            // Assert
            Assert.Matches(expectation, response.Streams[0].Content.ReadAsStringAsync().Result);
        }
        public void NamedPipeServer_ctor_With_Empty_BaseName()
        {
            var pipeName       = Guid.NewGuid().ToString().Substring(0, 18);
            var requestHandler = new StreamingRequestHandler(new MockBot(), new BotFrameworkHttpAdapter(), pipeName);

            Assert.Throws <ArgumentNullException>(() => new NamedPipeServer(string.Empty, requestHandler));
        }
        public async Task ItGetsUserAgentInfo()
        {
            // Arrange

            // Act
            var handler  = new StreamingRequestHandler(new MockBot(), new BotFrameworkHttpAdapter(), "fakePipe");
            var activity = new Schema.Activity()
            {
                Type = "message",
                Text = "received from bot",
                From = new Schema.ChannelAccount()
                {
                    Id   = "bot",
                    Name = "bot",
                },
                Conversation = new Schema.ConversationAccount(null, null, "testconvoid", null, null, null, null),
            };

            var payload             = new MemoryStream(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(activity, SerializationSettings.DefaultDeserializationSettings)));
            var fakeContentStreamId = Guid.NewGuid();
            var fakeContentStream   = new FakeContentStream(fakeContentStreamId, "application/json", payload);
            var testRequest         = new ReceiveRequest();

            testRequest.Path = "/api/version";
            testRequest.Verb = "GET";
            testRequest.Streams.Add(fakeContentStream);
            var response = await handler.ProcessRequestAsync(testRequest);

            // Assert
            Assert.NotNull(response);
        }
        public async Task StreamingRequestHandler_ProcessRequestAsync_PostMessages_WithBotError_InternalServerError()
        {
            var bot = new MockBot()
            {
                ThrowDuringOnTurnAsync = true
            };
            var s = new StreamingRequestHandler(onTurnError: null, bot: bot, transportServer: new MockStreamingTransportServer());

            var request = new ReceiveRequest()
            {
                Verb = "POST", Path = "/api/messages"
            };

            var stream = new MemoryStream();
            var x      = new StreamWriter(stream);
            var writer = new JsonTextWriter(x);

            var serializer = new JsonSerializer();

            serializer.Serialize(writer, new Activity()
            {
                Type = "message", Text = "hi"
            });
            x.Flush();
            stream.Position = 0;

            request.Streams = new List <IContentStream>()
            {
                new MockContentStream(stream, "application/json"),
            };

            var response = await s.ProcessRequestAsync(request, null);

            Assert.AreEqual((int)HttpStatusCode.InternalServerError, response.StatusCode);
        }
            public void CreateStreamingRequestHandler(WebSocket socket, Activity activity, string audience = null)
            {
                var srh = new StreamingRequestHandler(ConnectedBot, this, socket, audience, Logger);

                // Prepare StreamingRequestHandler for BotFrameworkHttpAdapterBase.ProcessStreamingActivityAsync()
                // Add ConversationId to StreamingRequestHandler's conversations cache
                var cacheField = typeof(StreamingRequestHandler).GetField("_conversations", BindingFlags.NonPublic | BindingFlags.Instance);
                var cache      = (ConcurrentDictionary <string, DateTime>)cacheField.GetValue(srh);

                cache.TryAdd(activity.Conversation.Id, DateTime.Now);

                // Add ServiceUrl to StreamingRequestHandler
                var serviceUrlProp = typeof(StreamingRequestHandler).GetProperty("ServiceUrl");

                serviceUrlProp.DeclaringType.GetProperty("ServiceUrl");
                serviceUrlProp.GetSetMethod(true).Invoke(srh, new object[] { activity.ServiceUrl });

                if (RequestHandlers != null)
                {
                    RequestHandlers.Add(srh);
                    return;
                }

                RequestHandlers = new List <StreamingRequestHandler> {
                    srh
                };
            }
        public void CanBeConstructedWithAWebSocket()
        {
            // Act
            var handler = new StreamingRequestHandler(new MockBot(), new BotFrameworkHttpAdapter(), new FauxSock());

            // Assert
            Assert.NotNull(handler);
        }
        public void CanBeConstructedWithANamedPipe()
        {
            // Act
            var handler = new StreamingRequestHandler(new MockBot(), new BotFrameworkHttpAdapter(), "fakePipe");

            // Assert
            Assert.NotNull(handler);
        }
        public void NamedPipeServer_IsConnected()
        {
            var pipeName       = Guid.NewGuid().ToString().Substring(0, 18);
            var requestHandler = new StreamingRequestHandler(new MockBot(), new BotFrameworkHttpAdapter(), pipeName);
            var pipe           = new NamedPipeServer(pipeName, requestHandler);

            Assert.False(pipe.IsConnected);
        }
        public async void NamedPipeServer_SendAsync_With_No_Message()
        {
            var pipeName       = Guid.NewGuid().ToString().Substring(0, 18);
            var requestHandler = new StreamingRequestHandler(new MockBot(), new BotFrameworkHttpAdapter(), pipeName);
            var pipe           = new NamedPipeServer(pipeName, requestHandler);

            await Assert.ThrowsAsync <ArgumentNullException>(() => pipe.SendAsync(null));
        }
Example #10
0
        /// <summary>
        /// Process the initial request to establish a long lived connection via a streaming server.
        /// </summary>
        /// <param name="bot">The <see cref="IBot"/> instance.</param>
        /// <param name="httpRequest">The connection request.</param>
        /// <param name="httpResponse">The response sent on error or connection termination.</param>
        /// <returns>Returns on task completion.</returns>
        private async Task ConnectWebSocketAsync(IBot bot, HttpRequest httpRequest, HttpResponse httpResponse)
        {
            if (httpRequest == null)
            {
                throw new ArgumentNullException(nameof(httpRequest));
            }

            if (httpResponse == null)
            {
                throw new ArgumentNullException(nameof(httpResponse));
            }

            ConnectedBot = bot ?? throw new ArgumentNullException(nameof(bot));

            if (!httpRequest.HttpContext.WebSockets.IsWebSocketRequest)
            {
                httpRequest.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                await httpRequest.HttpContext.Response.WriteAsync("Upgrade to WebSocket is required.").ConfigureAwait(false);

                return;
            }

            var claimsIdentity = await AuthenticateRequestAsync(httpRequest).ConfigureAwait(false);

            if (claimsIdentity == null)
            {
                httpRequest.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                await httpRequest.HttpContext.Response.WriteAsync("Request authentication failed.").ConfigureAwait(false);

                return;
            }

            try
            {
                var socket = await httpRequest.HttpContext.WebSockets.AcceptWebSocketAsync().ConfigureAwait(false);

                // Set ClaimsIdentity on Adapter to enable Skills and User OAuth in WebSocket-based streaming scenarios.
                var audience = GetAudience(claimsIdentity);

                var requestHandler = new StreamingRequestHandler(bot, this, socket, audience, Logger);

                if (RequestHandlers == null)
                {
                    RequestHandlers = new List <StreamingRequestHandler>();
                }

                RequestHandlers.Add(requestHandler);

                await requestHandler.ListenAsync().ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                httpRequest.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                await httpRequest.HttpContext.Response.WriteAsync($"Unable to create transport server. Error: {ex.ToString()}").ConfigureAwait(false);

                throw;
            }
        }
        public async void NamedPipeServer_SendAsync_With_No_Connected_Client()
        {
            var pipeName       = Guid.NewGuid().ToString().Substring(0, 18);
            var requestHandler = new StreamingRequestHandler(new MockBot(), new BotFrameworkHttpAdapter(), pipeName);
            var pipe           = new NamedPipeServer(pipeName, requestHandler);
            var message        = new StreamingRequest();

            await Assert.ThrowsAsync <InvalidOperationException>(() => pipe.SendAsync(message));
        }
Example #12
0
        public void CanBeConstructedWithANamedPipe()
        {
            // Arrange

            // Act
            var handler = new StreamingRequestHandler(new MockBot(), new BotFrameworkHttpAdapter(), Guid.NewGuid().ToString());

            // Assert
            Assert.NotNull(handler);
        }
        public void CanBeConstructedWithAWebSocket(FauxSock socket, string audience)
        {
            // Arrange

            // Act
            var handler = new StreamingRequestHandler(new MockBot(), new BotFrameworkHttpAdapter(), socket, audience);

            // Assert
            Assert.NotNull(handler);
            Assert.Equal(audience, handler.Audience);
        }
        public async Task StreamingRequestHandler_ProcessRequestAsync_NoVerb_ReturnsBadRequest()
        {
            var s = new StreamingRequestHandler(onTurnError: null, bot: new MockBot(), transportServer: new MockStreamingTransportServer());

            var response = await s.ProcessRequestAsync(new ReceiveRequest()
            {
                Path = "/api/messages"
            }, null);

            Assert.AreEqual((int)HttpStatusCode.BadRequest, response.StatusCode);
        }
Example #15
0
        /// <summary>
        /// Process the initial request to establish a long lived connection via a streaming server.
        /// </summary>
        /// <param name="bot">The <see cref="IBot"/> instance.</param>
        /// <param name="httpRequest">The connection request.</param>
        /// <param name="httpResponse">The response sent on error or connection termination.</param>
        /// <returns>Returns on task completion.</returns>
        private async Task ConnectWebSocketAsync(IBot bot, HttpRequestMessage httpRequest, HttpResponseMessage httpResponse)
        {
            if (httpRequest == null)
            {
                throw new ArgumentNullException(nameof(httpRequest));
            }

            if (httpResponse == null)
            {
                throw new ArgumentNullException(nameof(httpResponse));
            }

            ConnectedBot = bot ?? throw new ArgumentNullException(nameof(bot));

            if (HttpContext.Current.IsWebSocketRequest || HttpContext.Current.IsWebSocketRequestUpgrading)
            {
                httpResponse.StatusCode = HttpStatusCode.BadRequest;
                httpResponse.Content    = new StringContent("Upgrade to WebSocket is required.");

                return;
            }

            if (!await AuthenticateRequestAsync(httpRequest, httpResponse).ConfigureAwait(false))
            {
                httpResponse.StatusCode = HttpStatusCode.Unauthorized;
                httpResponse.Content    = new StringContent("Request authentication failed.");

                return;
            }

            try
            {
                HttpContext.Current.AcceptWebSocketRequest(async context =>
                {
                    var requestHandler = new StreamingRequestHandler(bot, this, context.WebSocket, Logger);

                    if (RequestHandlers == null)
                    {
                        RequestHandlers = new List <StreamingRequestHandler>();
                    }

                    RequestHandlers.Add(requestHandler);

                    await requestHandler.ListenAsync().ConfigureAwait(false);
                });
            }
            catch (Exception ex)
            {
                httpResponse.StatusCode = HttpStatusCode.InternalServerError;
                httpResponse.Content    = new StringContent($"Unable to create transport server. Error: {ex.ToString()}");

                throw ex;
            }
        }
Example #16
0
            public StreamingActivityProcessor(AuthenticateRequestResult authenticateRequestResult, string pipeName, CloudAdapter adapter, IBot bot)
            {
                _authenticateRequestResult = authenticateRequestResult;
                _adapter = adapter;

                // Internal reuse of the existing StreamingRequestHandler class
                _requestHandler = new StreamingRequestHandler(bot, this, pipeName, _authenticateRequestResult.Audience, adapter.Logger);

                // Fix up the connector factory so connector create from it will send over this connection
                _authenticateRequestResult.ConnectorFactory = new StreamingConnectorFactory(_requestHandler);
            }
Example #17
0
        public async void DoesNotThrowExceptionIfReceiveRequestIsNull()
        {
            // Arrange
            var            handler     = new StreamingRequestHandler(new MockBot(), new BotFrameworkHttpAdapter(), Guid.NewGuid().ToString());
            ReceiveRequest testRequest = null;

            // Act
            var response = await handler.ProcessRequestAsync(testRequest);

            // Assert
            Assert.Equal(400, response.StatusCode);
        }
Example #18
0
        public async Task StreamingRequestHandler_ProcessRequestAsync_PostMessages_NoActivity_BadRequest()
        {
            var s = new StreamingRequestHandler(null, new MockBot());

            s._transportServer = new MockStreamingTransportServer();

            var response = await s.ProcessRequestAsync(new ReceiveRequest()
            {
                Verb = "POST", Path = "/api/messages"
            }, null);

            Assert.AreEqual((int)HttpStatusCode.BadRequest, response.StatusCode);
        }
Example #19
0
        public async Task StreamingRequestHandler_ProcessRequestAsync_BadPath_ReturnsNotFound()
        {
            var s = new StreamingRequestHandler(null, new MockBot());

            s._transportServer = new MockStreamingTransportServer();

            var response = await s.ProcessRequestAsync(new ReceiveRequest()
            {
                Verb = "Post", Path = "/api/messagesV3"
            }, null);

            Assert.AreEqual((int)HttpStatusCode.NotFound, response.StatusCode);
        }
Example #20
0
        public async Task StreamingRequestHandler_ProcessRequestAsync_NoPath_ReturnsBadRequest()
        {
            var s = new StreamingRequestHandler(null, new MockBot());

            s._transportServer = new MockStreamingTransportServer();

            var response = await s.ProcessRequestAsync(new ReceiveRequest()
            {
                Verb = "POST"
            }, null);

            Assert.AreEqual((int)HttpStatusCode.BadRequest, response.StatusCode);
        }
        public async Task StreamingRequestHandler_ProcessRequestAsync_GetVersion()
        {
            var s = new StreamingRequestHandler(onTurnError: null, bot: new MockBot(), transportServer: new MockStreamingTransportServer());

            var response = await s.ProcessRequestAsync(new ReceiveRequest()
            {
                Verb = "GET", Path = "/api/version"
            }, null);

            Assert.AreEqual((int)HttpStatusCode.OK, response.StatusCode);
            Assert.AreEqual(1, response.Streams.Count);
            var version = await response.Streams[0].Content.ReadAsAsync <VersionInfo>();

            Assert.IsNotNull(version);
            Assert.IsNotNull(version.UserAgent);
        }
        public void StreamingRequestHandler_UserAgent_Matches_Standard_Format()
        {
            var s = new StreamingRequestHandler(null, new MockBot(), null);

            var client          = new HttpClient();
            var userAgentHeader = client.DefaultRequestHeaders.UserAgent;

            // The Schema version is 3.1, put into the Microsoft-BotFramework header
            var botFwkProductInfo = new ProductInfoHeaderValue("Microsoft-BotFramework", "3.1");

            if (!userAgentHeader.Contains(botFwkProductInfo))
            {
                userAgentHeader.Add(botFwkProductInfo);
            }

            // Info on Streaming Extensions Version
            var streamingExtensionsVersion = new ProductInfoHeaderValue("Streaming-Extensions", "1.0");

            if (!userAgentHeader.Contains(streamingExtensionsVersion))
            {
                userAgentHeader.Add(streamingExtensionsVersion);
            }

            // The Client SDK Version
            //  https://github.com/Microsoft/botbuilder-dotnet/blob/d342cd66d159a023ac435aec0fdf791f93118f5f/doc/UserAgents.md
            var botBuilderProductInfo = new ProductInfoHeaderValue("BotBuilder", ConnectorClient.GetClientVersion(new ConnectorClient(new System.Uri("http://localhost"))));

            if (!userAgentHeader.Contains(botBuilderProductInfo))
            {
                userAgentHeader.Add(botBuilderProductInfo);
            }

            // Additional Info.
            // https://github.com/Microsoft/botbuilder-dotnet/blob/d342cd66d159a023ac435aec0fdf791f93118f5f/doc/UserAgents.md
            var userAgent = $"({ConnectorClient.GetASPNetVersion()}; {ConnectorClient.GetOsVersion()}; {ConnectorClient.GetArchitecture()})";

            if (ProductInfoHeaderValue.TryParse(userAgent, out var additionalProductInfo))
            {
                if (!userAgentHeader.Contains(additionalProductInfo))
                {
                    userAgentHeader.Add(additionalProductInfo);
                }
            }

            Assert.AreEqual(s.UserAgent, userAgentHeader.ToString());
        }
Example #23
0
        public void ThrowsIfPipeNameIsBlank()
        {
            // Arrange
            Exception result = null;

            // Act
            try
            {
                var handler = new StreamingRequestHandler(new MockBot(), new BotFrameworkHttpAdapter(), string.Empty);
            }
            catch (Exception ex)
            {
                result = ex;
            }

            // Assert
            Assert.IsType <ArgumentNullException>(result);
        }
Example #24
0
        public void ThrowsIfSocketIsNull()
        {
            // Arrange
            Exception result = null;

            // Act
            try
            {
                var handler = new StreamingRequestHandler(new MockBot(), activityProcessor: new BotFrameworkHttpAdapter(), socket: null);
            }
            catch (Exception ex)
            {
                result = ex;
            }

            // Assert
            Assert.IsType <ArgumentNullException>(result);
        }
        public async void DoesNotThrowExceptionIfReceiveRequestHasNoActivity()
        {
            // Arrange
            var handler = new StreamingRequestHandler(new MockBot(), new BotFrameworkHttpAdapter(), Guid.NewGuid().ToString());

            var payload             = new MemoryStream();
            var fakeContentStreamId = Guid.NewGuid();
            var fakeContentStream   = new FakeContentStream(fakeContentStreamId, "application/json", payload);
            var testRequest         = new ReceiveRequest
            {
                Verb = "POST",
            };

            testRequest.Streams.Add(fakeContentStream);

            // Act
            var response = await handler.ProcessRequestAsync(testRequest);

            // Assert
            Assert.Equal(400, response.StatusCode);
        }
        public async Task RequestHandlerForgetsConversations()
        {
            // Arrange
            var handler        = new StreamingRequestHandler(new MockBot(), new BotFrameworkHttpAdapter(), "fakePipe");
            var conversationId = "testconvoid";
            var membersAdded   = new List <ChannelAccount>();
            var member         = new ChannelAccount
            {
                Id   = "123",
                Name = "bot",
            };

            membersAdded.Add(member);
            var activity = new Activity()
            {
                Type         = "conversationUpdate",
                MembersAdded = membersAdded,
                Conversation = new ConversationAccount(null, null, conversationId, null, null, null, null),
            };

            var payload             = new MemoryStream(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(activity, SerializationSettings.DefaultDeserializationSettings)));
            var fakeContentStreamId = Guid.NewGuid();
            var fakeContentStream   = new FakeContentStream(fakeContentStreamId, "application/json", payload);
            var testRequest         = new ReceiveRequest
            {
                Path = $"/v3/conversations/{activity.Conversation?.Id}/activities/{activity.Id}",
                Verb = "POST",
            };

            testRequest.Streams.Add(fakeContentStream);

            // Act
            _ = await handler.ProcessRequestAsync(testRequest);

            handler.ForgetConversation(conversationId);

            // Assert
            Assert.False(handler.HasConversation(conversationId));
        }
Example #27
0
        public async void RequestHandlerAssignsAServiceUrl()
        {
            // Arrange
            var handler        = new StreamingRequestHandler(new MockBot(), new BotFrameworkHttpAdapter(), Guid.NewGuid().ToString());
            var conversationId = Guid.NewGuid().ToString();
            var serviceUrl     = "urn:FakeName:fakeProtocol://fakePath";
            var membersAdded   = new List <ChannelAccount>();
            var member         = new ChannelAccount
            {
                Id   = "123",
                Name = "bot",
            };

            membersAdded.Add(member);
            var activity = new Activity()
            {
                ServiceUrl   = serviceUrl,
                Type         = "conversationUpdate",
                MembersAdded = membersAdded,
                Conversation = new ConversationAccount(null, null, conversationId, null, null, null, null),
            };

            var payload             = new MemoryStream(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(activity, SerializationSettings.DefaultDeserializationSettings)));
            var fakeContentStreamId = Guid.NewGuid();
            var fakeContentStream   = new FakeContentStream(fakeContentStreamId, "application/json", payload);
            var testRequest         = new ReceiveRequest
            {
                Path = $"/v3/conversations/{activity.Conversation?.Id}/activities/{activity.Id}",
                Verb = "POST",
            };

            testRequest.Streams.Add(fakeContentStream);

            // Act
            _ = await handler.ProcessRequestAsync(testRequest);

            // Assert
            Assert.Equal(serviceUrl, handler.ServiceUrl);
        }
        public void StreamingRequestHandler_UserAgentSet()
        {
            var s = new StreamingRequestHandler(null, new MockBot(), null);

            Assert.IsNotNull(s.UserAgent);
        }
        public void StreamingRequestHandler_NullMiddleware_Ok()
        {
            var s = new StreamingRequestHandler(null, new MockBot(), null);

            Assert.IsNotNull(s);
        }
        public void StreamingRequestHandler_NullOnTurnError_Ok()
        {
            var s = new StreamingRequestHandler(null, new MockBot());

            Assert.IsNotNull(s);
        }