Пример #1
0
        private HttpResponse SendRequest(HttpMethod method, Uri address,
            HttpContent content, bool reconnection = false)
        {
            _content = content;

            if (_tcpClient != null &&
                !_response.MessageBodyLoaded && !_response.HasError)
            {
                try
                {
                    _response.None();
                }
                catch (HttpException)
                {
                    Dispose();
                }
            }

            bool createdNewConnection = false;

            ProxyClient proxy = GetProxy();

            // Если нужно создать новое подключение.
            if (_tcpClient == null || Address.Port != address.Port ||
                !Address.Host.Equals(address.Host, StringComparison.OrdinalIgnoreCase) ||
                !Address.Scheme.Equals(address.Scheme, StringComparison.OrdinalIgnoreCase) ||
                _response.HasError || _currentProxy != proxy)
            {
                Address = address;
                _currentProxy = proxy;

                Dispose();
                CreateConnection();

                createdNewConnection = true;
            }
            else
            {
                Address = address;
            }

            #region Отправка запроса

            try
            {
                long contentLength = 0;
                string contentType = string.Empty;
                bool canContainsRequestBody = CanContainsRequestBody(method);

                if (canContainsRequestBody && _content != null)
                {
                    contentType = _content.ContentType;
                    contentLength = _content.CalculateContentLength();
                }

                string startingLine = GenerateStartingLine(method);
                string headers = GenerateHeaders(method, contentLength, contentType);

                byte[] startingLineBytes = Encoding.ASCII.GetBytes(startingLine);
                byte[] headersBytes = Encoding.ASCII.GetBytes(headers);

                _bytesSent = 0;
                _totalBytesSent = startingLineBytes.Length + headersBytes.Length + contentLength;

                _clientStream.Write(startingLineBytes, 0, startingLineBytes.Length);
                _clientStream.Write(headersBytes, 0, headersBytes.Length);

                bool hasRequestBody = (_content != null && contentLength > 0);

                // Отправляем тело запроса, если оно не присутствует.
                if (hasRequestBody)
                {
                    _content.WriteTo(_clientStream);
                }
            }
            catch (SecurityException ex)
            {
                throw NewHttpException(Resources.HttpException_FailedSendRequest, ex, HttpExceptionStatus.SendFailure);
            }
            catch (IOException ex)
            {
                // Если это не первый запрос и включены постоянные соединения и до этого не было переподключения,
                // то пробуем заново отправить запрос.
                if (!createdNewConnection && KeepAlive && !reconnection)
                {
                    Dispose();
                    return SendRequest(method, address, content, true);
                }

                throw NewHttpException(Resources.HttpException_FailedSendRequest, ex, HttpExceptionStatus.SendFailure);
            }

            #endregion

            #region Загрузка ответа

            try
            {
                _canReportBytesReceived = false;

                _bytesReceived = 0;
                _totalBytesReceived = _response.LoadResponse(method);

                _canReportBytesReceived = true;
            }
            catch (HttpException ex)
            {
                // Если был получен пустой ответ и до этого не было переподключения или
                // если это не первый запрос и включены постоянные соединения и до этого не было переподключения,
                // то пробуем заново отправить запрос.
                if ((ex.EmptyMessageBody && !reconnection) ||
                    (!createdNewConnection && KeepAlive && !reconnection))
                {
                    Dispose();
                    return SendRequest(method, address, content, true);
                }

                throw;
            }

            #endregion

            #region Проверка кода ответа

            if (!IgnoreProtocolErrors)
            {
                int statusCodeNum = (int)_response.StatusCode;

                if (statusCodeNum >= 400 && statusCodeNum < 500)
                {
                    throw new HttpException(string.Format(
                        Resources.HttpException_ClientError, statusCodeNum),
                        HttpExceptionStatus.ProtocolError, _response.StatusCode);
                }
                else if (statusCodeNum >= 500)
                {
                    throw new HttpException(string.Format(
                        Resources.HttpException_SeverError, statusCodeNum),
                        HttpExceptionStatus.ProtocolError, _response.StatusCode);
                }
            }

            #endregion

            #region Переадресация

            if (AllowAutoRedirect && _response.HasRedirect)
            {
                if (++_redirectionCount > _maximumAutomaticRedirections)
                {
                    throw NewHttpException(Resources.HttpException_LimitRedirections);
                }

                ClearRequestData();

                return SendRequest(HttpMethod.GET, _response.RedirectAddress, null);
            }

            _redirectionCount = 0;

            #endregion

            return _response;
        }
Пример #2
0
        private void ClearRequestData()
        {
            _content = null;

            _addedUrlParams = null;
            _addedParams = null;
            _addedMultipartContent = null;
            _addedHeaders = null;
        }
Пример #3
0
        /// <summary>
        /// Отправляет запрос HTTP-серверу.
        /// </summary>
        /// <param name="method">HTTP-метод запроса.</param>
        /// <param name="address">Адрес интернет-ресурса.</param>
        /// <param name="content">Контент, отправляемый HTTP-серверу, или значение <see langword="null"/>.</param>
        /// <returns>Объект, предназначенный для загрузки ответа от HTTP-сервера.</returns>
        /// <exception cref="System.ArgumentNullException">Значение параметра <paramref name="address"/> равно <see langword="null"/>.</exception>
        /// <exception cref="xNet.Net.HttpException">Ошибка при работе с HTTP-протоколом.</exception>
        public HttpResponse Raw(HttpMethod method, Uri address, HttpContent content = null)
        {
            #region Проверка параметров

            if (address == null)
            {
                throw new ArgumentNullException("address");
            }

            #endregion

            if (!address.IsAbsoluteUri)
            {
                address = GetRequestAddress(BaseAddress, address);
            }
            
            if (_addedUrlParams != null)
            {
                var uriBuilder = new UriBuilder(address);
                uriBuilder.Query = Http.ToQueryString(_addedUrlParams, true);

                address = uriBuilder.Uri;
            }

            if (content == null)
            {
                if (_addedParams != null)
                {
                    content = new FormUrlEncodedContent(_addedParams, false, CharacterSet);
                }
                else if (_addedMultipartContent != null)
                {
                    content = _addedMultipartContent;
                }
            }

            try
            {
                return SendRequest(method, address, content);
            }
            finally
            {
                if (content != null)
                {
                    content.Dispose();
                }

                ClearRequestData();
            }
        }
