async Task <HttpRequestFeature> CreateRequestAsync(Stream stream, CancellationToken cancellationToken) { var firstLine = await stream.ReadLineAsync(cancellationToken).ConfigureAwait(false); var parts = firstLine.Split(' '); var result = new HttpRequestFeature(); result.Method = parts[0]; var uri = new Uri(parts[1], UriKind.RelativeOrAbsolute); if (!uri.IsAbsoluteUri) { uri = new Uri(_localhostUri, uri); } result.Protocol = parts[2]; for (; ;) { var line = await stream.ReadLineAsync(cancellationToken).ConfigureAwait(false); if (line.Length == 0) { break; } (var name, var values) = HttpParser.ParseHeaderNameValues(line); result.Headers.Add(name, new Microsoft.Extensions.Primitives.StringValues(values.ToArray())); } result.Scheme = uri.Scheme; result.Path = PathString.FromUriComponent(uri); result.QueryString = QueryString.FromUriComponent(uri).Value; result.Body = new BodyStream(stream, result.Headers.ContentLength); return(result); }
private async Task PopulateRequestAsync(Stream stream, IOwinRequest request, CancellationToken cancellationToken) { var firstLine = await stream.ReadLineAsync(cancellationToken).ConfigureAwait(false); var parts = firstLine.Split(' '); if (parts.Length < 3) { throw new FormatException($"{firstLine} is not a valid request status"); } _logger.WriteVerbose("Incoming request:" + firstLine); request.Method = parts[0]; request.Protocol = parts[2]; var uri = new Uri(parts[1], UriKind.RelativeOrAbsolute); if (!uri.IsAbsoluteUri) { uri = new Uri(_localhostUri, uri); } for (; ;) { var line = await stream.ReadLineAsync(cancellationToken).ConfigureAwait(false); if (line.Length == 0) { break; } _logger.WriteVerbose("Incoming header:" + line); (var name, var values) = HttpParser.ParseHeaderNameValues(line); request.Headers.Add(name, values.ToArray()); } request.Scheme = uri.Scheme; request.Path = PathString.FromUriComponent(uri); request.QueryString = QueryString.FromUriComponent(uri); long?length = null; var contentLengthValues = request.Headers.GetValues("Content-Length"); if (contentLengthValues != null && contentLengthValues.Count > 0) { length = long.Parse(contentLengthValues[0]); } request.Body = new BodyStream(stream, length); }
protected override async Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { ValidateAndNormalizeRequest(request); Stream stream = null; try { _logger.LogVerbose("HttpOS Client: Trying to connect.."); stream = await _dial.DialAsync(request, cancellationToken).ConfigureAwait(false); _logger.LogVerbose("HttpOS Client: Connected."); request.Properties.Add(UnderlyingStreamProperty, stream); _logger.LogVerbose("HttpOS Client: Writing request"); await stream.WriteClientMethodAndHeadersAsync(request, cancellationToken).ConfigureAwait(false); // as soon as headers are sent, we should begin reading the response, and send the request body concurrently // This is because if the server 404s nothing will ever read the response and it'll hang waiting // for someone to read it var writeContentTask = Task.Run(async() => // Cancel this task if server response detected { if (request.Content != null) { _logger.LogVerbose("HttpOS Client: Writing request request.Content.CopyToAsync"); await request.Content.CopyToAsync(stream).ConfigureAwait(false); } _logger.LogVerbose("HttpOS Client: stream.FlushAsync"); await stream.FlushAsync(cancellationToken).ConfigureAwait(false); _logger.LogVerbose("HttpOS Client: Finished writing request"); }, cancellationToken); var responseContent = new DialResponseContent(); var response = new HttpResponseMessage { RequestMessage = request, Content = responseContent }; _logger.LogVerbose("HttpOS Client: Waiting for response"); string statusLine = await stream.ReadLineAsync(cancellationToken).ConfigureAwait(false); _logger.LogVerbose("HttpOS Client: Read 1st response line"); ParseStatusLine(response, statusLine); _logger.LogVerbose("HttpOS Client: ParseStatusLine"); for (;;) { var line = await stream.ReadLineAsync(cancellationToken).ConfigureAwait(false); if (line.Length == 0) { _logger.LogVerbose("HttpOS Client: Found empty line, end of response headers"); break; } try { _logger.LogVerbose("HttpOS Client: Parsing line:" + line); (var name, var value) = HttpParser.ParseHeaderNameValues(line); if (!response.Headers.TryAddWithoutValidation(name, value)) { response.Content.Headers.TryAddWithoutValidation(name, value); } } catch (FormatException ex) { throw new HttpRequestException("Error parsing header", ex); } } _logger.LogVerbose("HttpOS Client: Finished reading response header lines"); responseContent.SetContent( new BodyStream(stream, response.Content.Headers.ContentLength, closeOnReachEnd: true), response.Content.Headers.ContentLength); return(response); } catch (TimeoutException) { _logger.LogWarning("HttpOS Client: connection timed out."); stream?.Dispose(); throw; } catch (Exception e) { _logger.LogError("HttpOS Client: Exception:" + e.Message); stream?.Dispose(); throw; } }