private async Task ProcessSend(HttpContext context) { var connection = await GetConnectionAsync(context); if (connection == null) { // No such connection, GetConnection already set the response status code return; } context.Response.ContentType = "text/plain"; var transport = (TransportType?)connection.Items[ConnectionMetadataNames.Transport]; if (transport == TransportType.WebSockets) { Log.PostNotAllowedForWebSockets(_logger); context.Response.StatusCode = StatusCodes.Status405MethodNotAllowed; await context.Response.WriteAsync("POST requests are not allowed for WebSocket connections."); return; } // Until the parsers are incremental, we buffer the entire request body before // flushing the buffer. Using CopyToAsync allows us to avoid allocating a single giant // buffer before writing. var pipeWriterStream = new PipeWriterStream(connection.Application.Output); await context.Request.Body.CopyToAsync(pipeWriterStream); Log.ReceivedBytes(_logger, pipeWriterStream.Length); await connection.Application.Output.FlushAsync(); }
private async Task ProcessSend(HttpContext context, HttpConnectionOptions options) { var connection = await GetConnectionAsync(context, options); if (connection == null) { // No such connection, GetConnection already set the response status code return; } context.Response.ContentType = "text/plain"; var transport = (TransportType?)connection.Items[ConnectionMetadataNames.Transport]; if (transport == TransportType.WebSockets) { Log.PostNotAllowedForWebSockets(_logger); context.Response.StatusCode = StatusCodes.Status405MethodNotAllowed; await context.Response.WriteAsync("POST requests are not allowed for WebSocket connections."); return; } var pipeWriterStream = new PipeWriterStream(connection.Application.Output); await context.Request.Body.CopyToAsync(pipeWriterStream); Log.ReceivedBytes(_logger, pipeWriterStream.Length); }
public async Task WritingToPipeStreamWritesToUnderlyingPipeWriter(WriteAsyncDelegate writeAsync) { byte[] helloBytes = "Hello World" u8.ToArray(); var pipe = new Pipe(); var stream = new PipeWriterStream(pipe.Writer, leaveOpen: false); await writeAsync(stream, helloBytes); ReadResult result = await pipe.Reader.ReadAsync(); Assert.Equal(helloBytes, result.Buffer.ToArray()); pipe.Reader.Complete(); pipe.Writer.Complete(); }
private async Task Poll(Uri pollUrl, CancellationToken cancellationToken) { Log.StartReceive(_logger); try { while (!cancellationToken.IsCancellationRequested) { var request = new HttpRequestMessage(HttpMethod.Get, pollUrl); SendUtils.PrepareHttpRequest(request, _httpOptions); HttpResponseMessage response; try { response = await _httpClient.SendAsync(request, cancellationToken); } catch (OperationCanceledException) { // SendAsync will throw the OperationCanceledException if the passed cancellationToken is canceled // or if the http request times out due to HttpClient.Timeout expiring. In the latter case we // just want to start a new poll. continue; } response.EnsureSuccessStatusCode(); if (response.StatusCode == HttpStatusCode.NoContent || cancellationToken.IsCancellationRequested) { Log.ClosingConnection(_logger); // Transport closed or polling stopped, we're done break; } else { Log.ReceivedMessages(_logger); var stream = new PipeWriterStream(_application.Output); await response.Content.CopyToAsync(stream); await _application.Output.FlushAsync(); } } } catch (OperationCanceledException) { // transport is being closed Log.ReceiveCanceled(_logger); } catch (Exception ex) { Log.ErrorPolling(_logger, pollUrl, ex); throw; } finally { // Make sure the send loop is terminated _transportCts.Cancel(); Log.ReceiveStopped(_logger); } }
private async Task Poll(Uri pollUrl, CancellationToken cancellationToken) { Log.StartReceive(_logger); // Allocate this once for the duration of the transport so we can continuously write to it var applicationStream = new PipeWriterStream(_application.Output); try { while (!cancellationToken.IsCancellationRequested) { var request = new HttpRequestMessage(HttpMethod.Get, pollUrl); HttpResponseMessage response; try { response = await _httpClient.SendAsync(request, cancellationToken); } catch (OperationCanceledException) { // SendAsync will throw the OperationCanceledException if the passed cancellationToken is canceled // or if the http request times out due to HttpClient.Timeout expiring. In the latter case we // just want to start a new poll. continue; } catch (WebException ex) when(ex.Status == WebExceptionStatus.RequestCanceled) { // SendAsync on .NET Framework doesn't reliably throw OperationCanceledException. // Catch the WebException and test it. // https://github.com/dotnet/corefx/issues/26335 continue; } Log.PollResponseReceived(_logger, response); response.EnsureSuccessStatusCode(); if (response.StatusCode == HttpStatusCode.NoContent || cancellationToken.IsCancellationRequested) { Log.ClosingConnection(_logger); // Transport closed or polling stopped, we're done break; } else { Log.ReceivedMessages(_logger); await response.Content.CopyToAsync(applicationStream); var flushResult = await _application.Output.FlushAsync(); // We canceled in the middle of applying back pressure // or if the consumer is done if (flushResult.IsCanceled || flushResult.IsCompleted) { break; } } } } catch (OperationCanceledException) { // transport is being closed Log.ReceiveCanceled(_logger); } catch (Exception ex) { Log.ErrorPolling(_logger, pollUrl, ex); _error = ex; } finally { _application.Output.Complete(_error); Log.ReceiveStopped(_logger); } }
private async Task Poll(Uri pollUrl, CancellationToken cancellationToken) { Log.StartReceive(_logger); try { while (!cancellationToken.IsCancellationRequested) { var request = new HttpRequestMessage(HttpMethod.Get, pollUrl); HttpResponseMessage response; try { response = await _httpClient.SendAsync(request, cancellationToken); } catch (OperationCanceledException) { // SendAsync will throw the OperationCanceledException if the passed cancellationToken is canceled // or if the http request times out due to HttpClient.Timeout expiring. In the latter case we // just want to start a new poll. continue; } Log.PollResponseReceived(_logger, response); response.EnsureSuccessStatusCode(); if (response.StatusCode == HttpStatusCode.NoContent || cancellationToken.IsCancellationRequested) { Log.ClosingConnection(_logger); // Transport closed or polling stopped, we're done break; } else { Log.ReceivedMessages(_logger); var stream = new PipeWriterStream(_application.Output); await response.Content.CopyToAsync(stream); var flushResult = await _application.Output.FlushAsync(); // We canceled in the middle of applying back pressure // or if the consumer is done if (flushResult.IsCanceled || flushResult.IsCompleted) { break; } } } } catch (OperationCanceledException) { // transport is being closed Log.ReceiveCanceled(_logger); } catch (Exception ex) { Log.ErrorPolling(_logger, pollUrl, ex); _error = ex; } finally { _application.Output.Complete(_error); Log.ReceiveStopped(_logger); } }