Lukasz Lenart created WW-5688:
---------------------------------

             Summary: RestActionMapper maps URIs with an id into the empty 
namespace, so actions declared at namespace "/" 404
                 Key: WW-5688
                 URL: https://issues.apache.org/jira/browse/WW-5688
             Project: Struts 2
          Issue Type: Bug
          Components: Plugin - REST
    Affects Versions: 2.1.2
            Reporter: Lukasz Lenart
             Fix For: 7.4.0


Split out of [WW-2820|https://issues.apache.org/jira/browse/WW-2820], a 2008 
umbrella of five unrelated REST plugin claims. This is the only one of the five 
that still reproduces on {{main}}. Originally reported by Alvin Singh.

h3. Symptom

When a package is declared at {{namespace="/"}}, REST URIs that carry an id are 
mapped into a _different_ namespace than those that do not. The result is that 
{{index}} works while {{show}} / {{update}} / {{destroy}} return 404 for the 
very same action.

Given:

    [package name="rest-root" namespace="/" extends="rest-default"]
        [action name="dog" class="com.example.DogAction"/]
    [/package]

||Request||namespace from RestActionMapper||action resolves?||
|{{GET /dog}}|{{/}}|yes|
|{{GET /dog/1}}|(empty)|*no - 404*|

The reporter's original phrasing was "if you want a blank namespace, do not use 
/ as your namespace ... inconsistent behavior starts to occur", which is 
accurate.

h3. Root cause

{{RestActionMapper.parseNameAndNamespace()}} has two disjoint paths:
* {{lastSlash == 0}} hardcodes {{namespace = "/"}} (the WW-1046 root case).
* Any deeper URI instead runs the longest-matching-namespace loop. That loop's 
guard, {{prefix.charAt(ns.length()) == '/'}}, can never select {{"/"}} - it 
would require a {{//}} prefix - so it falls through to its default of {{""}}.

{{RuntimeConfiguration.getActionConfig()}} then only fails over {{"/"}} to 
{{""}}, never {{""}} to {{"/"}} (see 
{{DefaultConfiguration.shouldFallbackToEmptyNamespace}}). So the {{""}} branch 
is a dead end for an action declared at {{"/"}}.

Note that the loop computes {{name = uri.substring(namespace.length() + 1)}}, 
which assumes a non-root namespace. Simply allowing {{"/"}} to match in the 
loop is therefore not sufficient on its own.

h3. Reproduction

Against a configuration holding only the package above:

    PROBE index -> ns='/' name='dog'
    PROBE show  -> ns=''  name='dog'
    junit.framework.AssertionFailedError:
        GET /dog/1 must resolve to the action declared in namespace "/"

The companion assertion for {{GET /dog}} passes against the same configuration, 
so the failure is specific to the id-bearing URI and not an artefact of the 
fixture.

h3. Security assessment

Not a security issue. The defect makes actions _less_ reachable rather than 
more, and aligning {{/dog/1}} with what {{/dog}} already resolves to exposes no 
surface that the {{/dog}} path does not already expose.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to