public override void Stop() { EventSource.OnOpen -= OnEventSourceOpen; EventSource.OnMessage -= OnEventSourceMessage; EventSource.OnError -= OnEventSourceError; EventSource.OnClosed -= OnEventSourceClosed; EventSource.Close(); EventSource = null; }
public async Task When_server_returns_HTTP_error_a_reconnect_attempt_is_made() { var messageData = "hello"; var handler = new StubMessageHandler(); handler.QueueResponse(new HttpResponseMessage(HttpStatusCode.Unauthorized)); handler.QueueStringResponse("event: put\ndata: " + messageData + "\n\n"); var evt = new EventSource(new Configuration(_uri, handler)); var receiver = new ErrorReceiver(evt); string messageReceived = null; evt.MessageReceived += (_, e) => { messageReceived = e.Message.Data; evt.Close(); }; await evt.StartAsync(); Assert.Equal(2, handler.GetRequests().Count()); Assert.NotNull(receiver.ErrorReceived); var ex = Assert.IsType <EventSourceServiceUnsuccessfulResponseException>(receiver.ErrorReceived); Assert.Equal((int)HttpStatusCode.Unauthorized, ex.StatusCode); Assert.Equal(messageData, messageReceived); }
public async Task When_a_data_only_message_SSE_is_received_then_a_message_event_is_raised() { // Arrange var sse = "data: this is a test message\n\n"; var sseData = "this is a test message"; var handler = new StubMessageHandler(); handler.QueueStringResponse(sse); var evt = new EventSource(new Configuration(_uri, handler, readTimeout: _defaultReadTimeout)); MessageEvent message = null; var wasMessageReceivedEventRaised = false; evt.MessageReceived += (_, e) => { message = e.Message; wasMessageReceivedEventRaised = true; evt.Close(); }; //// Act await evt.StartAsync(); //// Assert Assert.Equal(sseData, message?.Data); Assert.True(wasMessageReceivedEventRaised); }
public async Task When_LastEventId_is_configured_then_the_outgoing_request_contains_Last_Event_Id_header() { // Arrange var sse = ":"; var lastEventId = "10"; var handler = new StubMessageHandler(); handler.QueueStringResponse(sse); var config = new Configuration( uri: _uri, messageHandler: handler, readTimeout: _defaultReadTimeout, lastEventId: lastEventId); var evt = new EventSource(config); evt.CommentReceived += (_, e) => { evt.Close(); }; //// Act await evt.StartAsync(); var request = handler.GetRequests().First(); IEnumerable <string> headerValues; var lastEventHeaderExists = request.Headers.TryGetValues(Constants.LastEventIdHttpHeader, out headerValues); //// Assert Assert.True(lastEventHeaderExists); Assert.Equal(lastEventId, headerValues.First()); }
public async Task When_server_returns_HTTP_error_a_reconnect_attempt_is_made() { var messageData = "hello"; var handler = new StubMessageHandler(); handler.QueueResponse(StubResponse.WithStatus(HttpStatusCode.Unauthorized)); handler.QueueResponse(StubResponse.StartStream( StreamAction.Write("event: put\ndata: " + messageData + "\n\n"))); var evt = new EventSource(new Configuration(_uri, handler)); var errorReceiver = new ErrorReceiver(); evt.Error += errorReceiver; var messageReceiver = new MessageReceiver(); evt.MessageReceived += messageReceiver; evt.MessageReceived += (_, e) => evt.Close(); await evt.StartAsync(); Assert.Equal(2, handler.GetRequests().Count()); Assert.NotNull(errorReceiver.ErrorReceived); var ex = Assert.IsType <EventSourceServiceUnsuccessfulResponseException>(errorReceiver.ErrorReceived); Assert.Equal((int)HttpStatusCode.Unauthorized, ex.StatusCode); Assert.Equal(messageData, messageReceiver.RequireSingleEvent().Message.Data); }
public async Task When_an_event_message_SSE_is_received_then_a_message_event_is_raised() { // Arrange var sse = "event: put\ndata: this is a test message\n\n"; var handler = new StubMessageHandler(); handler.QueueStringResponse(sse); var evt = new EventSource(new Configuration(_uri, handler, readTimeout: _defaultReadTimeout)); var wasMessageReceivedEventRaised = false; var eventName = "message"; evt.MessageReceived += (_, e) => { eventName = e.EventName; wasMessageReceivedEventRaised = true; evt.Close(); }; //// Act await evt.StartAsync(); //// Assert Assert.Equal("put", eventName); Assert.True(wasMessageReceivedEventRaised); }
public async Task When_response_exceeds_read_timeout_then_read_timeout_exception_occurs() { TimeSpan readTimeout = TimeSpan.FromSeconds(4); TimeSpan timeToWait = readTimeout.Add(TimeSpan.FromSeconds(1)); var handler = new StubMessageHandler(); handler.QueueResponse(StubResponse.StartStream( StreamAction.Write(":\n\n").AfterDelay(timeToWait))); handler.QueueResponse(StubResponse.StartStream()); var config = new ConfigurationBuilder(_uri).MessageHandler(handler).ReadTimeout(readTimeout).Build(); var evt = new EventSource(config); var receiver = new ErrorReceiver(); evt.Error += receiver; evt.Error += (_, e) => evt.Close(); await evt.StartAsync(); Assert.NotNull(receiver.ErrorReceived); Assert.Contains(receiver.ErrorReceived.Message, Resources.EventSourceService_Read_Timeout); Assert.Equal(ReadyState.Closed, receiver.SourceStateReceived); Assert.Equal(ReadyState.Shutdown, evt.ReadyState); }
public async Task Given_bad_http_responses_then_retry_delay_durations_should_increase() { var handler = new StubMessageHandler(); var nAttempts = 2; for (int i = 0; i < nAttempts; i++) { handler.QueueResponse(StubResponse.WithIOError()); } handler.QueueResponse(StubResponse.StartStream()); var evt = new EventSource(new Configuration(_uri, handler)); var backoffs = new List <TimeSpan>(); evt.Error += (_, e) => { backoffs.Add(evt.BackOffDelay); if (backoffs.Count >= nAttempts) { evt.Close(); } }; await evt.StartAsync(); Assert.NotEmpty(backoffs); Assert.NotEqual(backoffs[0], backoffs[1]); Assert.True(backoffs[1] > backoffs[0]); }
public async Task When_an_message_SSE_contains_id_is_received_then_last_event_id_is_set() { // Arrange var sse = "id:200\nevent: put\ndata: this is a test message\n\n"; var handler = new StubMessageHandler(); handler.QueueStringResponse(sse); var evt = new EventSource(new Configuration(_uri, handler, readTimeout: _defaultReadTimeout)); MessageEvent message = null; var wasMessageReceivedEventRaised = false; evt.MessageReceived += (_, e) => { message = e.Message; wasMessageReceivedEventRaised = true; evt.Close(); }; //// Act await evt.StartAsync(); //// Assert Assert.Equal("200", message.LastEventId); Assert.True(wasMessageReceivedEventRaised); }
public async Task When_Configuration_Request_headers_are_set_then_the_outgoing_request_contains_those_same_headers() { var handler = new StubMessageHandler(); handler.QueueResponse(StubResponse.StartStream()); var headers = new Dictionary <string, string> { { "User-Agent", "mozilla" }, { "Authorization", "testing" } }; var config = new ConfigurationBuilder(_uri).MessageHandler(handler) .RequestHeaders(headers).Build(); var evt = new EventSource(config); handler.RequestReceived += (s, r) => evt.Close(); await evt.StartAsync(); var request = handler.GetRequests().First(); Assert.True(headers.All( item => request.Headers.Contains(item.Key) && request.Headers.GetValues(item.Key).Contains(item.Value) )); }
public async Task Given_content_type_not_equal_to_eventstream_when_the_http_response_is_received_then_error_event_should_occur() { var handler = new StubMessageHandler(); var response = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent("testing", System.Text.Encoding.UTF8) }; response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/html"); handler.QueueResponse(StubResponse.WithResponse(response)); var config = new Configuration(_uri, handler); var evt = new EventSource(config); var receiver = new ErrorReceiver(); evt.Error += receiver; evt.Error += (_, e) => evt.Close(); await evt.StartAsync(); Assert.NotNull(receiver.ErrorReceived); Assert.Equal(ReadyState.Closed, receiver.SourceStateReceived); Assert.Equal(ReadyState.Shutdown, evt.ReadyState); }
public async Task When_the_HttpRequest_is_sent_then_the_outgoing_request_contains_accept_header() { // Arrange var sse = ":"; var handler = new StubMessageHandler(); handler.QueueStringResponse(sse); var evt = new EventSource(new Configuration(_uri, handler, readTimeout: _defaultReadTimeout)); evt.CommentReceived += (_, e) => { evt.Close(); }; //// Act await evt.StartAsync(); var request = handler.GetRequests().First(); IEnumerable <string> headerValues; var acceptHeaderExists = request.Headers.TryGetValues(Constants.AcceptHttpHeader, out headerValues); //// Assert Assert.True(acceptHeaderExists); Assert.True(headerValues.Contains(Constants.EventStreamContentType)); }
public async Task When_reconnecting_the_outgoing_request_contains_Last_Event_Id_header() { var lastEventId = "10"; var firstResponse = $"id:{lastEventId}\nevent: put\ndata: this is a test message\n\n"; var secondResponse = $"id:20\nevent: put\ndata: this is a test message\n\n"; var handler = new StubMessageHandler(); handler.QueueResponse(StubResponse.StartStream(StreamAction.Write(firstResponse), StreamAction.CloseStream())); handler.QueueResponse(StubResponse.StartStream(StreamAction.Write(secondResponse), StreamAction.CloseStream())); var evt = new EventSource(new Configuration(_uri, handler)); var first = true; handler.RequestReceived += (s, r) => { if (first) { first = false; } else { evt.Close(); } }; await evt.StartAsync(); var requests = handler.GetRequests().ToList(); Assert.False(requests[0].Headers.Contains(Constants.LastEventIdHttpHeader)); Assert.True(requests[1].Headers.Contains(Constants.LastEventIdHttpHeader)); Assert.True(requests[1].Headers.GetValues(Constants.LastEventIdHttpHeader).Contains(lastEventId)); }
public async Task ContextChange(string newHeader) { if (_featureHost.ServerEvaluation) { if (newHeader != _xFeatureHubHeader) { _xFeatureHubHeader = newHeader; if (_eventSource == null || _eventSource.ReadyState == ReadyState.Open || _eventSource.ReadyState == ReadyState.Connecting) { _eventSource?.Close(); var promise = new TaskCompletionSource <Readyness>(); EventHandler <Readyness> handler = (sender, r) => { promise.TrySetResult(r); }; _repository.ReadynessHandler += handler; Init(); await promise.Task; _repository.ReadynessHandler -= handler; } } } else if (_eventSource == null) { Init(); } }
public async Task When_Configuration_Request_headers_are_set_then_the_outgoing_request_contains_those_same_headers() { // Arrange var sse = ":"; var handler = new StubMessageHandler(); handler.QueueStringResponse(sse); var headers = new Dictionary <string, string> { { "User-Agent", "mozilla" }, { "Authorization", "testing" } }; var config = new Configuration(_uri, handler, requestHeaders: headers, readTimeout: _defaultReadTimeout); var evt = new EventSource(config); evt.CommentReceived += (_, e) => { evt.Close(); }; //// Act await evt.StartAsync(); var request = handler.GetRequests().First(); //// Assert Assert.True(headers.All( item => request.Headers.Contains(item.Key) && request.Headers.GetValues(item.Key).Contains(item.Value) )); }
public async Task When_a_comment_SSE_is_received_then_a_comment_event_is_raised() { // Arrange var commentSent = ":"; var handler = new StubMessageHandler(); handler.QueueStringResponse(commentSent); var evt = new EventSource(new Configuration(_uri, handler, readTimeout: _defaultReadTimeout)); string commentReceived = string.Empty; var wasCommentEventRaised = false; evt.CommentReceived += (_, e) => { commentReceived = e.Comment; wasCommentEventRaised = true; evt.Close(); }; //// Act await evt.StartAsync(); //// Assert Assert.Equal(commentSent, commentReceived); Assert.True(wasCommentEventRaised); }
public void Dispose() { _parents.Remove(this); if (_eventSource != null && _eventSource.ReadyState == ReadyState.Open) { _eventSource.Close(); } }
public void HandleError(object sender, ExceptionEventArgs e) { ErrorReceived = e.Exception; SourceStateReceived = _source.ReadyState; if (CloseEventSourceOnError) { _source.Close(); } }
public void Init() { var config = new Configuration(uri: new UriBuilder(_featureHost.Url).Uri, requestHeaders: _featureHost.ServerEvaluation ? BuildContextHeader() : null); _eventSource = new EventSource(config); // _eventSource.Closed += (sender, args) => // { // Console.WriteLine("source closed\n"); // }; _eventSource.MessageReceived += (sender, args) => { SSEResultState?state; switch (args.EventName) { case "features": state = SSEResultState.Features; break; case "feature": state = SSEResultState.Feature; break; case "failure": state = SSEResultState.Failure; break; case "delete_feature": state = SSEResultState.Deletefeature; break; default: state = null; break; } // Console.WriteLine($"The state was {state} with value {args.Message.Data}\n"); if (state == null) { return; } _repository.Notify(state.Value, args.Message.Data); if (state == SSEResultState.Failure) { _eventSource.Close(); } }; _eventSource.StartAsync(); }
public async Task CustomHttpClientIsNotClosedWhenEventSourceCloses() { var handler = new StubMessageHandler(StubResponse.WithStatus(HttpStatusCode.OK)); using (var client = new HttpClient(handler)) { var es = new EventSource(Configuration.Builder(_uri).HttpClient(client).Build()); es.Close(); await client.SendAsync(new HttpRequestMessage(HttpMethod.Get, _uri)); } }
public async Task CustomHttpClientIsNotClosedWhenEventSourceCloses() { using (var server = HttpServer.Start(Handlers.Status(200))) { using (var client = new HttpClient()) { var es = new EventSource(Configuration.Builder(server.Uri).HttpClient(client).Build()); es.Close(); await client.SendAsync(new HttpRequestMessage(HttpMethod.Get, server.Uri)); } } }
public async Task Default_HTTP_method_is_get() { var handler = new StubMessageHandler(); handler.QueueStringResponse(":"); var evt = new EventSource(new Configuration(_uri, handler, readTimeout: _defaultReadTimeout)); evt.CommentReceived += (_, e) => { evt.Close(); }; await evt.StartAsync(); var request = handler.GetRequests().First(); Assert.Equal(HttpMethod.Get, request.Method); }
public async Task Default_HTTP_method_is_get() { var handler = new StubMessageHandler(); handler.QueueResponse(StubResponse.StartStream()); var evt = new EventSource(new Configuration(_uri, handler)); handler.RequestReceived += (s, r) => evt.Close(); await evt.StartAsync(); var request = handler.GetRequests().First(); Assert.Equal(HttpMethod.Get, request.Method); }
public async Task When_error_handler_closes_event_source_no_reconnect_attempt_is_made() { var handler = new StubMessageHandler(); handler.QueueResponse(StubResponse.WithStatus(HttpStatusCode.Unauthorized)); handler.QueueResponse(StubResponse.StartStream()); var evt = new EventSource(new Configuration(_uri, handler)); evt.Error += (_, e) => evt.Close(); await evt.StartAsync(); Assert.Equal(1, handler.GetRequests().Count()); }
public void Init(string url, FeatureHubRepository repository) { var config = new Configuration(uri: new UriBuilder(url).Uri); _eventSource = new EventSource(config); _eventSource.MessageReceived += (sender, args) => { // Console.WriteLine($"{args.EventName}:\n\t {args.Message.Data}"); SSEResultState?state; switch (args.EventName) { case "features": state = SSEResultState.Features; break; case "feature": state = SSEResultState.Feature; break; case "failure": state = SSEResultState.Failure; break; case "delete_feature": state = SSEResultState.Deletefeature; break; default: state = null; break; } if (state == null) { return; } repository.Notify(state.Value, args.Message.Data); if (state == SSEResultState.Failure) { _eventSource.Close(); } }; _eventSource.StartAsync(); }
public async Task HTTP_method_can_be_specified() { var handler = new StubMessageHandler(); handler.QueueResponse(StubResponse.StartStream()); var config = new ConfigurationBuilder(_uri).MessageHandler(handler) .Method(HttpMethod.Post).Build(); var evt = new EventSource(config); handler.RequestReceived += (s, r) => evt.Close(); await evt.StartAsync(); var request = handler.GetRequests().First(); Assert.Equal(HttpMethod.Post, request.Method); }
public async Task When_the_HttpRequest_is_sent_then_the_outgoing_request_contains_accept_header() { var handler = new StubMessageHandler(); handler.QueueResponse(StubResponse.StartStream()); var evt = new EventSource(new Configuration(_uri, handler)); handler.RequestReceived += (s, r) => evt.Close(); await evt.StartAsync(); var request = handler.GetRequests().First(); Assert.True(request.Headers.Contains(Constants.AcceptHttpHeader)); Assert.True(request.Headers.GetValues(Constants.AcceptHttpHeader).Contains(Constants.EventStreamContentType)); }
public async Task Timeout_does_not_cause_unobserved_exception() { TimeSpan readTimeout = TimeSpan.FromMilliseconds(10); TimeSpan timeToWait = TimeSpan.FromMilliseconds(100); var handler = new StubMessageHandler(); handler.QueueResponse(StubResponse.StartStream( StreamAction.Write(":\n\n").AfterDelay(timeToWait))); handler.QueueResponse(StubResponse.StartStream()); var config = new ConfigurationBuilder(_uri).MessageHandler(handler).ReadTimeout(readTimeout).Build(); var evt = new EventSource(config); var caughtUnobservedException = false; EventHandler <UnobservedTaskExceptionEventArgs> exceptionHandler = (object sender, UnobservedTaskExceptionEventArgs e) => { e.SetObserved(); caughtUnobservedException = true; }; TaskScheduler.UnobservedTaskException += exceptionHandler; try { evt.Error += (_, e) => evt.Close(); await evt.StartAsync(); // StartAsync has returned, meaning that the EventSource was closed by the ErrorReceiver, meaning that it // encountered a timeout. Wait a little bit longer to make sure that the stream reader task has got an // exception from the closed stream. Thread.Sleep(TimeSpan.FromMilliseconds(300)); // Force finalizer to run so that if there was an unobserved exception, it will trigger that event. GC.Collect(); GC.WaitForPendingFinalizers(); Assert.False(caughtUnobservedException); } finally { TaskScheduler.UnobservedTaskException -= exceptionHandler; } }
public async Task When_event_source_closes_do_not_dispose_configured_http_client() { var handler = new StubMessageHandler(); handler.QueueResponse(StubResponse.WithResponse(new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent("Hello") })); var client = new HttpClient(handler); var evt = new EventSource(new Configuration(_uri, httpClient: client)); evt.Close(); await client.SendAsync(new HttpRequestMessage(HttpMethod.Get, _uri)); client.Dispose(); }
public async Task When_an_event_message_SSE_is_received_then_a_message_event_is_raised() { var sse = "event: put\ndata: this is a test message\n\n"; var handler = new StubMessageHandler(); handler.QueueResponse(StubResponse.StartStream(StreamAction.Write(sse))); var evt = new EventSource(new Configuration(_uri, handler)); var m = new MessageReceiver(); evt.MessageReceived += m; evt.MessageReceived += ((_, e) => evt.Close()); await evt.StartAsync(); Assert.Equal("put", m.RequireSingleEvent().EventName); }