mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-22 06:22:50 +08:00
regex for url match, means annoying constructor ocelot configuration object but cant work out a better way to do this at the moment
This commit is contained in:
parent
f8ea87c91b
commit
1fddcf0836
@ -1,14 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Ocelot.Library.Infrastructure.Configuration
|
|
||||||
{
|
|
||||||
public class Configuration
|
|
||||||
{
|
|
||||||
public Configuration()
|
|
||||||
{
|
|
||||||
ReRoutes = new List<ReRoute>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ReRoute> ReRoutes { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Ocelot.Library.Infrastructure.Responses;
|
|
||||||
|
|
||||||
namespace Ocelot.Library.Infrastructure.Configuration
|
|
||||||
{
|
|
||||||
public class DownstreamTemplateAlreadyUsedError : Error
|
|
||||||
{
|
|
||||||
public DownstreamTemplateAlreadyUsedError(string message) : base(message)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Ocelot.Library.Infrastructure.Responses;
|
|
||||||
|
|
||||||
namespace Ocelot.Library.Infrastructure.Configuration
|
|
||||||
{
|
|
||||||
public interface IConfigurationValidator
|
|
||||||
{
|
|
||||||
Response<ConfigurationValidationResult> IsValid(Configuration configuration);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,9 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Ocelot.Library.Infrastructure.Configuration
|
||||||
|
{
|
||||||
|
public interface IOcelotConfiguration
|
||||||
|
{
|
||||||
|
List<ReRoute> ReRoutes { get; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Ocelot.Library.Infrastructure.Configuration.Yaml;
|
||||||
|
|
||||||
|
namespace Ocelot.Library.Infrastructure.Configuration
|
||||||
|
{
|
||||||
|
public class OcelotConfiguration : IOcelotConfiguration
|
||||||
|
{
|
||||||
|
private readonly IOptions<YamlConfiguration> _options;
|
||||||
|
private readonly List<ReRoute> _reRoutes;
|
||||||
|
private const string RegExMatchEverything = ".*";
|
||||||
|
private const string RegExMatchEndString = "$";
|
||||||
|
|
||||||
|
public OcelotConfiguration(IOptions<YamlConfiguration> options)
|
||||||
|
{
|
||||||
|
_options = options;
|
||||||
|
_reRoutes = new List<ReRoute>();
|
||||||
|
SetReRoutes();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetReRoutes()
|
||||||
|
{
|
||||||
|
foreach(var reRoute in _options.Value.ReRoutes)
|
||||||
|
{
|
||||||
|
var upstreamTemplate = reRoute.UpstreamTemplate;
|
||||||
|
var placeholders = new List<string>();
|
||||||
|
|
||||||
|
for (int i = 0; i < upstreamTemplate.Length; i++)
|
||||||
|
{
|
||||||
|
if (IsPlaceHolder(upstreamTemplate, i))
|
||||||
|
{
|
||||||
|
var postitionOfPlaceHolderClosingBracket = upstreamTemplate.IndexOf('}', i);
|
||||||
|
var difference = postitionOfPlaceHolderClosingBracket - i + 1;
|
||||||
|
var variableName = upstreamTemplate.Substring(i, difference);
|
||||||
|
placeholders.Add(variableName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var placeholder in placeholders)
|
||||||
|
{
|
||||||
|
upstreamTemplate = upstreamTemplate.Replace(placeholder, RegExMatchEverything);
|
||||||
|
}
|
||||||
|
|
||||||
|
upstreamTemplate = $"{upstreamTemplate}{RegExMatchEndString}";
|
||||||
|
|
||||||
|
_reRoutes.Add(new ReRoute(reRoute.DownstreamTemplate, reRoute.UpstreamTemplate, reRoute.UpstreamHttpMethod, upstreamTemplate));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsPlaceHolder(string upstreamTemplate, int i)
|
||||||
|
{
|
||||||
|
return upstreamTemplate[i] == '{';
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ReRoute> ReRoutes => _reRoutes;
|
||||||
|
}
|
||||||
|
}
|
@ -2,8 +2,17 @@
|
|||||||
{
|
{
|
||||||
public class ReRoute
|
public class ReRoute
|
||||||
{
|
{
|
||||||
public string DownstreamTemplate { get; set; }
|
public ReRoute(string downstreamTemplate, string upstreamTemplate, string upstreamHttpMethod, string upstreamTemplatePattern)
|
||||||
public string UpstreamTemplate { get; set; }
|
{
|
||||||
public string UpstreamHttpMethod { get; set; }
|
DownstreamTemplate = downstreamTemplate;
|
||||||
|
UpstreamTemplate = upstreamTemplate;
|
||||||
|
UpstreamHttpMethod = upstreamHttpMethod;
|
||||||
|
UpstreamTemplatePattern = upstreamTemplatePattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string DownstreamTemplate { get; private set; }
|
||||||
|
public string UpstreamTemplate { get; private set; }
|
||||||
|
public string UpstreamTemplatePattern { get; private set; }
|
||||||
|
public string UpstreamHttpMethod { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Ocelot.Library.Infrastructure.Responses;
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
|
|
||||||
namespace Ocelot.Library.Infrastructure.Configuration
|
namespace Ocelot.Library.Infrastructure.Configuration.Yaml
|
||||||
{
|
{
|
||||||
public class ConfigurationValidationResult
|
public class ConfigurationValidationResult
|
||||||
{
|
{
|
@ -2,11 +2,11 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Ocelot.Library.Infrastructure.Responses;
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
|
|
||||||
namespace Ocelot.Library.Infrastructure.Configuration
|
namespace Ocelot.Library.Infrastructure.Configuration.Yaml
|
||||||
{
|
{
|
||||||
public class ConfigurationValidator : IConfigurationValidator
|
public class ConfigurationValidator : IConfigurationValidator
|
||||||
{
|
{
|
||||||
public Response<ConfigurationValidationResult> IsValid(Configuration configuration)
|
public Response<ConfigurationValidationResult> IsValid(YamlConfiguration configuration)
|
||||||
{
|
{
|
||||||
var duplicateUpstreamTemplates = configuration.ReRoutes
|
var duplicateUpstreamTemplates = configuration.ReRoutes
|
||||||
.Select(r => r.DownstreamTemplate)
|
.Select(r => r.DownstreamTemplate)
|
@ -0,0 +1,11 @@
|
|||||||
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
|
|
||||||
|
namespace Ocelot.Library.Infrastructure.Configuration.Yaml
|
||||||
|
{
|
||||||
|
public class DownstreamTemplateAlreadyUsedError : Error
|
||||||
|
{
|
||||||
|
public DownstreamTemplateAlreadyUsedError(string message) : base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
|
|
||||||
|
namespace Ocelot.Library.Infrastructure.Configuration.Yaml
|
||||||
|
{
|
||||||
|
public interface IConfigurationValidator
|
||||||
|
{
|
||||||
|
Response<ConfigurationValidationResult> IsValid(YamlConfiguration configuration);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Ocelot.Library.Infrastructure.Configuration.Yaml
|
||||||
|
{
|
||||||
|
public class YamlConfiguration
|
||||||
|
{
|
||||||
|
public YamlConfiguration()
|
||||||
|
{
|
||||||
|
ReRoutes = new List<YamlReRoute>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<YamlReRoute> ReRoutes { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
namespace Ocelot.Library.Infrastructure.Configuration.Yaml
|
||||||
|
{
|
||||||
|
public class YamlReRoute
|
||||||
|
{
|
||||||
|
public string DownstreamTemplate { get; set; }
|
||||||
|
public string UpstreamTemplate { get; set; }
|
||||||
|
public string UpstreamHttpMethod { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
using Ocelot.Library.Infrastructure.Configuration;
|
||||||
using Ocelot.Library.Infrastructure.Responses;
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
using Ocelot.Library.Infrastructure.UrlMatcher;
|
using Ocelot.Library.Infrastructure.UrlMatcher;
|
||||||
|
|
||||||
@ -9,24 +10,29 @@ namespace Ocelot.Library.Infrastructure.DownstreamRouteFinder
|
|||||||
{
|
{
|
||||||
public class DownstreamRouteFinder : IDownstreamRouteFinder
|
public class DownstreamRouteFinder : IDownstreamRouteFinder
|
||||||
{
|
{
|
||||||
private readonly IOptions<Configuration.Configuration> _configuration;
|
private readonly IOcelotConfiguration _configuration;
|
||||||
private readonly IUrlPathToUrlTemplateMatcher _urlMatcher;
|
private readonly IUrlPathToUrlTemplateMatcher _urlMatcher;
|
||||||
|
private readonly ITemplateVariableNameAndValueFinder _templateVariableNameAndValueFinder;
|
||||||
|
|
||||||
public DownstreamRouteFinder(IOptions<Configuration.Configuration> configuration, IUrlPathToUrlTemplateMatcher urlMatcher)
|
public DownstreamRouteFinder(IOcelotConfiguration configuration, IUrlPathToUrlTemplateMatcher urlMatcher, ITemplateVariableNameAndValueFinder templateVariableNameAndValueFinder)
|
||||||
{
|
{
|
||||||
_configuration = configuration;
|
_configuration = configuration;
|
||||||
_urlMatcher = urlMatcher;
|
_urlMatcher = urlMatcher;
|
||||||
|
_templateVariableNameAndValueFinder = templateVariableNameAndValueFinder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Response<DownstreamRoute> FindDownstreamRoute(string upstreamUrlPath, string upstreamHttpMethod)
|
public Response<DownstreamRoute> FindDownstreamRoute(string upstreamUrlPath, string upstreamHttpMethod)
|
||||||
{
|
{
|
||||||
foreach (var template in _configuration.Value.ReRoutes.Where(r => string.Equals(r.UpstreamHttpMethod, upstreamHttpMethod, StringComparison.CurrentCultureIgnoreCase)))
|
foreach (var template in _configuration.ReRoutes.Where(r => string.Equals(r.UpstreamHttpMethod, upstreamHttpMethod, StringComparison.CurrentCultureIgnoreCase)))
|
||||||
{
|
{
|
||||||
var urlMatch = _urlMatcher.Match(upstreamUrlPath, template.UpstreamTemplate);
|
var urlMatch = _urlMatcher.Match(upstreamUrlPath, template.UpstreamTemplatePattern);
|
||||||
|
|
||||||
if (urlMatch.Match)
|
if (urlMatch.Data.Match)
|
||||||
{
|
{
|
||||||
return new OkResponse<DownstreamRoute>(new DownstreamRoute(urlMatch.TemplateVariableNameAndValues, template.DownstreamTemplate));
|
var templateVariableNameAndValues = _templateVariableNameAndValueFinder.Find(upstreamUrlPath,
|
||||||
|
template.UpstreamTemplate);
|
||||||
|
|
||||||
|
return new OkResponse<DownstreamRoute>(new DownstreamRoute(templateVariableNameAndValues.Data, template.DownstreamTemplate));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,12 +5,13 @@ using System.Net.Http;
|
|||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
|
|
||||||
namespace Ocelot.Library.Infrastructure.RequestBuilder
|
namespace Ocelot.Library.Infrastructure.RequestBuilder
|
||||||
{
|
{
|
||||||
public class HttpRequestBuilder : IRequestBuilder
|
public class HttpRequestBuilder : IRequestBuilder
|
||||||
{
|
{
|
||||||
public async Task<Request> Build(string httpMethod, string downstreamUrl, Stream content, IHeaderDictionary headers,
|
public async Task<Response<Request>> Build(string httpMethod, string downstreamUrl, Stream content, IHeaderDictionary headers,
|
||||||
IRequestCookieCollection cookies, string queryString, string contentType)
|
IRequestCookieCollection cookies, string queryString, string contentType)
|
||||||
{
|
{
|
||||||
var method = new HttpMethod(httpMethod);
|
var method = new HttpMethod(httpMethod);
|
||||||
@ -65,8 +66,7 @@ namespace Ocelot.Library.Infrastructure.RequestBuilder
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return new OkResponse<Request>(new Request(httpRequestMessage, cookieContainer));
|
||||||
return new Request(httpRequestMessage, cookieContainer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,12 +1,13 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
|
|
||||||
namespace Ocelot.Library.Infrastructure.RequestBuilder
|
namespace Ocelot.Library.Infrastructure.RequestBuilder
|
||||||
{
|
{
|
||||||
public interface IRequestBuilder
|
public interface IRequestBuilder
|
||||||
{
|
{
|
||||||
Task<Request> Build(string httpMethod,
|
Task<Response<Request>> Build(string httpMethod,
|
||||||
string downstreamUrl,
|
string downstreamUrl,
|
||||||
Stream content,
|
Stream content,
|
||||||
IHeaderDictionary headers,
|
IHeaderDictionary headers,
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
|
|
||||||
|
namespace Ocelot.Library.Infrastructure.UrlMatcher
|
||||||
|
{
|
||||||
|
public interface ITemplateVariableNameAndValueFinder
|
||||||
|
{
|
||||||
|
Response<List<TemplateVariableNameAndValue>> Find(string upstreamUrlPath, string upstreamUrlPathTemplate);
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,9 @@
|
|||||||
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
|
|
||||||
namespace Ocelot.Library.Infrastructure.UrlMatcher
|
namespace Ocelot.Library.Infrastructure.UrlMatcher
|
||||||
{
|
{
|
||||||
public interface IUrlPathToUrlTemplateMatcher
|
public interface IUrlPathToUrlTemplateMatcher
|
||||||
{
|
{
|
||||||
UrlMatch Match(string upstreamUrlPath, string upstreamUrlPathTemplate);
|
Response<UrlMatch> Match(string upstreamUrlPath, string upstreamUrlPathTemplate);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
|
|
||||||
|
namespace Ocelot.Library.Infrastructure.UrlMatcher
|
||||||
|
{
|
||||||
|
public class RegExUrlMatcher : IUrlPathToUrlTemplateMatcher
|
||||||
|
{
|
||||||
|
public Response<UrlMatch> Match(string upstreamUrlPath, string upstreamUrlPathTemplate)
|
||||||
|
{
|
||||||
|
var regex = new Regex(upstreamUrlPathTemplate);
|
||||||
|
|
||||||
|
return regex.IsMatch(upstreamUrlPath)
|
||||||
|
? new OkResponse<UrlMatch>(new UrlMatch(true))
|
||||||
|
: new OkResponse<UrlMatch>(new UrlMatch(false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,19 +1,12 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
|
|
||||||
namespace Ocelot.Library.Infrastructure.UrlMatcher
|
namespace Ocelot.Library.Infrastructure.UrlMatcher
|
||||||
{
|
{
|
||||||
public class UrlPathToUrlTemplateMatcher : IUrlPathToUrlTemplateMatcher
|
public class TemplateVariableNameAndValueFinder : ITemplateVariableNameAndValueFinder
|
||||||
{
|
{
|
||||||
public UrlMatch Match(string upstreamUrlPath, string upstreamUrlPathTemplate)
|
public Response<List<TemplateVariableNameAndValue>> Find(string upstreamUrlPath, string upstreamUrlPathTemplate)
|
||||||
{
|
{
|
||||||
if (upstreamUrlPath.Length > upstreamUrlPathTemplate.Length)
|
|
||||||
{
|
|
||||||
return new UrlMatch(false, new List<TemplateVariableNameAndValue>(), string.Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
var urlPathTemplateCopy = upstreamUrlPathTemplate;
|
|
||||||
|
|
||||||
var templateKeysAndValues = new List<TemplateVariableNameAndValue>();
|
var templateKeysAndValues = new List<TemplateVariableNameAndValue>();
|
||||||
|
|
||||||
int counterForUrl = 0;
|
int counterForUrl = 0;
|
||||||
@ -38,14 +31,13 @@ namespace Ocelot.Library.Infrastructure.UrlMatcher
|
|||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
return new OkResponse<List<TemplateVariableNameAndValue>>(templateKeysAndValues);
|
||||||
return new UrlMatch(false, templateKeysAndValues, string.Empty);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
counterForUrl++;
|
counterForUrl++;
|
||||||
}
|
}
|
||||||
return new UrlMatch(true, templateKeysAndValues, urlPathTemplateCopy);
|
|
||||||
|
return new OkResponse<List<TemplateVariableNameAndValue>>(templateKeysAndValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetPlaceholderVariableValue(string urlPath, int counterForUrl)
|
private string GetPlaceholderVariableValue(string urlPath, int counterForUrl)
|
@ -1,17 +1,11 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Ocelot.Library.Infrastructure.UrlMatcher
|
namespace Ocelot.Library.Infrastructure.UrlMatcher
|
||||||
{
|
{
|
||||||
public class UrlMatch
|
public class UrlMatch
|
||||||
{
|
{
|
||||||
public UrlMatch(bool match, List<TemplateVariableNameAndValue> templateVariableNameAndValues, string downstreamUrlTemplate)
|
public UrlMatch(bool match)
|
||||||
{
|
{
|
||||||
Match = match;
|
Match = match;
|
||||||
TemplateVariableNameAndValues = templateVariableNameAndValues;
|
|
||||||
DownstreamUrlTemplate = downstreamUrlTemplate;
|
|
||||||
}
|
}
|
||||||
public bool Match {get;private set;}
|
public bool Match {get;private set;}
|
||||||
public List<TemplateVariableNameAndValue> TemplateVariableNameAndValues {get;private set;}
|
|
||||||
public string DownstreamUrlTemplate {get;private set;}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,11 +1,12 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using Ocelot.Library.Infrastructure.DownstreamRouteFinder;
|
using Ocelot.Library.Infrastructure.DownstreamRouteFinder;
|
||||||
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
|
|
||||||
namespace Ocelot.Library.Infrastructure.UrlTemplateReplacer
|
namespace Ocelot.Library.Infrastructure.UrlTemplateReplacer
|
||||||
{
|
{
|
||||||
public class DownstreamUrlTemplateVariableReplacer : IDownstreamUrlTemplateVariableReplacer
|
public class DownstreamUrlTemplateVariableReplacer : IDownstreamUrlTemplateVariableReplacer
|
||||||
{
|
{
|
||||||
public string ReplaceTemplateVariables(DownstreamRoute downstreamRoute)
|
public Response<string> ReplaceTemplateVariables(DownstreamRoute downstreamRoute)
|
||||||
{
|
{
|
||||||
var upstreamUrl = new StringBuilder();
|
var upstreamUrl = new StringBuilder();
|
||||||
|
|
||||||
@ -16,7 +17,7 @@ namespace Ocelot.Library.Infrastructure.UrlTemplateReplacer
|
|||||||
upstreamUrl.Replace(templateVarAndValue.TemplateVariableName, templateVarAndValue.TemplateVariableValue);
|
upstreamUrl.Replace(templateVarAndValue.TemplateVariableName, templateVarAndValue.TemplateVariableValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
return upstreamUrl.ToString();
|
return new OkResponse<string>(upstreamUrl.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,10 +1,10 @@
|
|||||||
using Ocelot.Library.Infrastructure.DownstreamRouteFinder;
|
using Ocelot.Library.Infrastructure.DownstreamRouteFinder;
|
||||||
using Ocelot.Library.Infrastructure.UrlMatcher;
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
|
|
||||||
namespace Ocelot.Library.Infrastructure.UrlTemplateReplacer
|
namespace Ocelot.Library.Infrastructure.UrlTemplateReplacer
|
||||||
{
|
{
|
||||||
public interface IDownstreamUrlTemplateVariableReplacer
|
public interface IDownstreamUrlTemplateVariableReplacer
|
||||||
{
|
{
|
||||||
string ReplaceTemplateVariables(DownstreamRoute downstreamRoute);
|
Response<string> ReplaceTemplateVariables(DownstreamRoute downstreamRoute);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,25 +2,22 @@ using System.Threading.Tasks;
|
|||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Ocelot.Library.Infrastructure.DownstreamRouteFinder;
|
using Ocelot.Library.Infrastructure.DownstreamRouteFinder;
|
||||||
using Ocelot.Library.Infrastructure.Repository;
|
using Ocelot.Library.Infrastructure.Repository;
|
||||||
using Ocelot.Library.Infrastructure.Responder;
|
|
||||||
|
|
||||||
namespace Ocelot.Library.Middleware
|
namespace Ocelot.Library.Middleware
|
||||||
{
|
{
|
||||||
public class DownstreamRouteFinderMiddleware
|
public class DownstreamRouteFinderMiddleware : OcelotMiddleware
|
||||||
{
|
{
|
||||||
private readonly RequestDelegate _next;
|
private readonly RequestDelegate _next;
|
||||||
private readonly IDownstreamRouteFinder _downstreamRouteFinder;
|
private readonly IDownstreamRouteFinder _downstreamRouteFinder;
|
||||||
private readonly IHttpResponder _responder;
|
|
||||||
private readonly IScopedRequestDataRepository _scopedRequestDataRepository;
|
private readonly IScopedRequestDataRepository _scopedRequestDataRepository;
|
||||||
|
|
||||||
public DownstreamRouteFinderMiddleware(RequestDelegate next,
|
public DownstreamRouteFinderMiddleware(RequestDelegate next,
|
||||||
IDownstreamRouteFinder downstreamRouteFinder,
|
IDownstreamRouteFinder downstreamRouteFinder,
|
||||||
IHttpResponder responder,
|
|
||||||
IScopedRequestDataRepository scopedRequestDataRepository)
|
IScopedRequestDataRepository scopedRequestDataRepository)
|
||||||
|
:base(scopedRequestDataRepository)
|
||||||
{
|
{
|
||||||
_next = next;
|
_next = next;
|
||||||
_downstreamRouteFinder = downstreamRouteFinder;
|
_downstreamRouteFinder = downstreamRouteFinder;
|
||||||
_responder = responder;
|
|
||||||
_scopedRequestDataRepository = scopedRequestDataRepository;
|
_scopedRequestDataRepository = scopedRequestDataRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +29,7 @@ namespace Ocelot.Library.Middleware
|
|||||||
|
|
||||||
if (downstreamRoute.IsError)
|
if (downstreamRoute.IsError)
|
||||||
{
|
{
|
||||||
await _responder.CreateNotFoundResponse(context);
|
SetPipelineError(downstreamRoute.Errors);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,22 +7,20 @@ using Ocelot.Library.Infrastructure.UrlTemplateReplacer;
|
|||||||
|
|
||||||
namespace Ocelot.Library.Middleware
|
namespace Ocelot.Library.Middleware
|
||||||
{
|
{
|
||||||
public class DownstreamUrlCreatorMiddleware
|
public class DownstreamUrlCreatorMiddleware : OcelotMiddleware
|
||||||
{
|
{
|
||||||
private readonly RequestDelegate _next;
|
private readonly RequestDelegate _next;
|
||||||
private readonly IDownstreamUrlTemplateVariableReplacer _urlReplacer;
|
private readonly IDownstreamUrlTemplateVariableReplacer _urlReplacer;
|
||||||
private readonly IScopedRequestDataRepository _scopedRequestDataRepository;
|
private readonly IScopedRequestDataRepository _scopedRequestDataRepository;
|
||||||
private readonly IHttpResponder _responder;
|
|
||||||
|
|
||||||
public DownstreamUrlCreatorMiddleware(RequestDelegate next,
|
public DownstreamUrlCreatorMiddleware(RequestDelegate next,
|
||||||
IDownstreamUrlTemplateVariableReplacer urlReplacer,
|
IDownstreamUrlTemplateVariableReplacer urlReplacer,
|
||||||
IScopedRequestDataRepository scopedRequestDataRepository,
|
IScopedRequestDataRepository scopedRequestDataRepository)
|
||||||
IHttpResponder responder)
|
:base(scopedRequestDataRepository)
|
||||||
{
|
{
|
||||||
_next = next;
|
_next = next;
|
||||||
_urlReplacer = urlReplacer;
|
_urlReplacer = urlReplacer;
|
||||||
_scopedRequestDataRepository = scopedRequestDataRepository;
|
_scopedRequestDataRepository = scopedRequestDataRepository;
|
||||||
_responder = responder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Invoke(HttpContext context)
|
public async Task Invoke(HttpContext context)
|
||||||
@ -31,13 +29,19 @@ namespace Ocelot.Library.Middleware
|
|||||||
|
|
||||||
if (downstreamRoute.IsError)
|
if (downstreamRoute.IsError)
|
||||||
{
|
{
|
||||||
await _responder.CreateNotFoundResponse(context);
|
SetPipelineError(downstreamRoute.Errors);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var downstreamUrl = _urlReplacer.ReplaceTemplateVariables(downstreamRoute.Data);
|
var downstreamUrl = _urlReplacer.ReplaceTemplateVariables(downstreamRoute.Data);
|
||||||
|
|
||||||
_scopedRequestDataRepository.Add("DownstreamUrl", downstreamUrl);
|
if (downstreamUrl.IsError)
|
||||||
|
{
|
||||||
|
SetPipelineError(downstreamUrl.Errors);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_scopedRequestDataRepository.Add("DownstreamUrl", downstreamUrl.Data);
|
||||||
|
|
||||||
await _next.Invoke(context);
|
await _next.Invoke(context);
|
||||||
}
|
}
|
||||||
|
@ -1,27 +1,22 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Ocelot.Library.Infrastructure.Repository;
|
using Ocelot.Library.Infrastructure.Repository;
|
||||||
using Ocelot.Library.Infrastructure.Requester;
|
using Ocelot.Library.Infrastructure.RequestBuilder;
|
||||||
using Ocelot.Library.Infrastructure.Responder;
|
|
||||||
|
|
||||||
namespace Ocelot.Library.Middleware
|
namespace Ocelot.Library.Middleware
|
||||||
{
|
{
|
||||||
using Infrastructure.RequestBuilder;
|
public class HttpRequestBuilderMiddleware : OcelotMiddleware
|
||||||
|
|
||||||
public class HttpRequestBuilderMiddleware
|
|
||||||
{
|
{
|
||||||
private readonly RequestDelegate _next;
|
private readonly RequestDelegate _next;
|
||||||
private readonly IHttpResponder _responder;
|
|
||||||
private readonly IScopedRequestDataRepository _scopedRequestDataRepository;
|
private readonly IScopedRequestDataRepository _scopedRequestDataRepository;
|
||||||
private readonly IRequestBuilder _requestBuilder;
|
private readonly IRequestBuilder _requestBuilder;
|
||||||
|
|
||||||
public HttpRequestBuilderMiddleware(RequestDelegate next,
|
public HttpRequestBuilderMiddleware(RequestDelegate next,
|
||||||
IHttpResponder responder,
|
|
||||||
IScopedRequestDataRepository scopedRequestDataRepository,
|
IScopedRequestDataRepository scopedRequestDataRepository,
|
||||||
IRequestBuilder requestBuilder)
|
IRequestBuilder requestBuilder)
|
||||||
|
:base(scopedRequestDataRepository)
|
||||||
{
|
{
|
||||||
_next = next;
|
_next = next;
|
||||||
_responder = responder;
|
|
||||||
_scopedRequestDataRepository = scopedRequestDataRepository;
|
_scopedRequestDataRepository = scopedRequestDataRepository;
|
||||||
_requestBuilder = requestBuilder;
|
_requestBuilder = requestBuilder;
|
||||||
}
|
}
|
||||||
@ -32,7 +27,7 @@ namespace Ocelot.Library.Middleware
|
|||||||
|
|
||||||
if (downstreamUrl.IsError)
|
if (downstreamUrl.IsError)
|
||||||
{
|
{
|
||||||
await _responder.CreateNotFoundResponse(context);
|
SetPipelineError(downstreamUrl.Errors);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,7 +35,13 @@ namespace Ocelot.Library.Middleware
|
|||||||
.Build(context.Request.Method, downstreamUrl.Data, context.Request.Body,
|
.Build(context.Request.Method, downstreamUrl.Data, context.Request.Body,
|
||||||
context.Request.Headers, context.Request.Cookies, context.Request.QueryString.Value, context.Request.ContentType);
|
context.Request.Headers, context.Request.Cookies, context.Request.QueryString.Value, context.Request.ContentType);
|
||||||
|
|
||||||
_scopedRequestDataRepository.Add("Request", request);
|
if (request.IsError)
|
||||||
|
{
|
||||||
|
SetPipelineError(request.Errors);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_scopedRequestDataRepository.Add("Request", request.Data);
|
||||||
|
|
||||||
await _next.Invoke(context);
|
await _next.Invoke(context);
|
||||||
}
|
}
|
||||||
|
@ -1,29 +1,24 @@
|
|||||||
using System.Net.Http;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Ocelot.Library.Infrastructure.Repository;
|
using Ocelot.Library.Infrastructure.Repository;
|
||||||
|
using Ocelot.Library.Infrastructure.RequestBuilder;
|
||||||
using Ocelot.Library.Infrastructure.Requester;
|
using Ocelot.Library.Infrastructure.Requester;
|
||||||
using Ocelot.Library.Infrastructure.Responder;
|
|
||||||
|
|
||||||
namespace Ocelot.Library.Middleware
|
namespace Ocelot.Library.Middleware
|
||||||
{
|
{
|
||||||
using Infrastructure.RequestBuilder;
|
public class HttpRequesterMiddleware : OcelotMiddleware
|
||||||
|
|
||||||
public class HttpRequesterMiddleware
|
|
||||||
{
|
{
|
||||||
private readonly RequestDelegate _next;
|
private readonly RequestDelegate _next;
|
||||||
private readonly IHttpRequester _requester;
|
private readonly IHttpRequester _requester;
|
||||||
private readonly IHttpResponder _responder;
|
|
||||||
private readonly IScopedRequestDataRepository _scopedRequestDataRepository;
|
private readonly IScopedRequestDataRepository _scopedRequestDataRepository;
|
||||||
|
|
||||||
public HttpRequesterMiddleware(RequestDelegate next,
|
public HttpRequesterMiddleware(RequestDelegate next,
|
||||||
IHttpRequester requester,
|
IHttpRequester requester,
|
||||||
IHttpResponder responder,
|
|
||||||
IScopedRequestDataRepository scopedRequestDataRepository)
|
IScopedRequestDataRepository scopedRequestDataRepository)
|
||||||
|
:base(scopedRequestDataRepository)
|
||||||
{
|
{
|
||||||
_next = next;
|
_next = next;
|
||||||
_requester = requester;
|
_requester = requester;
|
||||||
_responder = responder;
|
|
||||||
_scopedRequestDataRepository = scopedRequestDataRepository;
|
_scopedRequestDataRepository = scopedRequestDataRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,16 +28,19 @@ namespace Ocelot.Library.Middleware
|
|||||||
|
|
||||||
if (request.IsError)
|
if (request.IsError)
|
||||||
{
|
{
|
||||||
await _responder.CreateNotFoundResponse(context);
|
SetPipelineError(request.Errors);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var response = await _requester
|
var response = await _requester.GetResponse(request.Data);
|
||||||
.GetResponse(request.Data);
|
|
||||||
|
if (response.IsError)
|
||||||
|
{
|
||||||
|
SetPipelineError(response.Errors);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_scopedRequestDataRepository.Add("Response", response.Data);
|
_scopedRequestDataRepository.Add("Response", response.Data);
|
||||||
|
|
||||||
await _next.Invoke(context);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,10 +6,7 @@ using Ocelot.Library.Infrastructure.Responder;
|
|||||||
|
|
||||||
namespace Ocelot.Library.Middleware
|
namespace Ocelot.Library.Middleware
|
||||||
{
|
{
|
||||||
/// <summary>
|
public class HttpResponderMiddleware : OcelotMiddleware
|
||||||
/// Terminating middleware that is responsible for returning a http response to the client
|
|
||||||
/// </summary>
|
|
||||||
public class HttpResponderMiddleware
|
|
||||||
{
|
{
|
||||||
private readonly RequestDelegate _next;
|
private readonly RequestDelegate _next;
|
||||||
private readonly IHttpResponder _responder;
|
private readonly IHttpResponder _responder;
|
||||||
@ -18,6 +15,7 @@ namespace Ocelot.Library.Middleware
|
|||||||
public HttpResponderMiddleware(RequestDelegate next,
|
public HttpResponderMiddleware(RequestDelegate next,
|
||||||
IHttpResponder responder,
|
IHttpResponder responder,
|
||||||
IScopedRequestDataRepository scopedRequestDataRepository)
|
IScopedRequestDataRepository scopedRequestDataRepository)
|
||||||
|
:base(scopedRequestDataRepository)
|
||||||
{
|
{
|
||||||
_next = next;
|
_next = next;
|
||||||
_responder = responder;
|
_responder = responder;
|
||||||
@ -25,6 +23,18 @@ namespace Ocelot.Library.Middleware
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async Task Invoke(HttpContext context)
|
public async Task Invoke(HttpContext context)
|
||||||
|
{
|
||||||
|
await _next.Invoke(context);
|
||||||
|
|
||||||
|
if (PipelineError())
|
||||||
|
{
|
||||||
|
//todo obviously this needs to be better...prob look at response errors
|
||||||
|
// and make a decision i guess
|
||||||
|
var errors = GetPipelineErrors();
|
||||||
|
|
||||||
|
await _responder.CreateNotFoundResponse(context);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
var response = _scopedRequestDataRepository.Get<HttpResponseMessage>("Response");
|
var response = _scopedRequestDataRepository.Get<HttpResponseMessage>("Response");
|
||||||
|
|
||||||
@ -32,3 +42,4 @@ namespace Ocelot.Library.Middleware
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
34
src/Ocelot.Library/Middleware/OcelotMiddleware.cs
Normal file
34
src/Ocelot.Library/Middleware/OcelotMiddleware.cs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Ocelot.Library.Infrastructure.Repository;
|
||||||
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
|
|
||||||
|
namespace Ocelot.Library.Middleware
|
||||||
|
{
|
||||||
|
public class OcelotMiddleware
|
||||||
|
{
|
||||||
|
private readonly IScopedRequestDataRepository _scopedRequestDataRepository;
|
||||||
|
|
||||||
|
public OcelotMiddleware(IScopedRequestDataRepository scopedRequestDataRepository)
|
||||||
|
{
|
||||||
|
_scopedRequestDataRepository = scopedRequestDataRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetPipelineError(List<Error> errors)
|
||||||
|
{
|
||||||
|
_scopedRequestDataRepository.Add("OcelotMiddlewareError", true);
|
||||||
|
_scopedRequestDataRepository.Add("OcelotMiddlewareErrors", errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool PipelineError()
|
||||||
|
{
|
||||||
|
var response = _scopedRequestDataRepository.Get<bool>("OcelotMiddlewareError");
|
||||||
|
return response.Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Error> GetPipelineErrors()
|
||||||
|
{
|
||||||
|
var response = _scopedRequestDataRepository.Get<List<Error>>("OcelotMiddlewareErrors");
|
||||||
|
return response.Data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -17,6 +17,7 @@
|
|||||||
"Microsoft.Extensions.Logging.Debug": "1.0.0",
|
"Microsoft.Extensions.Logging.Debug": "1.0.0",
|
||||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
|
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
|
||||||
"Microsoft.AspNetCore.Http": "1.0.0",
|
"Microsoft.AspNetCore.Http": "1.0.0",
|
||||||
|
"System.Text.RegularExpressions": "4.1.0",
|
||||||
"YamlDotNet": "3.9.0"
|
"YamlDotNet": "3.9.0"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
using Microsoft.AspNetCore.Builder;
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Configuration.Memory;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
using Ocelot.Library.Infrastructure.Configuration;
|
using Ocelot.Library.Infrastructure.Configuration;
|
||||||
|
using Ocelot.Library.Infrastructure.Configuration.Yaml;
|
||||||
using Ocelot.Library.Infrastructure.DownstreamRouteFinder;
|
using Ocelot.Library.Infrastructure.DownstreamRouteFinder;
|
||||||
using Ocelot.Library.Infrastructure.Repository;
|
using Ocelot.Library.Infrastructure.Repository;
|
||||||
using Ocelot.Library.Infrastructure.RequestBuilder;
|
using Ocelot.Library.Infrastructure.RequestBuilder;
|
||||||
@ -26,6 +30,7 @@ namespace Ocelot
|
|||||||
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
|
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
|
||||||
.AddYamlFile("configuration.yaml")
|
.AddYamlFile("configuration.yaml")
|
||||||
.AddEnvironmentVariables();
|
.AddEnvironmentVariables();
|
||||||
|
|
||||||
Configuration = builder.Build();
|
Configuration = builder.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,10 +41,12 @@ namespace Ocelot
|
|||||||
{
|
{
|
||||||
services.AddOptions();
|
services.AddOptions();
|
||||||
|
|
||||||
services.Configure<Configuration>(Configuration);
|
services.Configure<YamlConfiguration>(Configuration);
|
||||||
|
|
||||||
// Add framework services.
|
// Add framework services.
|
||||||
services.AddSingleton<IUrlPathToUrlTemplateMatcher, UrlPathToUrlTemplateMatcher>();
|
services.AddSingleton<IOcelotConfiguration, OcelotConfiguration>();
|
||||||
|
services.AddSingleton<IUrlPathToUrlTemplateMatcher, RegExUrlMatcher>();
|
||||||
|
services.AddSingleton<ITemplateVariableNameAndValueFinder, TemplateVariableNameAndValueFinder>();
|
||||||
services.AddSingleton<IDownstreamUrlTemplateVariableReplacer, DownstreamUrlTemplateVariableReplacer>();
|
services.AddSingleton<IDownstreamUrlTemplateVariableReplacer, DownstreamUrlTemplateVariableReplacer>();
|
||||||
services.AddSingleton<IDownstreamRouteFinder, DownstreamRouteFinder>();
|
services.AddSingleton<IDownstreamRouteFinder, DownstreamRouteFinder>();
|
||||||
services.AddSingleton<IHttpRequester, HttpClientHttpRequester>();
|
services.AddSingleton<IHttpRequester, HttpClientHttpRequester>();
|
||||||
@ -58,6 +65,8 @@ namespace Ocelot
|
|||||||
|
|
||||||
loggerFactory.AddDebug();
|
loggerFactory.AddDebug();
|
||||||
|
|
||||||
|
app.UseHttpResponderMiddleware();
|
||||||
|
|
||||||
app.UseDownstreamRouteFinderMiddleware();
|
app.UseDownstreamRouteFinderMiddleware();
|
||||||
|
|
||||||
app.UserDownstreamUrlCreatorMiddleware();
|
app.UserDownstreamUrlCreatorMiddleware();
|
||||||
@ -65,8 +74,6 @@ namespace Ocelot
|
|||||||
app.UseHttpRequestBuilderMiddleware();
|
app.UseHttpRequestBuilderMiddleware();
|
||||||
|
|
||||||
app.UseHttpRequesterMiddleware();
|
app.UseHttpRequesterMiddleware();
|
||||||
|
|
||||||
app.UseHttpResponderMiddleware();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ using System.Net.Http;
|
|||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.TestHost;
|
using Microsoft.AspNetCore.TestHost;
|
||||||
using Ocelot.AcceptanceTests.Fake;
|
using Ocelot.AcceptanceTests.Fake;
|
||||||
using Ocelot.Library.Infrastructure.Configuration;
|
using Ocelot.Library.Infrastructure.Configuration.Yaml;
|
||||||
using Shouldly;
|
using Shouldly;
|
||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
@ -32,7 +32,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_return_response_404()
|
public void should_return_response_404()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenThereIsAConfiguration(new Configuration()))
|
this.Given(x => x.GivenThereIsAConfiguration(new YamlConfiguration()))
|
||||||
.And(x => x.GivenTheApiGatewayIsRunning())
|
.And(x => x.GivenTheApiGatewayIsRunning())
|
||||||
.When(x => x.WhenIGetUrlOnTheApiGateway("/"))
|
.When(x => x.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
.Then(x => x.ThenTheStatusCodeShouldBe(HttpStatusCode.NotFound))
|
.Then(x => x.ThenTheStatusCodeShouldBe(HttpStatusCode.NotFound))
|
||||||
@ -43,11 +43,11 @@ namespace Ocelot.AcceptanceTests
|
|||||||
public void should_return_response_200()
|
public void should_return_response_200()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879"))
|
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879"))
|
||||||
.And(x => x.GivenThereIsAConfiguration(new Configuration
|
.And(x => x.GivenThereIsAConfiguration(new YamlConfiguration
|
||||||
{
|
{
|
||||||
ReRoutes = new List<ReRoute>
|
ReRoutes = new List<YamlReRoute>
|
||||||
{
|
{
|
||||||
new ReRoute
|
new YamlReRoute
|
||||||
{
|
{
|
||||||
DownstreamTemplate = "http://localhost:51879/",
|
DownstreamTemplate = "http://localhost:51879/",
|
||||||
UpstreamTemplate = "/",
|
UpstreamTemplate = "/",
|
||||||
@ -66,11 +66,11 @@ namespace Ocelot.AcceptanceTests
|
|||||||
public void should_return_response_201()
|
public void should_return_response_201()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879"))
|
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879"))
|
||||||
.And(x => x.GivenThereIsAConfiguration(new Configuration
|
.And(x => x.GivenThereIsAConfiguration(new YamlConfiguration
|
||||||
{
|
{
|
||||||
ReRoutes = new List<ReRoute>
|
ReRoutes = new List<YamlReRoute>
|
||||||
{
|
{
|
||||||
new ReRoute
|
new YamlReRoute
|
||||||
{
|
{
|
||||||
DownstreamTemplate = "http://localhost:51879/",
|
DownstreamTemplate = "http://localhost:51879/",
|
||||||
UpstreamTemplate = "/",
|
UpstreamTemplate = "/",
|
||||||
@ -100,7 +100,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
_client = _server.CreateClient();
|
_client = _server.CreateClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenThereIsAConfiguration(Configuration configuration)
|
private void GivenThereIsAConfiguration(YamlConfiguration yamlConfiguration)
|
||||||
{
|
{
|
||||||
var serializer = new Serializer();
|
var serializer = new Serializer();
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
|
|
||||||
using (TextWriter writer = File.CreateText(_configurationPath))
|
using (TextWriter writer = File.CreateText(_configurationPath))
|
||||||
{
|
{
|
||||||
serializer.Serialize(writer, configuration);
|
serializer.Serialize(writer, yamlConfiguration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Ocelot.Library.Infrastructure.Configuration;
|
using Ocelot.Library.Infrastructure.Configuration.Yaml;
|
||||||
using Ocelot.Library.Infrastructure.Responses;
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
using Shouldly;
|
using Shouldly;
|
||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
@ -9,7 +9,7 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
{
|
{
|
||||||
public class ConfigurationValidationTests
|
public class ConfigurationValidationTests
|
||||||
{
|
{
|
||||||
private Library.Infrastructure.Configuration.Configuration _configuration;
|
private YamlConfiguration _yamlConfiguration;
|
||||||
private readonly IConfigurationValidator _configurationValidator;
|
private readonly IConfigurationValidator _configurationValidator;
|
||||||
private Response<ConfigurationValidationResult> _result;
|
private Response<ConfigurationValidationResult> _result;
|
||||||
|
|
||||||
@ -21,11 +21,11 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void configuration_is_valid_with_one_reroute()
|
public void configuration_is_valid_with_one_reroute()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenAConfiguration(new Library.Infrastructure.Configuration.Configuration()
|
this.Given(x => x.GivenAConfiguration(new YamlConfiguration()
|
||||||
{
|
{
|
||||||
ReRoutes = new List<ReRoute>
|
ReRoutes = new List<YamlReRoute>
|
||||||
{
|
{
|
||||||
new ReRoute
|
new YamlReRoute
|
||||||
{
|
{
|
||||||
DownstreamTemplate = "http://www.bbc.co.uk",
|
DownstreamTemplate = "http://www.bbc.co.uk",
|
||||||
UpstreamTemplate = "http://asdf.com"
|
UpstreamTemplate = "http://asdf.com"
|
||||||
@ -40,16 +40,16 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void configuration_is_not_valid_with_duplicate_reroutes()
|
public void configuration_is_not_valid_with_duplicate_reroutes()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenAConfiguration(new Library.Infrastructure.Configuration.Configuration()
|
this.Given(x => x.GivenAConfiguration(new YamlConfiguration()
|
||||||
{
|
{
|
||||||
ReRoutes = new List<ReRoute>
|
ReRoutes = new List<YamlReRoute>
|
||||||
{
|
{
|
||||||
new ReRoute
|
new YamlReRoute
|
||||||
{
|
{
|
||||||
DownstreamTemplate = "http://www.bbc.co.uk",
|
DownstreamTemplate = "http://www.bbc.co.uk",
|
||||||
UpstreamTemplate = "http://asdf.com"
|
UpstreamTemplate = "http://asdf.com"
|
||||||
},
|
},
|
||||||
new ReRoute
|
new YamlReRoute
|
||||||
{
|
{
|
||||||
DownstreamTemplate = "http://www.bbc.co.uk",
|
DownstreamTemplate = "http://www.bbc.co.uk",
|
||||||
UpstreamTemplate = "http://lol.com"
|
UpstreamTemplate = "http://lol.com"
|
||||||
@ -62,14 +62,14 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenAConfiguration(Library.Infrastructure.Configuration.Configuration configuration)
|
private void GivenAConfiguration(YamlConfiguration yamlConfiguration)
|
||||||
{
|
{
|
||||||
_configuration = configuration;
|
_yamlConfiguration = yamlConfiguration;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WhenIValidateTheConfiguration()
|
private void WhenIValidateTheConfiguration()
|
||||||
{
|
{
|
||||||
_result = _configurationValidator.IsValid(_configuration);
|
_result = _configurationValidator.IsValid(_yamlConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheResultIsValid()
|
private void ThenTheResultIsValid()
|
||||||
|
142
test/Ocelot.UnitTests/Configuration/OcelotConfigurationTests.cs
Normal file
142
test/Ocelot.UnitTests/Configuration/OcelotConfigurationTests.cs
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Moq;
|
||||||
|
using Ocelot.Library.Infrastructure.Configuration;
|
||||||
|
using Ocelot.Library.Infrastructure.Configuration.Yaml;
|
||||||
|
using Shouldly;
|
||||||
|
using TestStack.BDDfy;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Ocelot.UnitTests.Configuration
|
||||||
|
{
|
||||||
|
public class OcelotConfigurationTests
|
||||||
|
{
|
||||||
|
private readonly Mock<IOptions<YamlConfiguration>> _yamlConfig;
|
||||||
|
private OcelotConfiguration _config;
|
||||||
|
private YamlConfiguration _yamlConfiguration;
|
||||||
|
|
||||||
|
public OcelotConfigurationTests()
|
||||||
|
{
|
||||||
|
_yamlConfig = new Mock<IOptions<YamlConfiguration>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_create_template_pattern_that_matches_anything_to_end_of_string()
|
||||||
|
{
|
||||||
|
this.Given(x => x.GivenTheYamlConfigIs(new YamlConfiguration
|
||||||
|
{
|
||||||
|
ReRoutes = new List<YamlReRoute>
|
||||||
|
{
|
||||||
|
new YamlReRoute
|
||||||
|
{
|
||||||
|
UpstreamTemplate = "/api/products/{productId}",
|
||||||
|
DownstreamTemplate = "/products/{productId}",
|
||||||
|
UpstreamHttpMethod = "Get"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.When(x => x.WhenIInstanciateTheOcelotConfig())
|
||||||
|
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
|
||||||
|
{
|
||||||
|
new ReRoute("/products/{productId}","/api/products/{productId}", "Get", "/api/products/.*$")
|
||||||
|
}))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_create_template_pattern_that_matches_more_than_one_placeholder()
|
||||||
|
{
|
||||||
|
this.Given(x => x.GivenTheYamlConfigIs(new YamlConfiguration
|
||||||
|
{
|
||||||
|
ReRoutes = new List<YamlReRoute>
|
||||||
|
{
|
||||||
|
new YamlReRoute
|
||||||
|
{
|
||||||
|
UpstreamTemplate = "/api/products/{productId}/variants/{variantId}",
|
||||||
|
DownstreamTemplate = "/products/{productId}",
|
||||||
|
UpstreamHttpMethod = "Get"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.When(x => x.WhenIInstanciateTheOcelotConfig())
|
||||||
|
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
|
||||||
|
{
|
||||||
|
new ReRoute("/products/{productId}","/api/products/{productId}/variants/{variantId}", "Get", "/api/products/.*/variants/.*$")
|
||||||
|
}))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_create_template_pattern_that_matches_more_than_one_placeholder_with_trailing_slash()
|
||||||
|
{
|
||||||
|
this.Given(x => x.GivenTheYamlConfigIs(new YamlConfiguration
|
||||||
|
{
|
||||||
|
ReRoutes = new List<YamlReRoute>
|
||||||
|
{
|
||||||
|
new YamlReRoute
|
||||||
|
{
|
||||||
|
UpstreamTemplate = "/api/products/{productId}/variants/{variantId}/",
|
||||||
|
DownstreamTemplate = "/products/{productId}",
|
||||||
|
UpstreamHttpMethod = "Get"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.When(x => x.WhenIInstanciateTheOcelotConfig())
|
||||||
|
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
|
||||||
|
{
|
||||||
|
new ReRoute("/products/{productId}","/api/products/{productId}/variants/{variantId}/", "Get", "/api/products/.*/variants/.*/$")
|
||||||
|
}))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_create_template_pattern_that_matches_to_end_of_string()
|
||||||
|
{
|
||||||
|
this.Given(x => x.GivenTheYamlConfigIs(new YamlConfiguration
|
||||||
|
{
|
||||||
|
ReRoutes = new List<YamlReRoute>
|
||||||
|
{
|
||||||
|
new YamlReRoute
|
||||||
|
{
|
||||||
|
UpstreamTemplate = "/",
|
||||||
|
DownstreamTemplate = "/api/products/",
|
||||||
|
UpstreamHttpMethod = "Get"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.When(x => x.WhenIInstanciateTheOcelotConfig())
|
||||||
|
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
|
||||||
|
{
|
||||||
|
new ReRoute("/api/products/","/", "Get", "/$")
|
||||||
|
}))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheYamlConfigIs(YamlConfiguration yamlConfiguration)
|
||||||
|
{
|
||||||
|
_yamlConfiguration = yamlConfiguration;
|
||||||
|
_yamlConfig
|
||||||
|
.Setup(x => x.Value)
|
||||||
|
.Returns(_yamlConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WhenIInstanciateTheOcelotConfig()
|
||||||
|
{
|
||||||
|
_config = new OcelotConfiguration(_yamlConfig.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheReRoutesAre(List<ReRoute> expectedReRoutes)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _config.ReRoutes.Count; i++)
|
||||||
|
{
|
||||||
|
var result = _config.ReRoutes[i];
|
||||||
|
var expected = expectedReRoutes[i];
|
||||||
|
|
||||||
|
result.DownstreamTemplate.ShouldBe(expected.DownstreamTemplate);
|
||||||
|
result.UpstreamHttpMethod.ShouldBe(expected.UpstreamHttpMethod);
|
||||||
|
result.UpstreamTemplate.ShouldBe(expected.UpstreamTemplate);
|
||||||
|
result.UpstreamTemplatePattern.ShouldBe(expected.UpstreamTemplatePattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Microsoft.Extensions.Options;
|
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Library.Infrastructure.Configuration;
|
using Ocelot.Library.Infrastructure.Configuration;
|
||||||
using Ocelot.Library.Infrastructure.DownstreamRouteFinder;
|
using Ocelot.Library.Infrastructure.DownstreamRouteFinder;
|
||||||
@ -14,38 +13,35 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
public class DownstreamRouteFinderTests
|
public class DownstreamRouteFinderTests
|
||||||
{
|
{
|
||||||
private readonly IDownstreamRouteFinder _downstreamRouteFinder;
|
private readonly IDownstreamRouteFinder _downstreamRouteFinder;
|
||||||
private readonly Mock<IOptions<Library.Infrastructure.Configuration.Configuration>> _mockConfig;
|
private readonly Mock<IOcelotConfiguration> _mockConfig;
|
||||||
private readonly Mock<IUrlPathToUrlTemplateMatcher> _mockMatcher;
|
private readonly Mock<IUrlPathToUrlTemplateMatcher> _mockMatcher;
|
||||||
|
private readonly Mock<ITemplateVariableNameAndValueFinder> _finder;
|
||||||
private string _upstreamUrlPath;
|
private string _upstreamUrlPath;
|
||||||
private Response<DownstreamRoute> _result;
|
private Response<DownstreamRoute> _result;
|
||||||
private Response<DownstreamRoute> _response;
|
private Response<DownstreamRoute> _response;
|
||||||
private Library.Infrastructure.Configuration.Configuration _configuration;
|
private List<ReRoute> _reRoutesConfig;
|
||||||
private UrlMatch _match;
|
private Response<UrlMatch> _match;
|
||||||
private string _upstreamHttpMethod;
|
private string _upstreamHttpMethod;
|
||||||
|
|
||||||
public DownstreamRouteFinderTests()
|
public DownstreamRouteFinderTests()
|
||||||
{
|
{
|
||||||
_mockConfig = new Mock<IOptions<Library.Infrastructure.Configuration.Configuration>>();
|
_mockConfig = new Mock<IOcelotConfiguration>();
|
||||||
_mockMatcher = new Mock<IUrlPathToUrlTemplateMatcher>();
|
_mockMatcher = new Mock<IUrlPathToUrlTemplateMatcher>();
|
||||||
_downstreamRouteFinder = new Library.Infrastructure.DownstreamRouteFinder.DownstreamRouteFinder(_mockConfig.Object, _mockMatcher.Object);
|
_finder = new Mock<ITemplateVariableNameAndValueFinder>();
|
||||||
|
_downstreamRouteFinder = new Library.Infrastructure.DownstreamRouteFinder.DownstreamRouteFinder(_mockConfig.Object, _mockMatcher.Object, _finder.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_return_route()
|
public void should_return_route()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath"))
|
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath"))
|
||||||
.And(x => x.GivenTheConfigurationIs(new Library.Infrastructure.Configuration.Configuration {
|
.And(x => x.GivenTheTemplateVariableAndNameFinderReturns(new OkResponse<List<TemplateVariableNameAndValue>>(new List<TemplateVariableNameAndValue>())))
|
||||||
ReRoutes = new List<ReRoute>
|
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
|
||||||
{
|
{
|
||||||
new ReRoute()
|
new ReRoute("someDownstreamPath","someUpstreamPath", "Get", "someUpstreamPath")
|
||||||
{
|
|
||||||
UpstreamTemplate = "someUpstreamPath",
|
|
||||||
DownstreamTemplate = "someDownstreamPath",
|
|
||||||
UpstreamHttpMethod = "Get"
|
|
||||||
}
|
}
|
||||||
}
|
))
|
||||||
}))
|
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
|
||||||
.And(x => x.GivenTheUrlMatcherReturns(new UrlMatch(true, new List<TemplateVariableNameAndValue>(), "someDownstreamPath")))
|
|
||||||
.And(x => x.GivenTheUpstreamHttpMethodIs("Get"))
|
.And(x => x.GivenTheUpstreamHttpMethodIs("Get"))
|
||||||
.When(x => x.WhenICallTheFinder())
|
.When(x => x.WhenICallTheFinder())
|
||||||
.Then(
|
.Then(
|
||||||
@ -58,25 +54,14 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
public void should_return_correct_route_for_http_verb()
|
public void should_return_correct_route_for_http_verb()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath"))
|
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath"))
|
||||||
.And(x => x.GivenTheConfigurationIs(new Library.Infrastructure.Configuration.Configuration
|
.And(x => x.GivenTheTemplateVariableAndNameFinderReturns(new OkResponse<List<TemplateVariableNameAndValue>>(new List<TemplateVariableNameAndValue>())))
|
||||||
|
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
|
||||||
{
|
{
|
||||||
ReRoutes = new List<ReRoute>
|
new ReRoute("someDownstreamPath", "someUpstreamPath", "Get", string.Empty),
|
||||||
{
|
new ReRoute("someDownstreamPathForAPost", "someUpstreamPath", "Post", string.Empty)
|
||||||
new ReRoute()
|
|
||||||
{
|
|
||||||
UpstreamTemplate = "someUpstreamPath",
|
|
||||||
DownstreamTemplate = "someDownstreamPath",
|
|
||||||
UpstreamHttpMethod = "Get"
|
|
||||||
},
|
|
||||||
new ReRoute()
|
|
||||||
{
|
|
||||||
UpstreamTemplate = "someUpstreamPath",
|
|
||||||
DownstreamTemplate = "someDownstreamPathForAPost",
|
|
||||||
UpstreamHttpMethod = "Post"
|
|
||||||
}
|
}
|
||||||
}
|
))
|
||||||
}))
|
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
|
||||||
.And(x => x.GivenTheUrlMatcherReturns(new UrlMatch(true, new List<TemplateVariableNameAndValue>(), "someDownstreamPathForAPost")))
|
|
||||||
.And(x => x.GivenTheUpstreamHttpMethodIs("Post"))
|
.And(x => x.GivenTheUpstreamHttpMethodIs("Post"))
|
||||||
.When(x => x.WhenICallTheFinder())
|
.When(x => x.WhenICallTheFinder())
|
||||||
.Then(
|
.Then(
|
||||||
@ -88,19 +73,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
public void should_not_return_route()
|
public void should_not_return_route()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("somePath"))
|
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("somePath"))
|
||||||
.And(x => x.GivenTheConfigurationIs(new Library.Infrastructure.Configuration.Configuration
|
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
|
||||||
{
|
{
|
||||||
ReRoutes = new List<ReRoute>
|
new ReRoute("somPath", "somePath", "Get", "somePath")
|
||||||
{
|
|
||||||
new ReRoute()
|
|
||||||
{
|
|
||||||
UpstreamTemplate = "somePath",
|
|
||||||
DownstreamTemplate = "somPath",
|
|
||||||
UpstreamHttpMethod = "Get"
|
|
||||||
}
|
}
|
||||||
}
|
))
|
||||||
}))
|
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(false))))
|
||||||
.And(x => x.GivenTheUrlMatcherReturns(new UrlMatch(false, new List<TemplateVariableNameAndValue>(), null)))
|
|
||||||
.And(x => x.GivenTheUpstreamHttpMethodIs("Get"))
|
.And(x => x.GivenTheUpstreamHttpMethodIs("Get"))
|
||||||
.When(x => x.WhenICallTheFinder())
|
.When(x => x.WhenICallTheFinder())
|
||||||
.Then(
|
.Then(
|
||||||
@ -109,6 +87,13 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void GivenTheTemplateVariableAndNameFinderReturns(Response<List<TemplateVariableNameAndValue>> response)
|
||||||
|
{
|
||||||
|
_finder
|
||||||
|
.Setup(x => x.Find(It.IsAny<string>(), It.IsAny<string>()))
|
||||||
|
.Returns(response);
|
||||||
|
}
|
||||||
|
|
||||||
private void GivenTheUpstreamHttpMethodIs(string upstreamHttpMethod)
|
private void GivenTheUpstreamHttpMethodIs(string upstreamHttpMethod)
|
||||||
{
|
{
|
||||||
_upstreamHttpMethod = upstreamHttpMethod;
|
_upstreamHttpMethod = upstreamHttpMethod;
|
||||||
@ -122,10 +107,10 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
private void ThenTheUrlMatcherIsCalledCorrectly()
|
private void ThenTheUrlMatcherIsCalledCorrectly()
|
||||||
{
|
{
|
||||||
_mockMatcher
|
_mockMatcher
|
||||||
.Verify(x => x.Match(_upstreamUrlPath, _configuration.ReRoutes[0].UpstreamTemplate), Times.Once);
|
.Verify(x => x.Match(_upstreamUrlPath, _reRoutesConfig[0].UpstreamTemplate), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenTheUrlMatcherReturns(UrlMatch match)
|
private void GivenTheUrlMatcherReturns(Response<UrlMatch> match)
|
||||||
{
|
{
|
||||||
_match = match;
|
_match = match;
|
||||||
_mockMatcher
|
_mockMatcher
|
||||||
@ -133,12 +118,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.Returns(_match);
|
.Returns(_match);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenTheConfigurationIs(Library.Infrastructure.Configuration.Configuration configuration)
|
private void GivenTheConfigurationIs(List<ReRoute> reRoutesConfig)
|
||||||
{
|
{
|
||||||
_configuration = configuration;
|
_reRoutesConfig = reRoutesConfig;
|
||||||
_mockConfig
|
_mockConfig
|
||||||
.Setup(x => x.Value)
|
.Setup(x => x.ReRoutes)
|
||||||
.Returns(_configuration);
|
.Returns(_reRoutesConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenThereIsAnUpstreamUrlPath(string upstreamUrlPath)
|
private void GivenThereIsAnUpstreamUrlPath(string upstreamUrlPath)
|
||||||
|
@ -6,6 +6,7 @@ using System.Net.Http;
|
|||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Http.Internal;
|
using Microsoft.AspNetCore.Http.Internal;
|
||||||
using Ocelot.Library.Infrastructure.RequestBuilder;
|
using Ocelot.Library.Infrastructure.RequestBuilder;
|
||||||
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
using Shouldly;
|
using Shouldly;
|
||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
@ -22,7 +23,7 @@ namespace Ocelot.UnitTests.RequestBuilder
|
|||||||
private string _query;
|
private string _query;
|
||||||
private string _contentType;
|
private string _contentType;
|
||||||
private readonly IRequestBuilder _requestBuilder;
|
private readonly IRequestBuilder _requestBuilder;
|
||||||
private Request _result;
|
private Response<Request> _result;
|
||||||
|
|
||||||
public RequestBuilderTests()
|
public RequestBuilderTests()
|
||||||
{
|
{
|
||||||
@ -131,7 +132,7 @@ namespace Ocelot.UnitTests.RequestBuilder
|
|||||||
|
|
||||||
private void ThenTheCorrectQueryStringIsUsed(string expected)
|
private void ThenTheCorrectQueryStringIsUsed(string expected)
|
||||||
{
|
{
|
||||||
_result.HttpRequestMessage.RequestUri.Query.ShouldBe(expected);
|
_result.Data.HttpRequestMessage.RequestUri.Query.ShouldBe(expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenTheQueryStringIs(string query)
|
private void GivenTheQueryStringIs(string query)
|
||||||
@ -141,7 +142,7 @@ namespace Ocelot.UnitTests.RequestBuilder
|
|||||||
|
|
||||||
private void ThenTheCorrectCookiesAreUsed(IRequestCookieCollection expected)
|
private void ThenTheCorrectCookiesAreUsed(IRequestCookieCollection expected)
|
||||||
{
|
{
|
||||||
var resultCookies = _result.CookieContainer.GetCookies(new Uri(_downstreamUrl + _query));
|
var resultCookies = _result.Data.CookieContainer.GetCookies(new Uri(_downstreamUrl + _query));
|
||||||
var resultDictionary = resultCookies.Cast<Cookie>().ToDictionary(cook => cook.Name, cook => cook.Value);
|
var resultDictionary = resultCookies.Cast<Cookie>().ToDictionary(cook => cook.Name, cook => cook.Value);
|
||||||
|
|
||||||
foreach (var expectedCookie in expected)
|
foreach (var expectedCookie in expected)
|
||||||
@ -162,7 +163,7 @@ namespace Ocelot.UnitTests.RequestBuilder
|
|||||||
|
|
||||||
foreach (var expectedHeader in expectedHeaders)
|
foreach (var expectedHeader in expectedHeaders)
|
||||||
{
|
{
|
||||||
_result.HttpRequestMessage.Headers.ShouldContain(x => x.Key == expectedHeader.Key && x.Value.First() == expectedHeader.Value[0]);
|
_result.Data.HttpRequestMessage.Headers.ShouldContain(x => x.Key == expectedHeader.Key && x.Value.First() == expectedHeader.Value[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,7 +173,7 @@ namespace Ocelot.UnitTests.RequestBuilder
|
|||||||
|
|
||||||
foreach (var expectedHeader in expectedHeaders)
|
foreach (var expectedHeader in expectedHeaders)
|
||||||
{
|
{
|
||||||
_result.HttpRequestMessage.Content.Headers.ShouldContain(x => x.Key == expectedHeader.Key
|
_result.Data.HttpRequestMessage.Content.Headers.ShouldContain(x => x.Key == expectedHeader.Key
|
||||||
&& x.Value.First() == expectedHeader.Value[0]
|
&& x.Value.First() == expectedHeader.Value[0]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -207,17 +208,17 @@ namespace Ocelot.UnitTests.RequestBuilder
|
|||||||
|
|
||||||
private void ThenTheCorrectDownstreamUrlIsUsed(string expected)
|
private void ThenTheCorrectDownstreamUrlIsUsed(string expected)
|
||||||
{
|
{
|
||||||
_result.HttpRequestMessage.RequestUri.AbsoluteUri.ShouldBe(expected);
|
_result.Data.HttpRequestMessage.RequestUri.AbsoluteUri.ShouldBe(expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheCorrectHttpMethodIsUsed(HttpMethod expected)
|
private void ThenTheCorrectHttpMethodIsUsed(HttpMethod expected)
|
||||||
{
|
{
|
||||||
_result.HttpRequestMessage.Method.Method.ShouldBe(expected.Method);
|
_result.Data.HttpRequestMessage.Method.Method.ShouldBe(expected.Method);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheCorrectContentIsUsed(HttpContent expected)
|
private void ThenTheCorrectContentIsUsed(HttpContent expected)
|
||||||
{
|
{
|
||||||
_result.HttpRequestMessage.Content.ReadAsStringAsync().Result.ShouldBe(expected.ReadAsStringAsync().Result);
|
_result.Data.HttpRequestMessage.Content.ReadAsStringAsync().Result.ShouldBe(expected.ReadAsStringAsync().Result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
156
test/Ocelot.UnitTests/UrlMatcher/RegExUrlMatcherTests.cs
Normal file
156
test/Ocelot.UnitTests/UrlMatcher/RegExUrlMatcherTests.cs
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
|
using Ocelot.Library.Infrastructure.UrlMatcher;
|
||||||
|
using Shouldly;
|
||||||
|
using TestStack.BDDfy;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Ocelot.UnitTests.UrlMatcher
|
||||||
|
{
|
||||||
|
public class RegExUrlMatcherTests
|
||||||
|
{
|
||||||
|
private readonly IUrlPathToUrlTemplateMatcher _urlMatcher;
|
||||||
|
private string _downstreamUrlPath;
|
||||||
|
private string _downstreamPathTemplate;
|
||||||
|
private Response<UrlMatch> _result;
|
||||||
|
|
||||||
|
public RegExUrlMatcherTests()
|
||||||
|
{
|
||||||
|
_urlMatcher = new RegExUrlMatcher();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_find_match_when_template_smaller_than_valid_path()
|
||||||
|
{
|
||||||
|
this.Given(x => x.GivenIHaveAUpstreamPath("/api/products/2354325435624623464235"))
|
||||||
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("/api/products/.*$"))
|
||||||
|
.When(x => x.WhenIMatchThePaths())
|
||||||
|
.And(x => x.ThenTheResultIsTrue())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_not_find_match()
|
||||||
|
{
|
||||||
|
this.Given(x => x.GivenIHaveAUpstreamPath("/api/values"))
|
||||||
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("/$"))
|
||||||
|
.When(x => x.WhenIMatchThePaths())
|
||||||
|
.And(x => x.ThenTheResultIsFalse())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void can_match_down_stream_url()
|
||||||
|
{
|
||||||
|
this.Given(x => x.GivenIHaveAUpstreamPath(""))
|
||||||
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("$"))
|
||||||
|
.When(x => x.WhenIMatchThePaths())
|
||||||
|
.And(x => x.ThenTheResultIsTrue())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void can_match_down_stream_url_with_no_slash()
|
||||||
|
{
|
||||||
|
this.Given(x => x.GivenIHaveAUpstreamPath("api"))
|
||||||
|
.Given(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("api$"))
|
||||||
|
.When(x => x.WhenIMatchThePaths())
|
||||||
|
.Then(x => x.ThenTheResultIsTrue())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void can_match_down_stream_url_with_one_slash()
|
||||||
|
{
|
||||||
|
this.Given(x => x.GivenIHaveAUpstreamPath("api/"))
|
||||||
|
.Given(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("api/$"))
|
||||||
|
.When(x => x.WhenIMatchThePaths())
|
||||||
|
.Then(x => x.ThenTheResultIsTrue())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void can_match_down_stream_url_with_downstream_template()
|
||||||
|
{
|
||||||
|
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/"))
|
||||||
|
.Given(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("api/product/products/$"))
|
||||||
|
.When(x => x.WhenIMatchThePaths())
|
||||||
|
.Then(x => x.ThenTheResultIsTrue())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void can_match_down_stream_url_with_downstream_template_with_one_place_holder()
|
||||||
|
{
|
||||||
|
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1"))
|
||||||
|
.Given(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("api/product/products/.*$"))
|
||||||
|
.When(x => x.WhenIMatchThePaths())
|
||||||
|
.Then(x => x.ThenTheResultIsTrue())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void can_match_down_stream_url_with_downstream_template_with_two_place_holders()
|
||||||
|
{
|
||||||
|
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/2"))
|
||||||
|
.Given(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("api/product/products/.*/.*$"))
|
||||||
|
.When(x => x.WhenIMatchThePaths())
|
||||||
|
.Then(x => x.ThenTheResultIsTrue())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void can_match_down_stream_url_with_downstream_template_with_two_place_holders_seperated_by_something()
|
||||||
|
{
|
||||||
|
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2"))
|
||||||
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("api/product/products/.*/categories/.*$"))
|
||||||
|
.When(x => x.WhenIMatchThePaths())
|
||||||
|
.Then(x => x.ThenTheResultIsTrue())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void can_match_down_stream_url_with_downstream_template_with_three_place_holders_seperated_by_something()
|
||||||
|
{
|
||||||
|
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/123"))
|
||||||
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("api/product/products/.*/categories/.*/variant/.*$"))
|
||||||
|
.When(x => x.WhenIMatchThePaths())
|
||||||
|
.Then(x => x.ThenTheResultIsTrue())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void can_match_down_stream_url_with_downstream_template_with_three_place_holders()
|
||||||
|
{
|
||||||
|
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/"))
|
||||||
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("api/product/products/.*/categories/.*/variant/$"))
|
||||||
|
.When(x => x.WhenIMatchThePaths())
|
||||||
|
.Then(x => x.ThenTheResultIsTrue())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenIHaveAUpstreamPath(string downstreamPath)
|
||||||
|
{
|
||||||
|
_downstreamUrlPath = downstreamPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenIHaveAnUpstreamUrlTemplatePattern(string downstreamUrlTemplate)
|
||||||
|
{
|
||||||
|
_downstreamPathTemplate = downstreamUrlTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WhenIMatchThePaths()
|
||||||
|
{
|
||||||
|
_result = _urlMatcher.Match(_downstreamUrlPath, _downstreamPathTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheResultIsTrue()
|
||||||
|
{
|
||||||
|
_result.Data.Match.ShouldBeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheResultIsFalse()
|
||||||
|
{
|
||||||
|
_result.Data.Match.ShouldBeFalse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
using Ocelot.Library.Infrastructure.UrlMatcher;
|
using Ocelot.Library.Infrastructure.UrlMatcher;
|
||||||
using Shouldly;
|
using Shouldly;
|
||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
@ -9,33 +10,14 @@ namespace Ocelot.UnitTests.UrlMatcher
|
|||||||
{
|
{
|
||||||
public class UrlPathToUrlTemplateMatcherTests
|
public class UrlPathToUrlTemplateMatcherTests
|
||||||
{
|
{
|
||||||
private readonly IUrlPathToUrlTemplateMatcher _urlMatcher;
|
private readonly ITemplateVariableNameAndValueFinder _finder;
|
||||||
private string _downstreamUrlPath;
|
private string _downstreamUrlPath;
|
||||||
private string _downstreamPathTemplate;
|
private string _downstreamPathTemplate;
|
||||||
private UrlMatch _result;
|
private Response<List<TemplateVariableNameAndValue>> _result;
|
||||||
|
|
||||||
public UrlPathToUrlTemplateMatcherTests()
|
public UrlPathToUrlTemplateMatcherTests()
|
||||||
{
|
{
|
||||||
_urlMatcher = new UrlPathToUrlTemplateMatcher();
|
_finder = new TemplateVariableNameAndValueFinder();
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void should_find_match_when_template_smaller_than_valid_path()
|
|
||||||
{
|
|
||||||
this.Given(x => x.GivenIHaveAUpstreamPath("/api/products/2354325435624623464235"))
|
|
||||||
.And(x => x.GivenIHaveAnUpstreamUrlTemplate("/api/products/{productId}"))
|
|
||||||
.When(x => x.WhenIMatchThePaths())
|
|
||||||
.And(x => x.ThenTheResultIsTrue())
|
|
||||||
.BDDfy();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void should_not_find_match()
|
|
||||||
{
|
|
||||||
this.Given(x => x.GivenIHaveAUpstreamPath("/api/values"))
|
|
||||||
.And(x => x.GivenIHaveAnUpstreamUrlTemplate("/"))
|
|
||||||
.When(x => x.WhenIMatchThePaths())
|
|
||||||
.And(x => x.ThenTheResultIsFalse())
|
|
||||||
.BDDfy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -43,10 +25,8 @@ namespace Ocelot.UnitTests.UrlMatcher
|
|||||||
{
|
{
|
||||||
this.Given(x => x.GivenIHaveAUpstreamPath(""))
|
this.Given(x => x.GivenIHaveAUpstreamPath(""))
|
||||||
.And(x => x.GivenIHaveAnUpstreamUrlTemplate(""))
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplate(""))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIFindTheUrlVariableNamesAndValues())
|
||||||
.And(x => x.ThenTheResultIsTrue())
|
|
||||||
.And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>()))
|
.And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>()))
|
||||||
.And(x => x.ThenTheDownstreamUrlTemplateIs(""))
|
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,10 +35,8 @@ namespace Ocelot.UnitTests.UrlMatcher
|
|||||||
{
|
{
|
||||||
this.Given(x => x.GivenIHaveAUpstreamPath("api"))
|
this.Given(x => x.GivenIHaveAUpstreamPath("api"))
|
||||||
.Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api"))
|
.Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api"))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIFindTheUrlVariableNamesAndValues())
|
||||||
.Then(x => x.ThenTheResultIsTrue())
|
|
||||||
.And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>()))
|
.And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>()))
|
||||||
.And(x => x.ThenTheDownstreamUrlTemplateIs("api"))
|
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,10 +45,8 @@ namespace Ocelot.UnitTests.UrlMatcher
|
|||||||
{
|
{
|
||||||
this.Given(x => x.GivenIHaveAUpstreamPath("api/"))
|
this.Given(x => x.GivenIHaveAUpstreamPath("api/"))
|
||||||
.Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/"))
|
.Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/"))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIFindTheUrlVariableNamesAndValues())
|
||||||
.Then(x => x.ThenTheResultIsTrue())
|
|
||||||
.And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>()))
|
.And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>()))
|
||||||
.And(x => x.ThenTheDownstreamUrlTemplateIs("api/"))
|
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,10 +55,8 @@ namespace Ocelot.UnitTests.UrlMatcher
|
|||||||
{
|
{
|
||||||
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/"))
|
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/"))
|
||||||
.Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/"))
|
.Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/"))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIFindTheUrlVariableNamesAndValues())
|
||||||
.Then(x => x.ThenTheResultIsTrue())
|
|
||||||
.And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>()))
|
.And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>()))
|
||||||
.And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/"))
|
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,10 +70,8 @@ namespace Ocelot.UnitTests.UrlMatcher
|
|||||||
|
|
||||||
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1"))
|
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1"))
|
||||||
.Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}"))
|
.Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}"))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIFindTheUrlVariableNamesAndValues())
|
||||||
.Then(x => x.ThenTheResultIsTrue())
|
|
||||||
.And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates))
|
.And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates))
|
||||||
.And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/{productId}"))
|
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,10 +86,8 @@ namespace Ocelot.UnitTests.UrlMatcher
|
|||||||
|
|
||||||
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/2"))
|
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/2"))
|
||||||
.Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}/{categoryId}"))
|
.Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}/{categoryId}"))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIFindTheUrlVariableNamesAndValues())
|
||||||
.Then(x => x.ThenTheResultIsTrue())
|
|
||||||
.And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates))
|
.And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates))
|
||||||
.And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/{productId}/{categoryId}"))
|
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,10 +102,8 @@ namespace Ocelot.UnitTests.UrlMatcher
|
|||||||
|
|
||||||
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2"))
|
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2"))
|
||||||
.And(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}"))
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}"))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIFindTheUrlVariableNamesAndValues())
|
||||||
.Then(x => x.ThenTheResultIsTrue())
|
|
||||||
.And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates))
|
.And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates))
|
||||||
.And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/{productId}/categories/{categoryId}"))
|
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,10 +119,8 @@ namespace Ocelot.UnitTests.UrlMatcher
|
|||||||
|
|
||||||
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/123"))
|
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/123"))
|
||||||
.And(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}/variant/{variantId}"))
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}/variant/{variantId}"))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIFindTheUrlVariableNamesAndValues())
|
||||||
.Then(x => x.ThenTheResultIsTrue())
|
|
||||||
.And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates))
|
.And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates))
|
||||||
.And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/{productId}/categories/{categoryId}/variant/{variantId}"))
|
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,10 +135,8 @@ namespace Ocelot.UnitTests.UrlMatcher
|
|||||||
|
|
||||||
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/"))
|
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/"))
|
||||||
.And(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}/variant/"))
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}/variant/"))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIFindTheUrlVariableNamesAndValues())
|
||||||
.Then(x => x.ThenTheResultIsTrue())
|
|
||||||
.And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates))
|
.And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates))
|
||||||
.And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/{productId}/categories/{categoryId}/variant/"))
|
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,16 +144,12 @@ namespace Ocelot.UnitTests.UrlMatcher
|
|||||||
{
|
{
|
||||||
foreach (var expectedResult in expectedResults)
|
foreach (var expectedResult in expectedResults)
|
||||||
{
|
{
|
||||||
var result = _result.TemplateVariableNameAndValues
|
var result = _result.Data
|
||||||
.First(t => t.TemplateVariableName == expectedResult.TemplateVariableName);
|
.First(t => t.TemplateVariableName == expectedResult.TemplateVariableName);
|
||||||
result.TemplateVariableValue.ShouldBe(expectedResult.TemplateVariableValue);
|
result.TemplateVariableValue.ShouldBe(expectedResult.TemplateVariableValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheDownstreamUrlTemplateIs(string expectedDownstreamUrlTemplate)
|
|
||||||
{
|
|
||||||
_result.DownstreamUrlTemplate.ShouldBe(expectedDownstreamUrlTemplate);
|
|
||||||
}
|
|
||||||
private void GivenIHaveAUpstreamPath(string downstreamPath)
|
private void GivenIHaveAUpstreamPath(string downstreamPath)
|
||||||
{
|
{
|
||||||
_downstreamUrlPath = downstreamPath;
|
_downstreamUrlPath = downstreamPath;
|
||||||
@ -200,19 +160,9 @@ namespace Ocelot.UnitTests.UrlMatcher
|
|||||||
_downstreamPathTemplate = downstreamUrlTemplate;
|
_downstreamPathTemplate = downstreamUrlTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WhenIMatchThePaths()
|
private void WhenIFindTheUrlVariableNamesAndValues()
|
||||||
{
|
{
|
||||||
_result = _urlMatcher.Match(_downstreamUrlPath, _downstreamPathTemplate);
|
_result = _finder.Find(_downstreamUrlPath, _downstreamPathTemplate);
|
||||||
}
|
|
||||||
|
|
||||||
private void ThenTheResultIsTrue()
|
|
||||||
{
|
|
||||||
_result.Match.ShouldBeTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ThenTheResultIsFalse()
|
|
||||||
{
|
|
||||||
_result.Match.ShouldBeFalse();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Ocelot.Library.Infrastructure.DownstreamRouteFinder;
|
using Ocelot.Library.Infrastructure.DownstreamRouteFinder;
|
||||||
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
using Ocelot.Library.Infrastructure.UrlMatcher;
|
using Ocelot.Library.Infrastructure.UrlMatcher;
|
||||||
using Ocelot.Library.Infrastructure.UrlTemplateReplacer;
|
using Ocelot.Library.Infrastructure.UrlTemplateReplacer;
|
||||||
using Shouldly;
|
using Shouldly;
|
||||||
@ -11,7 +12,7 @@ namespace Ocelot.UnitTests.UrlTemplateReplacer
|
|||||||
public class UpstreamUrlPathTemplateVariableReplacerTests
|
public class UpstreamUrlPathTemplateVariableReplacerTests
|
||||||
{
|
{
|
||||||
private DownstreamRoute _downstreamRoute;
|
private DownstreamRoute _downstreamRoute;
|
||||||
private string _result;
|
private Response<string> _result;
|
||||||
private readonly IDownstreamUrlTemplateVariableReplacer _downstreamUrlPathReplacer;
|
private readonly IDownstreamUrlTemplateVariableReplacer _downstreamUrlPathReplacer;
|
||||||
|
|
||||||
public UpstreamUrlPathTemplateVariableReplacerTests()
|
public UpstreamUrlPathTemplateVariableReplacerTests()
|
||||||
@ -135,7 +136,7 @@ namespace Ocelot.UnitTests.UrlTemplateReplacer
|
|||||||
|
|
||||||
private void ThenTheDownstreamUrlPathIsReturned(string expected)
|
private void ThenTheDownstreamUrlPathIsReturned(string expected)
|
||||||
{
|
{
|
||||||
_result.ShouldBe(expected);
|
_result.Data.ShouldBe(expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user