fix(pathmap): leave the URL unchanged when a script mapping has no engine - #3452
Merged
Merged
Conversation
…gine
A path mapping whose replacement names a script engine that is not registered,
typically a groovy: mapping saved before 15.9 on an installation without
fess-script-groovy, logs that the replacement "is used as a plain replacement"
and then fails on every URL it matches. The fallback in
PathMappingHelper#resolveEngineMatcher hands the whole replacement to
Matcher#replaceAll, which reads it as a regular-expression replacement: the
${...} of a Groovy GString is a named-group reference, so the call throws
IllegalArgumentException ("named capturing group is missing trailing '}'").
PathMapping#process catches it, logs a warning with the stack trace and returns
the URL unchanged, on every call. The replacement the first warning announces
never happens.
Group references in that fallback are intended, but not for scripts. 15.8.0
sent every replacement except a groovy: one through Matcher#replaceAll, and the
path mapping guide describes a replacement whose prefix is not a registered
engine, such as https://, as a plain regular-expression replacement. That path
is unchanged, $1 included.
A replacement whose prefix is one of the script types Fess records (groovy,
javascript) is script text, and neither reading of it gives a mapping anyone
wrote: as a regular-expression replacement it throws on ${...}, and inserted
literally it turns every matching URL into the script, which a crawl-time
mapping would then index. Such a mapping is now not applied. The URL is left as
it is, and the missing engine is still reported once per mapping, with the
warning saying the mapping is not applied. A document boost rule without its
engine already behaves the same way and boosts nothing.
test_replaceUrl_missingGroovyEngineIsPlainReplacement pinned the literal result
(groovy:url becoming groovy:urla.html); it is renamed to
test_replaceUrl_missingGroovyEngineLeavesUrlUnchanged and expects the URL
unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Found while verifying the 15.8 → 15.9 upgrade path. On an installation upgraded without
fess-script-groovy, a path mapping with a Groovy replacement such asmaps nothing, and the log says something else happened:
When the engine is missing,
PathMappingHelper#resolveEngineMatcherfalls back tom.replaceAll(replacement).Matcher#replaceAllreads its argument as a regular-expression replacement, so the${...}of a GString is taken as a named-group reference and the call throws.PathMapping#processcatches the exception, logs it with its stack trace and returns the URL unchanged, and it does so on every call: once per matching search result for a display mapping, and once per matching document for a crawl-time one. The "plain replacement" the first warning announces never happens.Intended behaviour of the fallback
Group references in that fallback are intended, but not for scripts:
groovy:one throughMatcher#replaceAll, andpathmap-guide.rstdescribes a replacement whose prefix is not a registered engine (https://…) as a plain regular-expression replacement.$1has always worked there.groovy:replacement was always evaluated as a script and never went throughreplaceAll. Falling back to a plain replacement when its engine is missing is new in 15.9 (feat(script)!: default to JavaScript and treat an unset script type as Groovy #3345).Change
SCRIPT_ENGINE_NAMES(groovy,javascript) and that engine is not registered, the mapping is not applied: its matcher function returns the URL unchanged. The warning is still logged once per mapping, and now says the mapping is not applied.Matcher#replaceAll,$1included.The other option was to insert the script literally. That also stops the exception, but every matching URL would become the script text, and a crawl-time mapping would index documents under it. Leaving the URL alone is where 15.9 already ends up after the exception, just without a stack trace per URL. It is also how a document boost rule behaves without its engine: it boosts nothing (#3412). Installing
fess-script-groovymakes such a mapping work as it did in 15.8.Compatibility
test_replaceUrl_missingGroovyEngineIsPlainReplacementpinned the old result forgroovy:urlwithout an engine (groovy:urla.html). It is renamed totest_replaceUrl_missingGroovyEngineLeavesUrlUnchangedand now expects the URL unchanged. Mappings whose prefix is notgroovy:orjavascript:behave exactly as before.Verification
New tests in
PathMappingHelperTest:test_createPathMatcher_missingGroovyEngineDoesNotThrowOnScript: builds the matcher forgroovy:"http://mapped.invalid/en-${matcher.group(1)}"with no Groovy engine and applies it. Onmainthis throwsIllegalArgumentException: named capturing group is missing trailing '}'; with this change it returns the URL.test_replaceUrl_missingGroovyEngineScriptLeavesUrlAndLogsNoFailure: runs two URLs throughreplaceUrl. Both come back unchanged,PathMappinglogs no warning, andPathMappingHelperlogs exactly one, namingfess-script-groovy. Onmainit fails on theFailed to apply … IllegalArgumentExceptionwarnings.test_replaceUrl_unregisteredPrefixKeepsGroupReferences:https://files.example.com/$1still substitutes the group. It passes before and after and guards the intended behaviour.mvn test -Dtest=PathMappingHelperTest: 40 tests. Onmain1 failure and 1 error (the two new tests); on this branch 0 failures and 0 errors.mvn test: 7490 tests, 0 failures, 0 errors.