New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#658 Change upstream Regex to account for blank placeholders #1333
base: develop
Are you sure you want to change the base?
Conversation
@AndyConlisk I don't see develop branch in your fork! Your fork is too old. Could you Sync fork please? So, new develop branch will occur with all top commits! Could you add me as collaborator to your forked repo please? I will create develop branch and make it default. |
@skyflyer Hi Miha! |
So, I'm not sure if my rationale is sound, but this does not seem to work, at least not for the case I reported in the issue. First, do understand, that we're not using Ocelot anymore (the project that was the consumer of this library unfortunately died some time ago). Also understand that I'm not in a position to really review the code, as I'm not really acquainted with the codebase nor the roadmap and the design of the library. So take the following comments with that in mind. 😄 The general idea was that ocelot lib would route requests coming to In order to verify this behaviour, I cloned the develop branch from the main repo and "squash merged" the PR 1333 into that, so the changes are applied on top of the latest develop bits. I then used a simple config (see below) and tried to request the resources. I've setup python's simple http server (
Simple config{
"Routes": [
{
"DownstreamPathTemplate": "/{id}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 8000
}
],
"UpstreamPathTemplate": "/api/{id}",
"UpstreamHttpMethod": [ "Get", "Post" ]
}
],
"GlobalConfiguration": {
"BaseUrl": "https://localhost:5000"
}
} And here is the Program.csusing Ocelot.Middleware;
using Ocelot.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddJsonFile("ocelot.json");
builder.Services.AddOcelot(builder.Configuration);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.UseOcelot().Wait();
app.Run(); |
Thanks! |
@raman-m I have made the develop branch to be the default branch. |
Thanks for user scenarios. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AndyConlisk
Although the code looks solid, but it can be improved. 👇
${\color{orange}There\ are\ no\ new\ tests!}$
The new code blocks are not covered by unit tests.
There are no unit tests for user scenarios from the linked issue.
Also, there are no acceptance tests to make sure Ocelot pipeline will handle all user scenarios correctly.
@@ -9,6 +9,7 @@ namespace Ocelot.Configuration.Creator | |||
public class UpstreamTemplatePatternCreator : IUpstreamTemplatePatternCreator | |||
{ | |||
private const string RegExMatchOneOrMoreOfEverything = ".+"; | |||
private const string RegExMatchLastPlaceHolderZeroOrMoreOfEverything = "(|/.+|/[\\?&#].+)"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
What about URL encoded queries including
everything
case?
Should we add%
to the set of chars[\\?&#]
? -
The 2nd case of having something after last slash char (everything-case) is defined by expression which matches by
.+
quantifier. Can we replace all reg-expression like that:(/[\\?&#].*)
?
@@ -52,7 +53,15 @@ public UpstreamPathTemplate Create(IRoute route) | |||
var indexOfNextForwardSlash = upstreamTemplate.IndexOf("/", indexOfPlaceholder, StringComparison.Ordinal); | |||
if (indexOfNextForwardSlash < indexOfPlaceholder || (containsQueryString && upstreamTemplate.IndexOf('?', StringComparison.Ordinal) < upstreamTemplate.IndexOf(placeholders[i], StringComparison.Ordinal))) | |||
{ | |||
upstreamTemplate = upstreamTemplate.Replace(placeholders[i], RegExMatchOneOrMoreOfEverything); | |||
if (upstreamTemplate[indexOfPlaceholder - 1] == '/') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you look at line 77 please?
Is not the same case when the string ends with slash?
delimiter = '&'; | ||
nextDelimiter = '&'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be one line assignment
delimiter = '&'; | |
nextDelimiter = '&'; | |
delimiter = nextDelimiter = '&'; |
delimiter = '?'; | ||
nextDelimiter = '?'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
delimiter = '?'; | |
nextDelimiter = '?'; | |
delimiter = nextDelimiter = '?'; |
else if (TemplateDoesNotEndInForwardSlash(pathTemplate) && IsLastPlaceholder(path, counterForPath, pathTemplate)) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code for this if-block was copied from lines 26-46.
Based on the function of code snippet, why not to define private helper-method to be reused in both places?
Use range operator
…ance data and can be marked as static
…an be marked as static
… characters: should_*
@AndyConlisk Do you have time to fix code review issues? |
I don't know when I will have time to write the new unit tests. I can try in the near future, but I can't give a solid commitment at this time. |
@AndyConlisk commented on Nov 7 Lazy bones! 😉 |
Fixes #658
Proposed Changes
Regex
and to account for blank last placeholder.