private RestResponse SendInternal(long contentLength, Stream stream) { RestResponse resp = SendInternalAsync(contentLength, stream, CancellationToken.None).Result; return(resp); }
private async Task <RestResponse> SendInternalAsync(long contentLength, Stream stream, CancellationToken token) { if (String.IsNullOrEmpty(Url)) { throw new ArgumentNullException(nameof(Url)); } Logger?.Invoke(_Header + Method.ToString() + " " + Url); try { #region Setup-Webrequest Logger?.Invoke(_Header + "setting up web request"); if (IgnoreCertificateErrors) { ServicePointManager.ServerCertificateValidationCallback = Validator; } ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; HttpWebRequest client = (HttpWebRequest)WebRequest.Create(Url); client.KeepAlive = false; client.Method = Method.ToString(); client.AllowAutoRedirect = true; client.Timeout = _Timeout; client.ContentLength = 0; client.ContentType = ContentType; client.UserAgent = "RestWrapper (https://www.github.com/jchristn/RestWrapper)"; #endregion #region Add-Certificate if (!String.IsNullOrEmpty(CertificateFilename)) { if (!String.IsNullOrEmpty(CertificatePassword)) { Logger?.Invoke(_Header + "adding certificate including password"); X509Certificate2 cert = new X509Certificate2(CertificateFilename, CertificatePassword); client.ClientCertificates.Add(cert); } else { Logger?.Invoke(_Header + "adding certificate without password"); X509Certificate2 cert = new X509Certificate2(CertificateFilename); client.ClientCertificates.Add(cert); } } #endregion #region Add-Headers if (Headers != null && Headers.Count > 0) { foreach (KeyValuePair <string, string> pair in Headers) { if (String.IsNullOrEmpty(pair.Key)) { continue; } if (String.IsNullOrEmpty(pair.Value)) { continue; } Logger?.Invoke(_Header + "adding header " + pair.Key + ": " + pair.Value); if (pair.Key.ToLower().Trim().Equals("accept")) { client.Accept = pair.Value; } else if (pair.Key.ToLower().Trim().Equals("close")) { // do nothing } else if (pair.Key.ToLower().Trim().Equals("connection")) { // do nothing } else if (pair.Key.ToLower().Trim().Equals("content-length")) { client.ContentLength = Convert.ToInt64(pair.Value); } else if (pair.Key.ToLower().Trim().Equals("content-type")) { client.ContentType = pair.Value; } else if (pair.Key.ToLower().Trim().Equals("date")) { client.Date = Convert.ToDateTime(pair.Value); } else if (pair.Key.ToLower().Trim().Equals("expect")) { client.Expect = pair.Value; } else if (pair.Key.ToLower().Trim().Equals("host")) { client.Host = pair.Value; } else if (pair.Key.ToLower().Trim().Equals("if-modified-since")) { client.IfModifiedSince = Convert.ToDateTime(pair.Value); } else if (pair.Key.ToLower().Trim().Equals("keep-alive")) { client.KeepAlive = Convert.ToBoolean(pair.Value); } else if (pair.Key.ToLower().Trim().Equals("proxy-connection")) { // do nothing } else if (pair.Key.ToLower().Trim().Equals("referer")) { client.Referer = pair.Value; } else if (pair.Key.ToLower().Trim().Equals("transfer-encoding")) { client.TransferEncoding = pair.Value; } else if (pair.Key.ToLower().Trim().Equals("user-agent")) { client.UserAgent = pair.Value; } else { client.Headers.Add(pair.Key, pair.Value); } } } #endregion #region Add-Auth-Info if (!String.IsNullOrEmpty(_Authorization.User)) { if (_Authorization.EncodeCredentials) { Logger?.Invoke(_Header + "adding encoded credentials for user " + _Authorization.User); string authInfo = _Authorization.User + ":" + _Authorization.Password; authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo)); client.Headers.Add("Authorization", "Basic " + authInfo); } else { Logger?.Invoke(_Header + "adding plaintext credentials for user " + _Authorization.User); client.Headers.Add("Authorization", "Basic " + _Authorization.User + ":" + _Authorization.Password); } } else if (!String.IsNullOrEmpty(_Authorization.BearerToken)) { Logger?.Invoke(_Header + "adding authorization bearer token " + _Authorization.BearerToken); client.Headers.Add("Authorization", "Bearer " + _Authorization.BearerToken); } #endregion #region Write-Request-Body-Data if (Method == HttpMethod.POST || Method == HttpMethod.PUT || Method == HttpMethod.DELETE) { if (contentLength > 0 && stream != null) { Logger?.Invoke(_Header + "reading data (" + contentLength + " bytes), writing to request"); client.ContentLength = contentLength; client.ContentType = ContentType; Stream clientStream = client.GetRequestStream(); byte[] buffer = new byte[_StreamReadBufferSize]; long bytesRemaining = contentLength; int bytesRead = 0; while (bytesRemaining > 0) { bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false); if (bytesRead > 0) { bytesRemaining -= bytesRead; await clientStream.WriteAsync(buffer, 0, bytesRead).ConfigureAwait(false); } } clientStream.Close(); Logger?.Invoke(_Header + "added " + contentLength + " bytes to request"); } } #endregion #region Submit-Request-and-Build-Response Logger?.Invoke(_Header + "submitting"); HttpWebResponse response = (HttpWebResponse)(await client.GetResponseAsync().ConfigureAwait(false)); Logger?.Invoke(_Header + "server returned status code " + (int)response.StatusCode); RestResponse ret = new RestResponse(); ret.ProtocolVersion = "HTTP/" + response.ProtocolVersion.ToString(); ret.ContentEncoding = response.ContentEncoding; ret.ContentType = response.ContentType; ret.ContentLength = response.ContentLength; ret.ResponseURI = response.ResponseUri.ToString(); ret.StatusCode = (int)response.StatusCode; ret.StatusDescription = response.StatusDescription; #endregion #region Headers Logger?.Invoke(_Header + "processing response headers"); if (response.Headers != null && response.Headers.Count > 0) { ret.Headers = new Dictionary <string, string>(); for (int i = 0; i < response.Headers.Count; i++) { string key = response.Headers.GetKey(i); string val = ""; int valCount = 0; foreach (string value in response.Headers.GetValues(i)) { if (valCount == 0) { val += value; valCount++; } else { val += "," + value; valCount++; } } Logger?.Invoke(_Header + "adding response header " + key + ": " + val); ret.Headers.Add(key, val); } } #endregion #region Payload bool contentLengthHeaderExists = false; if (ret.Headers != null && ret.Headers.Count > 0) { foreach (KeyValuePair <string, string> header in ret.Headers) { if (String.IsNullOrEmpty(header.Key)) { continue; } if (header.Key.ToLower().Equals("content-length")) { contentLengthHeaderExists = true; break; } } } if (!contentLengthHeaderExists) { Logger?.Invoke(_Header + "content-length header not supplied"); long totalBytesRead = 0; int bytesRead = 0; byte[] buffer = new byte[_StreamReadBufferSize]; MemoryStream ms = new MemoryStream(); while (true) { bytesRead = await response.GetResponseStream().ReadAsync(buffer, 0, buffer.Length, token).ConfigureAwait(false); if (bytesRead > 0) { await ms.WriteAsync(buffer, 0, bytesRead, token).ConfigureAwait(false); totalBytesRead += bytesRead; Logger?.Invoke(_Header + "read " + bytesRead + " bytes, " + totalBytesRead + " total bytes"); } else { break; } } ms.Seek(0, SeekOrigin.Begin); ret.ContentLength = totalBytesRead; ret.Data = ms; } else if (response.ContentLength > 0) { Logger?.Invoke(_Header + "attaching response stream with content length " + response.ContentLength + " bytes"); ret.ContentLength = response.ContentLength; ret.Data = response.GetResponseStream(); } else { ret.ContentLength = 0; ret.Data = null; } #endregion return(ret); } catch (TaskCanceledException) { Logger?.Invoke(_Header + "task canceled"); return(null); } catch (OperationCanceledException) { Logger?.Invoke(_Header + "operation canceled"); return(null); } catch (WebException we) { #region WebException Logger?.Invoke(_Header + "web exception: " + we.Message); RestResponse ret = new RestResponse(); ret.Headers = null; ret.ContentEncoding = null; ret.ContentType = null; ret.ContentLength = 0; ret.ResponseURI = null; ret.StatusCode = 0; ret.StatusDescription = null; ret.Data = null; HttpWebResponse exceptionResponse = we.Response as HttpWebResponse; if (exceptionResponse != null) { ret.ProtocolVersion = "HTTP/" + exceptionResponse.ProtocolVersion.ToString(); ret.ContentEncoding = exceptionResponse.ContentEncoding; ret.ContentType = exceptionResponse.ContentType; ret.ContentLength = exceptionResponse.ContentLength; ret.ResponseURI = exceptionResponse.ResponseUri.ToString(); ret.StatusCode = (int)exceptionResponse.StatusCode; ret.StatusDescription = exceptionResponse.StatusDescription; Logger?.Invoke(_Header + "server returned status code " + ret.StatusCode); if (exceptionResponse.Headers != null && exceptionResponse.Headers.Count > 0) { ret.Headers = new Dictionary <string, string>(); for (int i = 0; i < exceptionResponse.Headers.Count; i++) { string key = exceptionResponse.Headers.GetKey(i); string val = ""; int valCount = 0; foreach (string value in exceptionResponse.Headers.GetValues(i)) { if (valCount == 0) { val += value; valCount++; } else { val += "," + value; valCount++; } } Logger?.Invoke(_Header + "adding exception header " + key + ": " + val); ret.Headers.Add(key, val); } } if (exceptionResponse.ContentLength > 0) { Logger?.Invoke(_Header + "attaching exception response stream to response with content length " + exceptionResponse.ContentLength + " bytes"); ret.ContentLength = exceptionResponse.ContentLength; ret.Data = exceptionResponse.GetResponseStream(); } else { ret.ContentLength = 0; ret.Data = null; } } return(ret); #endregion } }
private RestResponse SendInternal(long contentLength, Stream stream) { RestResponse resp = SendInternalAsync(contentLength, stream).Result; return(resp); }