Beispiel #1
0
        /// <summary>
        /// Sends an HTTP request and return an HTTP response as asynchronous operation.
        /// </summary>
        /// <param name="content"></param>
        /// <param name="requestCancellationToken"></param>
        /// <returns></returns>
        public async Task<HttpResponse> SendAsync(HttpContent content, CancellationToken requestCancellationToken)
        {
            this.CheckProtocol(content != null);
            if (this.SetRequestSubmitted())
            {
                throw new InvalidOperationException("This HTTP request has been submitted.");
            }

            var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(requestCancellationToken);
            if (this.SetTimeout(linkedCts))
            {
                _requestCancellationToken = linkedCts.Token;
            }
            _submitContent = content;
            var connection = this.ServicePoint.SubmitRequest(this);
            var responseData = await this.SendRequestAsync(connection).ConfigureAwait(false);
            return new HttpResponse(_uri, _method, responseData, _automaticDecompression);
        }
Beispiel #2
0
        private async Task WriteRequestAsync(Connection connection)
        {
            this.UpdateHeaders();
            if (_httpWriteMode != HttpWriteMode.None)
            {
                if (_httpWriteMode == HttpWriteMode.Chunked)
                {
                    _headers.AddInternal(HttpHeaderNames.TransferEncoding, ChunkedHeader);
                }
                else
                {
                    if (_contentLength >= 0L)
                    {
                        _headers.SetInternal(HttpHeaderNames.ContentLength, _contentLength.ToString());
                    }
                }
                //100-continue ??
            }
            //Accept-Encoding header
            var acceptEncodingValues = this.Accept ?? string.Empty;
            if ((_automaticDecompression & DecompressionMethods.GZip) != DecompressionMethods.None && acceptEncodingValues.IndexOf(GZipHeader, StringComparison.OrdinalIgnoreCase) < 0)
            {
                if ((_automaticDecompression & DecompressionMethods.Deflate) != 0
                    && acceptEncodingValues.IndexOf(DeflateHeader, StringComparison.OrdinalIgnoreCase) < 0)
                {
                    _headers.AddInternal(HttpHeaderNames.AcceptEncoding, GZipHeader + ", " + DeflateHeader);
                }
                else
                {
                    _headers.AddInternal(HttpHeaderNames.AcceptEncoding, GZipHeader);
                }
            }
            else
            {
                if ((_automaticDecompression & DecompressionMethods.Deflate) != DecompressionMethods.None && acceptEncodingValues.IndexOf("deflate", StringComparison.OrdinalIgnoreCase) < 0)
                {
                    _headers.AddInternal(HttpHeaderNames.AcceptEncoding, DeflateHeader);
                }
            }
            if (_keepAlive)
            {
                _headers.SetInternal(HttpHeaderNames.Connection, "Keep-Alive");
            }
            else
            {
                _headers.SetInternal(HttpHeaderNames.Connection, "Close");
            }
            var requestHeadersString = _headers.ToString();
            string requestLine = null;
            if (this.UsesProxySemantics)
            {
                requestLine = this.GenerateProxyRequestLine();
            }
            else
            {
                requestLine = this.GenerateRequestLine();
            }
            // Request-Line   = Method SP Request-URI SP HTTP-Version CRLF
            // i.e. GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1\r\n

            var writeBytesCount = requestHeadersString.Length + requestLine.Length + RequestLineConstantSize;
            byte[] writeBuffer = null;
            var usePooledBuffer = false;
            var offset = 0;
            if (connection.Buffer.Length >= writeBytesCount)
            {
                writeBuffer = connection.Buffer.Array;
                offset = connection.Buffer.Offset;
                usePooledBuffer = true;
            }
            else
            {
                writeBuffer = new byte[writeBytesCount];
            }           
            offset += Encoding.ASCII.GetBytes(requestLine, 0, requestLine.Length, writeBuffer, offset);
            Buffer.BlockCopy(HttpBytes, 0, writeBuffer, offset, HttpBytes.Length);
            offset += HttpBytes.Length;
            writeBuffer[offset++] = (byte)(_version == HttpVersion.HTTP20 ? '2' : '1');
            writeBuffer[offset++] = (byte)'.';
            writeBuffer[offset++] = (byte)(_version == HttpVersion.HTTP20 ? '0' : '1');
            writeBuffer[offset++] = (byte)'\r';
            writeBuffer[offset++] = (byte)'\n';
            Encoding.UTF8.GetBytes(requestHeadersString, 0, requestHeadersString.Length, writeBuffer, offset);
            offset += requestHeadersString.Length;
            //transfer data
            var beginReadIndex = 0;
            var leftWriteBytes = writeBytesCount;
            while (leftWriteBytes > 0)
            {
                var count = Math.Min(writeBytesCount - beginReadIndex, connection.Buffer.Length);
                if (!usePooledBuffer)
                {
                    Buffer.BlockCopy(writeBuffer, beginReadIndex, connection.Buffer.Array, connection.Buffer.Offset, count); 
                }
                var writeBytes = await connection.WritePooledBufferAsync(connection.Buffer.Offset + beginReadIndex, count);          
                leftWriteBytes -= writeBytes;
                beginReadIndex += writeBytes;
            }
            if (_method.AllowRequestContent && _submitContent != null)
            {
                using (_submitContent)
                {
                    await _submitContent.CopyToAsync(new ConnectStream(connection, this));
                    _submitContent = null;
                }
            }
        }