示例#1
0
        protected override async Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            ValidateAndNormalizeRequest(request);
            var stream = await _dial.DialAsync(request, cancellationToken).ConfigureAwait(false);

            request.Properties.Add(UnderlyingStreamProperty, stream);
            var headerWriter = new HttpHeaderWriter(stream, 4096);
            await headerWriter.WriteMethodAndHeadersAsync(request).ConfigureAwait(false);

            await headerWriter.FlushAsync().ConfigureAwait(false);

            if (request.Content != null)
            {
                await request.Content.CopyToAsync(stream).ConfigureAwait(false);
            }
            await stream.FlushAsync().ConfigureAwait(false);

            await((stream as IWithCloseWriteSupport)?.CloseWriteAsync() ?? Task.CompletedTask).ConfigureAwait(false);
            var responseContent = new DialResponseContent();
            var response        = new HttpResponseMessage {
                RequestMessage = request, Content = responseContent
            };
            var lineReader = new ByLineReader(stream, 4096);

            ParseStatusLine(response, await lineReader.NextLineAsync().ConfigureAwait(false));
            for (; ;)
            {
                var line = await lineReader.NextLineAsync().ConfigureAwait(false);

                if (line.Count == 0)
                {
                    break;
                }
                try
                {
                    (var name, var value) = HttpParser.ParseHeaderNameValue(line);
                    if (!response.Headers.TryAddWithoutValidation(name, value))
                    {
                        response.Content.Headers.TryAddWithoutValidation(name, value);
                    }
                }
                catch (FormatException ex)
                {
                    throw new HttpRequestException("Error parsing header", ex);
                }
            }
            responseContent.SetContent(lineReader.Remaining, stream);
            return(response);
        }
        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;
            }
        }