public async Task ParseMultipleMessagesText(string message1, string message2) { using (var pipeFactory = new PipeFactory()) { var pipe = pipeFactory.Create(); // Read the first part of the message await pipe.Writer.WriteAsync(Encoding.UTF8.GetBytes(message1 + message2)); var result = await pipe.Reader.ReadAsync(); var parser = new ServerSentEventsMessageParser(); var parseResult = parser.ParseMessage(result.Buffer, out var consumed, out var examined, out var message); Assert.Equal(ServerSentEventsMessageParser.ParseResult.Completed, parseResult); Assert.Equal("foo", Encoding.UTF8.GetString(message)); Assert.Equal(consumed, result.Buffer.Move(result.Buffer.Start, message1.Length)); pipe.Reader.Advance(consumed, examined); Assert.Equal(consumed, examined); parser.Reset(); result = await pipe.Reader.ReadAsync(); parseResult = parser.ParseMessage(result.Buffer, out consumed, out examined, out message); Assert.Equal(ServerSentEventsMessageParser.ParseResult.Completed, parseResult); Assert.Equal("bar", Encoding.UTF8.GetString(message)); pipe.Reader.Advance(consumed, examined); } }
public async Task ParseMessageAcrossMultipleReadsFailure(string encodedMessagePart1, string encodedMessagePart2, string expectedMessage) { using (var pipeFactory = new PipeFactory()) { var pipe = pipeFactory.Create(); // Read the first part of the message await pipe.Writer.WriteAsync(Encoding.UTF8.GetBytes(encodedMessagePart1)); var result = await pipe.Reader.ReadAsync(); var parser = new ServerSentEventsMessageParser(); var parseResult = parser.ParseMessage(result.Buffer, out var consumed, out var examined, out var buffer); Assert.Equal(ServerSentEventsMessageParser.ParseResult.Incomplete, parseResult); pipe.Reader.Advance(consumed, examined); // Send the rest of the data and parse the complete message await pipe.Writer.WriteAsync(Encoding.UTF8.GetBytes(encodedMessagePart2)); result = await pipe.Reader.ReadAsync(); var ex = Assert.Throws <FormatException>(() => parser.ParseMessage(result.Buffer, out consumed, out examined, out buffer)); Assert.Equal(expectedMessage, ex.Message); } }
public async Task ParseMessageAcrossMultipleReadsSuccess(string[] messageParts, string expectedMessage) { using (var pipeFactory = new PipeFactory()) { var parser = new ServerSentEventsMessageParser(); var pipe = pipeFactory.Create(); byte[] message = null; ReadCursor consumed = default(ReadCursor), examined = default(ReadCursor); for (var i = 0; i < messageParts.Length; i++) { var messagePart = messageParts[i]; await pipe.Writer.WriteAsync(Encoding.UTF8.GetBytes(messagePart)); var result = await pipe.Reader.ReadAsync(); var parseResult = parser.ParseMessage(result.Buffer, out consumed, out examined, out message); pipe.Reader.Advance(consumed, examined); // parse result should be complete only after we parsed the last message part var expectedResult = i == messageParts.Length - 1 ? ServerSentEventsMessageParser.ParseResult.Completed : ServerSentEventsMessageParser.ParseResult.Incomplete; Assert.Equal(expectedResult, parseResult); } Assert.Equal(consumed, examined); var resultMessage = Encoding.UTF8.GetString(message); Assert.Equal(expectedMessage, resultMessage); } }
public void ParseSSEMessageIncompleteParseResult(string encodedMessage) { var buffer = Encoding.UTF8.GetBytes(encodedMessage); var readableBuffer = new ReadOnlySequence <byte>(buffer); var parser = new ServerSentEventsMessageParser(); var parseResult = parser.ParseMessage(readableBuffer, out var consumed, out var examined, out var message); Assert.Equal(ServerSentEventsMessageParser.ParseResult.Incomplete, parseResult); }
public void ParseSSEMessageFailureCases(string encodedMessage, string expectedExceptionMessage) { var buffer = Encoding.UTF8.GetBytes(encodedMessage); var readableBuffer = new ReadOnlySequence <byte>(buffer); var parser = new ServerSentEventsMessageParser(); var ex = Assert.Throws <FormatException>(() => { parser.ParseMessage(readableBuffer, out var consumed, out var examined, out var message); }); Assert.Equal(expectedExceptionMessage, ex.Message); }
public void ReadSingleMessage() { var buffer = new ReadOnlySequence <byte>(_sseFormattedData); if (_parser.ParseMessage(buffer, out _, out _, out _) != ServerSentEventsMessageParser.ParseResult.Completed) { throw new InvalidOperationException("Parse failed!"); } _parser.Reset(); }
public void ParseSSEMessageSuccessCases(string encodedMessage, string expectedMessage) { var buffer = Encoding.UTF8.GetBytes(encodedMessage); var readableBuffer = new ReadOnlySequence <byte>(buffer); var parser = new ServerSentEventsMessageParser(); var parseResult = parser.ParseMessage(readableBuffer, out var consumed, out var examined, out var message); Assert.Equal(ServerSentEventsMessageParser.ParseResult.Completed, parseResult); Assert.Equal(consumed, examined); var result = Encoding.UTF8.GetString(message); Assert.Equal(expectedMessage, result); }
public void ParseMessagesWithMultipleDataLines(string encodedMessage, string expectedMessage) { var buffer = Encoding.UTF8.GetBytes(encodedMessage); var readableBuffer = ReadableBuffer.Create(buffer); var parser = new ServerSentEventsMessageParser(); var parseResult = parser.ParseMessage(readableBuffer, out var consumed, out var examined, out var message); Assert.Equal(ServerSentEventsMessageParser.ParseResult.Completed, parseResult); Assert.Equal(consumed, examined); var result = Encoding.UTF8.GetString(message); Assert.Equal(expectedMessage, result); }
private async Task OpenConnection(IDuplexPipe application, Uri url, TaskCompletionSource <object> startTcs, CancellationToken cancellationToken) { Log.StartReceive(_logger); var request = new HttpRequestMessage(HttpMethod.Get, url); SendUtils.PrepareHttpRequest(request, _httpOptions); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/event-stream")); HttpResponseMessage response; try { response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken); response.EnsureSuccessStatusCode(); startTcs.TrySetResult(null); } catch (Exception ex) { Log.TransportStopping(_logger); startTcs.TrySetException(ex); return; } using (var stream = await response.Content.ReadAsStreamAsync()) { var pipeOptions = new PipeOptions(pauseWriterThreshold: 0, resumeWriterThreshold: 0); var pipelineReader = StreamPipeConnection.CreateReader(pipeOptions, stream); var readCancellationRegistration = cancellationToken.Register( reader => ((PipeReader)reader).CancelPendingRead(), pipelineReader); try { while (true) { var result = await pipelineReader.ReadAsync(); var input = result.Buffer; if (result.IsCanceled || (input.IsEmpty && result.IsCompleted)) { Log.EventStreamEnded(_logger); break; } var consumed = input.Start; var examined = input.End; try { Log.ParsingSSE(_logger, input.Length); var parseResult = _parser.ParseMessage(input, out consumed, out examined, out var buffer); switch (parseResult) { case ServerSentEventsMessageParser.ParseResult.Completed: Log.MessageToApp(_logger, buffer.Length); await _application.Output.WriteAsync(buffer); _parser.Reset(); break; case ServerSentEventsMessageParser.ParseResult.Incomplete: if (result.IsCompleted) { throw new FormatException("Incomplete message."); } break; } } finally { pipelineReader.AdvanceTo(consumed, examined); } } } catch (OperationCanceledException) { Log.ReceiveCanceled(_logger); } finally { readCancellationRegistration.Dispose(); _transportCts.Cancel(); Log.ReceiveStopped(_logger); } } }
private async Task OpenConnection(Channel <byte[], SendMessage> application, Uri url, CancellationToken cancellationToken) { _logger.StartReceive(); var request = new HttpRequestMessage(HttpMethod.Get, url); SendUtils.PrepareHttpRequest(request, _httpOptions); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/event-stream")); var response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken); var stream = await response.Content.ReadAsStreamAsync(); var pipelineReader = StreamPipeConnection.CreateReader(new PipeOptions(_memoryPool), stream); var readCancellationRegistration = cancellationToken.Register( reader => ((IPipeReader)reader).CancelPendingRead(), pipelineReader); try { while (true) { var result = await pipelineReader.ReadAsync(); var input = result.Buffer; if (result.IsCancelled || (input.IsEmpty && result.IsCompleted)) { _logger.EventStreamEnded(); break; } var consumed = input.Start; var examined = input.End; try { var parseResult = _parser.ParseMessage(input, out consumed, out examined, out var buffer); switch (parseResult) { case ServerSentEventsMessageParser.ParseResult.Completed: _application.Writer.TryWrite(buffer); _parser.Reset(); break; case ServerSentEventsMessageParser.ParseResult.Incomplete: if (result.IsCompleted) { throw new FormatException("Incomplete message."); } break; } } finally { pipelineReader.Advance(consumed, examined); } } } catch (OperationCanceledException) { _logger.ReceiveCanceled(); } finally { readCancellationRegistration.Dispose(); _transportCts.Cancel(); stream.Dispose(); _logger.ReceiveStopped(); } }