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)); }
/// <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)); }
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); }
/// <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; } }
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); }
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); }
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); }
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); }
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()); }
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); }
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)); }
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); }