Пример #4
0
        /// <summary>
        /// Отправляет запрос HTTP-серверу.
        /// </summary>
        /// <param name="method">HTTP-метод запроса.</param>
        /// <param name="address">Адрес интернет-ресурса.</param>
        /// <param name="content">Контент, отправляемый HTTP-серверу, или значение <see langword="null"/>.</param>
        /// <returns>Объект, предназначенный для загрузки ответа от HTTP-сервера.</returns>
        /// <exception cref="System.ArgumentNullException">Значение параметра <paramref name="address"/> равно <see langword="null"/>.</exception>
        /// <exception cref="System.ArgumentException">Значение параметра <paramref name="address"/> является пустой строкой.</exception>
        /// <exception cref="xNet.Net.HttpException">Ошибка при работе с HTTP-протоколом.</exception>
        public HttpResponse Raw(HttpMethod method, string address, HttpContent content = null)
        {
            #region Проверка параметров

            if (address == null)
            {
                throw new ArgumentNullException("address");
            }

            if (address.Length == 0)
            {
                throw ExceptionHelper.EmptyString("address");
            }

            #endregion

            var uri = new Uri(address, UriKind.RelativeOrAbsolute);

            return Raw(method, uri, content);
        }
Пример #5
0
        /// <summary>
        /// Отправляет POST-запрос HTTP-серверу.
        /// </summary>
        /// <param name="address">Адрес интернет-ресурса.</param>
        /// <param name="content">Контент, отправляемый HTTP-серверу.</param>
        /// <returns>Объект, предназначенный для загрузки ответа от HTTP-сервера.</returns>
        /// <exception cref="System.ArgumentNullException">
        /// Значение параметра <paramref name="address"/> равно <see langword="null"/>.
        /// -или-
        /// Значение параметра <paramref name="content"/> равно <see langword="null"/>.
        /// </exception>
        /// <exception cref="xNet.Net.HttpException">Ошибка при работе с HTTP-протоколом.</exception>
        public HttpResponse Post(Uri address, HttpContent content)
        {
            #region Проверка параметров

            if (content == null)
            {
                throw new ArgumentNullException("content");
            }

            #endregion

            return Raw(HttpMethod.POST, address, content);
        }
Пример #6
0
        private void ClearRequestData()
        {
            _content = null;

            _temporaryUrlParams = null;
            _temporaryParams = null;
            _temporaryMultipartContent = null;
            _temporaryHeaders = null;
        }
Пример #7
0
        private HttpResponse Request(HttpMethod method, Uri address, HttpContent content)
        {
            _method = method;
            _content = content;

            CloseConnectionIfNeeded();

            var previousAddress = Address;
            Address = address;

            var createdNewConnection = false;
            try
            {
                createdNewConnection = TryCreateConnectionOrUseExisting(address, previousAddress);
            }
            catch (HttpException ex)
            {
                if (CanReconnect())
                    return ReconnectAfterFail();

                throw;
            }

            if (createdNewConnection)
                _keepAliveRequestCount = 1;
            else
                _keepAliveRequestCount++;

            #region Отправка запроса

            try
            {
                SendRequestData(method);
            }
            catch (SecurityException ex)
            {
                throw NewHttpException(Resources.HttpException_FailedSendRequest, ex, HttpExceptionStatus.SendFailure);
            }
            catch (IOException ex)
            {
                if (CanReconnect())
                    return ReconnectAfterFail();

                throw NewHttpException(Resources.HttpException_FailedSendRequest, ex, HttpExceptionStatus.SendFailure);
            }

            #endregion

            #region Загрузка заголовков ответа

            try
            {
                ReceiveResponseHeaders(method);
            }
            catch (HttpException ex)
            {
                if (CanReconnect())
                    return ReconnectAfterFail();

                // Если сервер оборвал постоянное соединение вернув пустой ответ, то пробуем подключиться заново.
                // Он мог оборвать соединение потому, что достигнуто максимально допустимое кол-во запросов или вышло время простоя.
                if (KeepAlive && !_keepAliveReconnected && !createdNewConnection && ex.EmptyMessageBody)
                    return KeepAliveReconect();

                throw;
            }

            #endregion

            _response.ReconnectCount = _reconnectCount;

            _reconnectCount = 0;
            _keepAliveReconnected = false;
            _whenConnectionIdle = DateTime.Now;

            if (!IgnoreProtocolErrors)
                CheckStatusCode(_response.StatusCode);

            #region Переадресация

            if (AllowAutoRedirect && _response.HasRedirect)
            {
                if (++_redirectionCount > _maximumAutomaticRedirections)
                    throw NewHttpException(Resources.HttpException_LimitRedirections);

                ClearRequestData();
                return Request(HttpMethod.GET, _response.RedirectAddress, null);
            }

            _redirectionCount = 0;

            #endregion

            return _response;
        }