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; }
private void ClearRequestData() { _content = null; _addedUrlParams = null; _addedParams = null; _addedMultipartContent = null; _addedHeaders = null; }
/// <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(); } }
/// <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); }
/// <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); }
private void ClearRequestData() { _content = null; _temporaryUrlParams = null; _temporaryParams = null; _temporaryMultipartContent = null; _temporaryHeaders = null; }
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; }