Skip to content
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

Improved PathSpec handling for servletName & pathInfo #7947

Merged
merged 17 commits into from Jun 7, 2022

Conversation

joakime
Copy link
Contributor

@joakime joakime commented May 2, 2022

Introduction of MatchedResource and MatchedPath to capture the results of a PathSpec match.

Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
@joakime joakime self-assigned this May 2, 2022
@joakime joakime added this to In progress in Jetty 9.4.47 - 🧊 FROZEN 🥶 via automation May 2, 2022
Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
@joakime joakime linked an issue May 3, 2022 that may be closed by this pull request
Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
@joakime joakime requested a review from gregw May 4, 2022 12:08
Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
@joakime joakime marked this pull request as ready for review May 5, 2022 17:09
Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
Copy link
Contributor

@gregw gregw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few things from a quick look through.
I don't love that we are not optimizing if there are Regex patterns, but I think that can be a TODO for later.

{
_exactMap = new ArrayTernaryTrie<>((ArrayTernaryTrie<MappedResource<E>>)_exactMap, 1.5);
// This is not a Servlet mapping, turn off optimization on Exact
_optimizedExact = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel that we probably can do optimized exact matches, even for regex etc. The Trie maps to a MappedResource that includes the PathSpec, so if match produces a non ServletPathSpec match, then we know we have to run it again to ensure we match any groups etc.

But maybe this is OK for now. Perhaps add a TODO to investigate if an exact map can be done.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets punt on optimized regex for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some comments about the concerns on exact/prefix/suffix and non-servlet path specs

{
_prefixMap = new ArrayTernaryTrie<>((ArrayTernaryTrie<MappedResource<E>>)_prefixMap, 1.5);
// This is not a Servlet mapping, turn off optimization on Prefix
_optimizedPrefix = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, we should be able to extract the prefix from any PREFIX_GLOB and put that in the Trie.
So again, for now add a TODO to optimize later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not quite as easy as you think.
The comments added show what needs to be resolved.
TODO added as well.

else
{
// This is not a Servlet mapping, turn off optimization on Suffix
_optimizedSuffix = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm I really don't like all these optimized booleans. Might just be better to null out the map/trie and have a null mean don't look up. That is a single test rather than always testing boolean then looking at the map/trie

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That means creating the Trie anew with every .add() or .put()

Jetty 9.4.47 - 🧊 FROZEN 🥶 automation moved this from In progress to Review in progress May 12, 2022
gregw
gregw previously requested changes May 13, 2022
{
case EXACT:
if (_declaration.equals(path))
return MatchedPath.from(path, null);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a final field as it will always be the immutable MatchedPath.from(_declaration, null)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

final where? if you have multiple PathSpecs, you have multiple final fields, which means a lookup/map again.

Comment on lines 297 to 306
if (isWildcardMatch(path))
{
String pathMatch = path;
String pathInfo = null;
if (path.length() != (_specLength - 2))
{
pathMatch = path.substring(0, _specLength - 2);
pathInfo = path.substring(_specLength - 2);
}
return MatchedPath.from(pathMatch, pathInfo);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also needs to avoid allocation in the common case of "/foo" matching "/foo/*"

Suggested change
if (isWildcardMatch(path))
{
String pathMatch = path;
String pathInfo = null;
if (path.length() != (_specLength - 2))
{
pathMatch = path.substring(0, _specLength - 2);
pathInfo = path.substring(_specLength - 2);
}
return MatchedPath.from(pathMatch, pathInfo);
if (isWildcardMatch(path))
{
if (path.length() == (_specLength - 2))
return finalFieldAllocatedInConstructor;
String pathMatch = anotherFinalFiledAllocatedInConstructor ;
String pathInfo = path.substring(_specLength - 2);
return MatchedPath.from(pathMatch, pathInfo);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll have a map of values, mapping each PathSpec and potential path.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pathSpec itself should know it's prefix, so that is what is returned. No map needed.

@gregw
Copy link
Contributor

gregw commented May 16, 2022

@joakime do you want me to have a go at fixing some of these issues?

+ Implemented recalculations
+ Added more comments

Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
@joakime
Copy link
Contributor Author

joakime commented May 16, 2022

I addressed most of the review comments.

The comments about final fields for various things don't make much sense to me, as we are dealing with multiple PathSpec objects in the collection, so having a final field make sense will result in another Map lookup, which kinda defeats the whole final field benefit.

If you can make it work without a new collection/trie/etc, give it a whirl.

@gregw
Copy link
Contributor

gregw commented May 17, 2022

I'll do a PR against this PR addressing some of my performance concerns.... good task for on the train/plane tomorrow.

@joakime joakime added the Sponsored This issue affects a user with a commercial support agreement label May 23, 2022
@joakime
Copy link
Contributor Author

joakime commented Jun 2, 2022

@gregw 🚩 bump 🚩 : this need attention for the next release.

@gregw
Copy link
Contributor

gregw commented Jun 3, 2022

Ack

@gregw gregw self-requested a review June 3, 2022 22:45
@gregw
Copy link
Contributor

gregw commented Jun 3, 2022

@joakime I pushed a change to this branch that should improve performance.
You'll need to get somebody else to review now.

@gregw gregw dismissed their stale review June 4, 2022 03:00

contributing now

@joakime
Copy link
Contributor Author

joakime commented Jun 6, 2022

+1 from me.
Now lets get @janbartel @lachlan-roberts @sbordet or @lorban to review it (and hopefully approve it)

Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
@sbordet sbordet self-requested a review June 7, 2022 17:58
Jetty 9.4.47 - 🧊 FROZEN 🥶 automation moved this from Review in progress to Reviewer approved Jun 7, 2022
@joakime joakime merged commit 5b4d1dd into jetty-9.4.x Jun 7, 2022
Jetty 9.4.47 - 🧊 FROZEN 🥶 automation moved this from Reviewer approved to Done Jun 7, 2022
@joakime joakime deleted the fix/jetty-9.4.x-improved-regexpathspec branch June 7, 2022 19:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement Sponsored This issue affects a user with a commercial support agreement
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

Better Servlet PathMappings for Regex
3 participants