public static XmlAction GetXmlAction(this XmlApiRecord apiRecord, IApiProxyConfiguration proxyConfiguration)
        {
            if (!proxyConfiguration.FallbackToDefaultApi)
            {
                if (apiRecord.ResponseContent != null || apiRecord.Mock)
                {
                    return(XmlAction.ReplayFromMock);
                }
                return(XmlAction.None);
            }

            var xmlConfiguration = apiRecord.Configuration;

            if ((xmlConfiguration != null && apiRecord.Mock && !string.IsNullOrWhiteSpace(xmlConfiguration.Transform?.RequestContent?.XsltFileName)))
            {
                return(XmlAction.ReplayFromTransformedRequestMock);
            }

            if (xmlConfiguration?.Transform != null)
            {
                return(XmlAction.TransformResponse);
            }
            if (apiRecord.ResponseContent != null || apiRecord.Mock)
            {
                return(XmlAction.ReplayFromMock);
            }

            return(XmlAction.ReplayFromRealApi);
        }
        private HttpResponseMessage ReplayResponseFromApiRecord(XmlApiRecord apiRecord, string responseContent)
        {
            HttpStatusCode statusCode = HttpStatusCode.BadRequest;

            Enum.TryParse(apiRecord.StatusCode, true, out statusCode);
            var contentType = apiRecord.ResponseContentType;

            return(new HttpResponseMessage()
            {
                StatusCode = statusCode,
                Content = !string.IsNullOrEmpty(responseContent) ? new StringContent(
                    responseContent,
                    Encoding.UTF8,
                    contentType
                    ) : null
            });
        }
        private string GetRelativeQueryParameter(HttpRequestMessage request, XmlApiRecord record)
        {
            if (string.IsNullOrWhiteSpace(record.Configuration?.Transform?.Query?.TrimQueryParameters))
            {
                return(request.RequestUri.PathAndQuery);
            }
            var resultantQueries           = new List <KeyValuePair <string, string> >();
            var queryParametersTobeTrimmed = record.Configuration?.Transform?.Query?.TrimQueryParameters.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries).Select(queryParameterName => queryParameterName.ToLowerInvariant()).Select(
                queryParameterName =>
            {
                var keyValue = queryParameterName.Split(new char[] { '=' });
                if (keyValue.Length >= 2)
                {
                    return(new KeyValuePair <string, string>(keyValue[0], keyValue[1]));
                }

                return(new KeyValuePair <string, string>(queryParameterName, string.Empty));
            });

            var queryParameters = request.GetQueryNameValuePairs();

            if (queryParametersTobeTrimmed.Any() && queryParameters.Any())
            {
                resultantQueries.AddRange(
                    queryParameters.Where(queryParameter =>
                {
                    var selectedQuery = queryParametersTobeTrimmed.FirstOrDefault(
                        pair =>
                    {
                        if (pair.Key == queryParameter.Key.ToLowerInvariant())
                        {
                            if (pair.Value != String.Empty)
                            {
                                return(queryParameter.Value.ToLowerInvariant() == pair.Value);
                            }
                        }
                        return(false);
                    });
                    return(!string.IsNullOrWhiteSpace(selectedQuery.Key));
                }));

                return(resultantQueries.Any() ? string.Format("{0}?{1}", request.RequestUri.AbsolutePath, string.Join("&", resultantQueries.Select(parameter => parameter.Key + "=" + parameter.Value))) : request.RequestUri.AbsolutePath);
            }
            return(request.RequestUri.PathAndQuery);
        }
        public XmlContentTypeApiProxyProvider(IApiProxyConfiguration proxyConfiguration, IApiRecorder apiRecorder, XmlApiRecord apiRecord)
        {
            if (proxyConfiguration == null)
            {
                throw new ArgumentNullException(nameof(proxyConfiguration));
            }
            ProxyConfiguration = proxyConfiguration;

            if (apiRecorder == null)
            {
                throw new ArgumentNullException(nameof(apiRecorder));
            }
            ApiRecorder = apiRecorder;

            if (apiRecord == null)
            {
                throw new ArgumentNullException(nameof(apiRecord));
            }
            _xmlApiRecord = apiRecord;
        }
        private async Task <string> TransformXmlRequestAndReplay(HttpRequestMessage request, Guid activityId, XmlApiRecord apiRecord, HttpContent realContent)
        {
            var transformedContent = apiRecord.ResponseContent;

            if (!request.IsContentMediaTypeXml())
            {
                ApiProxyEvents.Raise.VerboseMessaging(string.Format("Skipping Request Transforming the as content type is not application/xml for request:{0}", request.RequestUri));
                return(transformedContent);
            }

            var xsltFileName = apiRecord?.Configuration?.Transform?.RequestContent?.XsltFileName;

            if (string.IsNullOrWhiteSpace(xsltFileName))
            {
                ApiProxyEvents.Raise.VerboseMessaging(string.Format("Skipping Request Transforming the as xmlt path is not specified for request:{0}", request.RequestUri));
                return(transformedContent);
            }

            var effectiveXsltFileNamePath = Path.Combine(Path.GetDirectoryName(apiRecord.MockFilePath), xsltFileName);
            var xmlContent = await realContent.ReadAsStringAsync();

            IList <string> transformOutput;

            ApiProxyEvents.Raise.VerboseMessaging(string.Format("Transforming the response using xslt:{0} for request:{1}, real response:{2}", effectiveXsltFileNamePath, request.RequestUri, xmlContent));
            transformedContent = TransformContent(request, xmlContent, effectiveXsltFileNamePath, out transformOutput);
            if (string.IsNullOrWhiteSpace(transformedContent))
            {
                ApiProxyEvents.Raise.VerboseMessaging(string.Format("Response Transform was skipped request:{0}, real response:{1}", request.RequestUri, xmlContent));
                return(apiRecord.ResponseContent);
            }

            Dictionary <string, string> outDictionary = new Dictionary <string, string>();

            transformOutput.ToList().ForEach(
                msg =>
            {
                var pair = msg.Trim(' ').Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
                if (!outDictionary.ContainsKey(pair[0]))
                {
                    outDictionary.Add(pair[0], pair.Length > 1 ? pair[1] : String.Empty);
                }
            });

            if (outDictionary.ContainsKey("StatusCode"))
            {
                apiRecord.StatusCode = outDictionary["StatusCode"];
            }

            return(transformedContent);
        }
        private async Task <HttpContent> TransformApiXmlRequestContent(HttpRequestMessage request, Guid activityId, XmlApiRecord apiRecord, HttpContent realContent)
        {
            if (!request.IsContentMediaTypeXml())
            {
                ApiProxyEvents.Raise.VerboseMessaging(string.Format("Skipping Request Transforming the as content type is not application/xml for request:{0}", request.RequestUri));
                return(realContent);
            }

            var xsltFileName = apiRecord?.Configuration?.Transform?.RequestContent?.XsltFileName;

            if (string.IsNullOrWhiteSpace(xsltFileName))
            {
                ApiProxyEvents.Raise.VerboseMessaging(string.Format("Skipping Request Transforming the as xmlt path is not specified for request:{0}", request.RequestUri));
                return(realContent);
            }

            var effectiveXsltFileNamePath = Path.Combine(Path.GetDirectoryName(apiRecord.MockFilePath), xsltFileName);
            var xmlContent = await realContent.ReadAsStringAsync();

            IList <string> transformOutput;

            ApiProxyEvents.Raise.VerboseMessaging(string.Format("Transforming the response using xslt:{0} for request:{1}, real response:{2}", effectiveXsltFileNamePath, request.RequestUri, xmlContent));
            var transformedContent = TransformContent(request, xmlContent, effectiveXsltFileNamePath, out transformOutput);

            if (string.IsNullOrWhiteSpace(transformedContent))
            {
                ApiProxyEvents.Raise.VerboseMessaging(string.Format("Response Transform was skipped request:{0}, real response:{1}", request.RequestUri, xmlContent));
                return(realContent);
            }
            var contentType = realContent.Headers.ContentType.MediaType;

            return(new StringContent(transformedContent,
                                     Encoding.UTF8,
                                     contentType));
        }
        private async Task <HttpContent> TransformApiUrlEncodeRequestContent(HttpRequestMessage request, Guid activityId, XmlApiRecord apiRecord, HttpContent realContent)
        {
            var contentType = request.Content.Headers.ContentType.MediaType;

            if (contentType != "application/x-www-form-urlencoded")
            {
                ApiProxyEvents.Raise.VerboseMessaging(
                    $"Skipping Request Transforming the as content type is not application/x-www-form-urlencoded for request:{request.RequestUri}");
                return(realContent);
            }

            var queryParametersTobeTrimmed = apiRecord.Configuration?.Transform?.RequestContent?.TrimQueryParameters.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries).Select(queryParameterName => queryParameterName.ToLowerInvariant()).Select(
                queryParameterName =>
            {
                var keyValue = queryParameterName.Split(new char[] { '=' });
                if (keyValue.Length >= 2)
                {
                    return(new KeyValuePair <string, string>(keyValue[0], keyValue[1]));
                }

                return(new KeyValuePair <string, string>(queryParameterName, string.Empty));
            }).ToList();

            if (queryParametersTobeTrimmed != null && !queryParametersTobeTrimmed.Any())
            {
                ApiProxyEvents.Raise.VerboseMessaging(string.Format("Skipping Request Transforming the as no query parametes needs to be trimmed for request:{0}", request.RequestUri));
                return(realContent);
            }

            var urlEncodedContent = await realContent.ReadAsStringAsync();

            ApiProxyEvents.Raise.VerboseMessaging(string.Format("Transforming the request by trimming content:{0} for request:{1}, real response:{2}", apiRecord.Configuration?.Transform?.RequestContent?.TrimQueryParameters, request.RequestUri, urlEncodedContent));
            var urlParameters = urlEncodedContent.Split(new char[] { '&' }, StringSplitOptions.RemoveEmptyEntries).Select(
                pair =>
            {
                var keyValue = pair.Split(new char[] { '=' });
                if (keyValue.Length > 0 && keyValue.Length < 2)
                {
                    return(new KeyValuePair <string, string>(keyValue[0], string.Empty));
                }
                return(new KeyValuePair <string, string>(keyValue[0], keyValue[1]));
            }).ToList();

            if (string.IsNullOrWhiteSpace(urlEncodedContent))
            {
                ApiProxyEvents.Raise.VerboseMessaging(string.Format("Request Transform was skipped for request:{0}, real response:{1}", request.RequestUri, urlEncodedContent));
                return(realContent);
            }

            var transformedContent = urlEncodedContent;
            var resultantQueries   = new List <KeyValuePair <string, string> >();

            if (queryParametersTobeTrimmed != null && (queryParametersTobeTrimmed.Any() && urlParameters.Any()))
            {
                resultantQueries.AddRange(
                    urlParameters.Where(queryParameter =>
                {
                    var selectedQuery = queryParametersTobeTrimmed.FirstOrDefault(
                        pair =>
                    {
                        if (pair.Key == queryParameter.Key.ToLowerInvariant())
                        {
                            if (pair.Value != String.Empty)
                            {
                                return(queryParameter.Value.ToLowerInvariant() != pair.Value);
                            }
                        }
                        return(false);
                    });
                    return(!string.IsNullOrWhiteSpace(selectedQuery.Key));
                }));
                transformedContent = resultantQueries.Any() ? string.Join("&", resultantQueries.Select(parameter => parameter.Key + "=" + parameter.Value)) : string.Empty;
            }
            return(new StringContent(transformedContent,
                                     Encoding.UTF8,
                                     contentType));
        }
        private async Task <HttpContent> TransformApiRequestContent(HttpRequestMessage request, Guid activityId, XmlApiRecord apiRecord, HttpContent realContent)
        {
            var contentType = request.Content.Headers.ContentType.MediaType;

            if (contentType != "application/xml" && contentType != "application/x-www-form-urlencoded" && contentType != "text/xml")
            {
                ApiProxyEvents.Raise.VerboseMessaging(
                    $"Skipping Request Transforming the as content type is not application/xml or application/x-www-form-urlencoded for request:{request.RequestUri}");
                return(realContent);
            }

            if (contentType == "application/xml" || contentType == "text/xml")
            {
                return(await TransformApiXmlRequestContent(request, activityId, apiRecord, realContent));
            }
            return(await TransformApiUrlEncodeRequestContent(request, activityId, apiRecord, realContent));
        }
        private async Task <HttpResponseMessage> GetApiResponseFromDefaultApi(HttpRequestMessage request, XmlApiRecord apiRecord, Guid activityId)
        {
            // Else pass the request to the default api
            if (ProxyConfiguration.DefaultApiAddress == null)
            {
                return(request.CreateResponse(HttpStatusCode.InternalServerError,
                                              new ErrorResponse
                {
                    ActivityId = activityId,
                    Message = "Default Api Address is not found"
                }
                                              ));
            }

            //Trust all certificates
            System.Net.ServicePointManager.ServerCertificateValidationCallback =
                ((sender, certificate, chain, sslPolicyErrors) => true);

            using (HttpClient client = new HttpClient())
            {
                client.BaseAddress = ProxyConfiguration.DefaultApiAddress;
                var requestUri = new Uri(client.BaseAddress, GetRelativeQueryParameter(request, apiRecord));
                ApiProxyEvents.Raise.VerboseMessaging($"Routing Request to the Default Api Address : {requestUri}");
                client.DefaultRequestHeaders.Clear();
                foreach (var header in request.Headers)
                {
                    if (header.Key != "Host")
                    {
                        client.DefaultRequestHeaders.Add(header.Key, header.Value);
                    }
                }
                HttpResponseMessage defaultApiresponse = null;
                var transformOutput = new List <string>();

                if (request.Method == HttpMethod.Get)
                {
                    defaultApiresponse =
                        await
                        client.GetAsync(requestUri,
                                        HttpCompletionOption.ResponseContentRead);
                }
                else if (request.Method == HttpMethod.Post)
                {
                    defaultApiresponse =
                        await client.PostAsync(requestUri, await TransformApiRequestContent(request, activityId, apiRecord, request.Content));
                }
                else if (request.Method == HttpMethod.Put)
                {
                    defaultApiresponse =
                        await client.PutAsync(requestUri, await TransformApiRequestContent(request, activityId, apiRecord, request.Content));
                }
                else if (request.Method == HttpMethod.Delete)
                {
                    defaultApiresponse = await client.DeleteAsync(requestUri);
                }
                if (defaultApiresponse != null)
                {
                    ApiProxyEvents.Raise.VerboseMessaging(
                        $"Response from the Default Api , request :{requestUri}, status :{defaultApiresponse.StatusCode}");
                    // Record the api req/res if enabled
                    await ApiRecorder.RecordApi(request, defaultApiresponse);

                    return(defaultApiresponse);
                }
                return(request.CreateResponse(HttpStatusCode.InternalServerError,
                                              new ErrorResponse
                {
                    ActivityId = activityId,
                    Message = "Request to Default Api with the given Method cannot be done"
                }
                                              ));
            }
        }
 private HttpResponseMessage ReplayResponseFromApiRecord(XmlApiRecord apiRecord)
 {
     return(ReplayResponseFromApiRecord(apiRecord, apiRecord.ResponseContent));
 }