internal void LogResponseDetails(FullResponse fullResponse)
 {
     _logger.Debug("Response status code: {StatusCode}", fullResponse.StatusCode);
     _logger.Debug("  Response headers: {ResponseHeaders}",
                   fullResponse.Headers?.Select(kv => $"{kv.Key}: {kv.Value}")
                   .Aggregate("", (str, header) => $"{str}{header}, ").TrimEnd(',', ' '));
     _logger.Debug("  Body size: {ResponseBodySize}",
                   fullResponse.Body == null ? "None" : $"{fullResponse.Body.Length}");
 }
        public FullResponse InvokeMethodFull(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("VaultConnection");
            }

            if (string.IsNullOrEmpty(relativeUrl))
            {
                throw new ArgumentException("Parameter may not be null or empty", nameof(relativeUrl));
            }

            var request = new RestRequest(relativeUrl, method);

            if (_credential != null)
            {
                request.AddHeader("X-Vault-Token", _credential);
            }

            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);
            }
            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;
            }

            LogRequestDetails(method, new Uri(_vaultClient.BaseUrl + $"/{relativeUrl}"), parameters, additionalHeaders);

            var response = _vaultClient.Execute(request);

            _logger.Debug("  Body size: {RequestBodySize}", body == null ? "None" : $"{body.Length}");
            if (response.ResponseStatus != ResponseStatus.Completed)
            {
                throw new Exception($"Unable to connect to web service {_vaultClient.BaseUrl}, Error: " + response.ErrorMessage);
            }

            if (response.StatusCode == HttpStatusCode.TemporaryRedirect)
            {
                //Wait 2 seconds and try the request again. The vault sometimes redirects to the same URL.
                Thread.Sleep(TimeSpan.FromSeconds(2));
                response = _vaultClient.Execute(request);
                if (response.ResponseStatus != ResponseStatus.Completed)
                {
                    throw new Exception($"Unable to connect to web service {_vaultClient.BaseUrl}, Error: " + response.ErrorMessage);
                }
            }

            if (!response.IsSuccessful && response.StatusCode != HttpStatusCode.ServiceUnavailable)
            {
                throw new Exception("Error returned from Safeguard API, Error: " + $"{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());
                }
            }
            LogResponseDetails(fullResponse);

            return(fullResponse);
        }