internal static void LogResponseDetails(FullResponse fullResponse) { Log.Debug("Response status code: {StatusCode}", fullResponse.StatusCode); Log.Debug(" Response headers: {ResponseHeaders}", fullResponse.Headers?.Select(kv => $"{kv.Key}: {kv.Value}") .Aggregate("", (str, header) => $"{str}{header}, ").TrimEnd(',', ' ')); Log.Debug(" Body size: {ResponseBodySize}", fullResponse.Body == null ? "None" : $"{fullResponse.Body.Length}"); }
public static void LogResponseDetails(this FullResponse fullResponse) { if (fullResponse is null) { Log.Debug("LogResponseDetails: fullResponse is null!"); return; } Log.Debug($"Response status code: {fullResponse.StatusCode}"); Log.Debug(" Response headers: {ResponseHeaders}", fullResponse.Headers?.Select(kv => $"{kv.Key}: {kv.Value}") .Aggregate("", (str, header) => $"{str}{header}, ").TrimEnd(',', ' ')); Log.Debug(" Body size: {ResponseBodySize}", fullResponse.Body == null ? "None" : $"{fullResponse.Body.Length}"); }
public static void LogResponseDetails(this IRestResponse restResponse) { if (restResponse is null) { Log.Debug("LogResponseDetails: restResponse is null!"); return; } var fullResponse = new FullResponse { StatusCode = restResponse.StatusCode, Headers = new Dictionary <string, string>(), Body = restResponse.Content }; fullResponse.LogResponseDetails(); }
private async Task <string> ValidatePostResponse(HttpResponseMessage response) { var fullResponse = new FullResponse { Body = await response.Content.ReadAsStringAsync(), Headers = response.Headers.ToDictionary(key => key.Key, value => value.Value.FirstOrDefault()), StatusCode = response.StatusCode }; if (!response.IsSuccessStatusCode) { throw new SafeguardDotNetException( $"Error returned from Safeguard API, Error: {fullResponse.StatusCode} {fullResponse.Body}", fullResponse.StatusCode, fullResponse.Body); } fullResponse.LogResponseDetails(); return(fullResponse.Body); }
private void ValidateGetResponse(HttpResponseMessage response) { var fullResponse = new FullResponse { Headers = response.Headers.ToDictionary(key => key.Key, value => value.Value.FirstOrDefault()), StatusCode = response.StatusCode }; // Check for 200 OK here because 204 Accepted doesn't return a stream, // better to fail in that case. if (response.StatusCode != System.Net.HttpStatusCode.OK) { fullResponse.Body = response.Content.ReadAsStringAsync().Result; throw new SafeguardDotNetException( $"Response does not indicate OK status. Error: {fullResponse.StatusCode} {fullResponse.Body}", fullResponse.StatusCode, fullResponse.Body); } fullResponse.LogResponseDetails(); }
public FullResponse InvokeMethodFull(Service service, Method method, string relativeUrl, string body = null, IDictionary <string, string> parameters = null, IDictionary <string, string> additionalHeaders = null, TimeSpan?timeout = null) { if (_disposed) { throw new ObjectDisposedException("SafeguardConnection"); } if (string.IsNullOrEmpty(relativeUrl)) { throw new ArgumentException("Parameter may not be null or empty", nameof(relativeUrl)); } var request = new RestRequest(relativeUrl, method.ConvertToRestSharpMethod()); if (!_authenticationMechanism.IsAnonymous) { if (!_authenticationMechanism.HasAccessToken()) { throw new SafeguardDotNetException("Access token is missing due to log out, you must refresh the access token to invoke a method"); } // SecureString handling here basically negates the use of a secure string anyway, but when calling a Web API // I'm not sure there is anything you can do about it. request.AddHeader("Authorization", $"Bearer {_authenticationMechanism.GetAccessToken().ToInsecureString()}"); } if (additionalHeaders != null && !additionalHeaders.ContainsKey("Accept")) { request.AddHeader("Accept", "application/json"); // Assume JSON unless specified } if (additionalHeaders != null) { foreach (var header in additionalHeaders) { request.AddHeader(header.Key, header.Value); } } if ((method == Method.Post || method == Method.Put) && body != null) { request.AddParameter("application/json", body, ParameterType.RequestBody); } else if (method == Method.Post || method == Method.Put) // have to set the Content-type header even if empty body or Safeguard chokes { request.AddHeader("Content-type", "application/json"); } if (parameters != null) { foreach (var param in parameters) { request.AddParameter(param.Key, param.Value, ParameterType.QueryString); } } if (timeout.HasValue) { request.Timeout = (timeout.Value.TotalMilliseconds > int.MaxValue) ? int.MaxValue : (int)timeout.Value.TotalMilliseconds; } var client = GetClientForService(service); client.LogRequestDetails(request, parameters, additionalHeaders); var response = client.Execute(request); Log.Debug(" Body size: {RequestBodySize}", body == null ? "None" : $"{body.Length}"); if (response.ResponseStatus != ResponseStatus.Completed) { throw new SafeguardDotNetException($"Unable to connect to web service {client.BaseUrl}, Error: " + response.ErrorMessage); } if (!response.IsSuccessful) { throw new SafeguardDotNetException( "Error returned from Safeguard API, Error: " + $"{response.StatusCode} {response.Content}", response.StatusCode, response.Content); } var fullResponse = new FullResponse { StatusCode = response.StatusCode, Headers = new Dictionary <string, string>(), Body = response.Content }; foreach (var header in response.Headers) { if (header.Name != null) { fullResponse.Headers.Add(header.Name, header.Value?.ToString()); } } fullResponse.LogResponseDetails(); return(fullResponse); }
public FullResponse InvokeMethodFull(Service service, Method method, string relativeUrl, string body = null, IDictionary <string, string> parameters = null, IDictionary <string, string> additionalHeaders = null) { if (_disposed) { throw new ObjectDisposedException("SafeguardConnection"); } if (string.IsNullOrEmpty(relativeUrl)) { throw new ArgumentException("Parameter may not be null or empty", nameof(relativeUrl)); } var request = new RestRequest(relativeUrl, method.ConvertToRestSharpMethod()); if (!_authenticationMechanism.IsAnonymous) { if (!_authenticationMechanism.HasAccessToken()) { throw new SafeguardDotNetException("Access token is missing due to log out, you must refresh the access token to invoke a method"); } // SecureString handling here basically negates the use of a secure string anyway, but when calling a Web API // I'm not sure there is anything you can do about it. request.AddHeader("Authorization", $"Bearer {_authenticationMechanism.GetAccessToken().ToInsecureString()}"); } if (additionalHeaders != null && !additionalHeaders.ContainsKey("Accept")) { request.AddHeader("Accept", "application/json"); // Assume JSON unless specified } if (additionalHeaders != null) { foreach (var header in additionalHeaders) { request.AddHeader(header.Key, header.Value); } } if (method == Method.Post || method == Method.Put) { request.AddParameter("application/json", body, ParameterType.RequestBody); } if (parameters != null) { foreach (var param in parameters) { request.AddParameter(param.Key, param.Value, ParameterType.QueryString); } } var client = GetClientForService(service); Log.Debug("Invoking method: {Method} {Endpoint}", method.ToString().ToUpper(), client.BaseUrl + $"/{relativeUrl}"); Log.Debug(" Query parameters: {QueryParameters}", parameters?.Select(kv => $"{kv.Key}={kv.Value}").Aggregate("", (str, param) => $"{str}{param}&") .TrimEnd('&') ?? "None"); Log.Debug(" Additional headers: {AdditionalHeaders}", additionalHeaders?.Select(kv => $"{kv.Key}: {kv.Value}") .Aggregate("", (str, header) => $"{str}{header}, ").TrimEnd(',', ' ') ?? "None"); var response = client.Execute(request); Log.Debug(" Body size: {RequestBodySize}", body == null ? "None" : $"{body.Length}"); if (response.ResponseStatus != ResponseStatus.Completed) { throw new SafeguardDotNetException($"Unable to connect to web service {client.BaseUrl}, Error: " + response.ErrorMessage); } if (!response.IsSuccessful) { throw new SafeguardDotNetException( "Error returned from Safeguard API, Error: " + $"{response.StatusCode} {response.Content}", response.StatusCode, response.Content); } var fullResponse = new FullResponse { StatusCode = response.StatusCode, Headers = new Dictionary <string, string>(), Body = response.Content }; if (response.Headers != null) { foreach (var header in response.Headers) { fullResponse.Headers.Add(header.Name, header.Value?.ToString()); } } Log.Debug("Response status code: {StatusCode}", fullResponse.StatusCode); Log.Debug(" Response headers: {ResponseHeaders}", fullResponse.Headers?.Select(kv => $"{kv.Key}: {kv.Value}") .Aggregate("", (str, header) => $"{str}{header}, ").TrimEnd(',', ' ')); Log.Debug(" Body size: {ResponseBodySize}", fullResponse.Body == null ? "None" : $"{fullResponse.Body.Length}"); return(fullResponse); }
public async Task <string> UploadAsync(Service service, string relativeUrl, Stream stream, IProgress <TransferProgress> progress = null, IDictionary <string, string> parameters = null, IDictionary <string, string> additionalHeaders = null, CancellationToken?cancellationToken = null) { if (_isDisposed()) { throw new ObjectDisposedException("SafeguardConnection"); } if (string.IsNullOrEmpty(relativeUrl)) { throw new ArgumentException("Parameter may not be null or empty", nameof(relativeUrl)); } var token = cancellationToken ?? CancellationToken.None; var uri = $"https://{_authenticationMechanism.NetworkAddress}/service/{service}/v{_authenticationMechanism.ApiVersion}/{relativeUrl}"; if (parameters != null) { uri = QueryHelpers.AddQueryString(uri, parameters); } using (var request = new HttpRequestMessage(HttpMethod.Post, uri)) { if (!_authenticationMechanism.IsAnonymous) { if (!_authenticationMechanism.HasAccessToken()) { throw new SafeguardDotNetException("Access token is missing due to log out, you must refresh the access token to invoke a method"); } // SecureString handling here basically negates the use of a secure string anyway, but when calling a Web API // I'm not sure there is anything you can do about it. request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _authenticationMechanism.GetAccessToken().ToInsecureString()); } if (additionalHeaders != null && !additionalHeaders.ContainsKey("Accept")) { request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); } if (additionalHeaders != null) { foreach (var header in additionalHeaders) { request.Headers.Add(header.Key, header.Value); } } SafeguardConnection.LogRequestDetails(Method.Post, new Uri(uri), parameters, additionalHeaders); EventHandler <HttpProgressEventArgs> progressHandlerFunc = null; using (var content = new StreamContent(stream, DefaultBufferSize)) { request.Content = content; request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); if (progress != null) { progressHandlerFunc = (sender, args) => { var uploadProgress = new TransferProgress { BytesTotal = args.TotalBytes.GetValueOrDefault(0), BytesTransferred = args.BytesTransferred }; progress.Report(uploadProgress); }; _progressMessageHandler.HttpSendProgress += progressHandlerFunc; } try { var response = await Client.SendAsync(request, completionOption : HttpCompletionOption.ResponseHeadersRead, token); var fullResponse = new FullResponse { Body = await response.Content.ReadAsStringAsync(), Headers = response.Headers.ToDictionary(key => key.Key, value => value.Value.FirstOrDefault()), StatusCode = response.StatusCode }; if (!response.IsSuccessStatusCode) { throw new SafeguardDotNetException( $"Error returned from Safeguard API, Error: {fullResponse.StatusCode} {fullResponse.Body}", fullResponse.StatusCode, fullResponse.Body); } SafeguardConnection.LogResponseDetails(fullResponse); return(fullResponse.Body); } finally { if (progressHandlerFunc != null) { _progressMessageHandler.HttpSendProgress -= progressHandlerFunc; } } } } }