You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by re...@apache.org on 2021/07/08 12:37:26 UTC

[cxf] branch 3.3.x-fixes updated (44bb98f -> 72b24f2)

This is an automated email from the ASF dual-hosted git repository.

reta pushed a change to branch 3.3.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git.


    from 44bb98f  Updating Tomcat to 8.5.69
     new 5670229  CXF-8557: Incorrect Proxy Path Segmenting when @Path Annotation RegexExpression Contains '/' (#822)
     new 72b24f2  Recording .gitmergeinfo Changes

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .gitmergeinfo                                      |   1 +
 .../org/apache/cxf/jaxrs/utils/JAXRSUtils.java     |  73 ++++++++++++---
 .../apache/cxf/jaxrs/impl/UriBuilderImplTest.java  | 100 +++++++++++++++++++++
 3 files changed, 162 insertions(+), 12 deletions(-)

[cxf] 01/02: CXF-8557: Incorrect Proxy Path Segmenting when @Path Annotation RegexExpression Contains '/' (#822)

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

reta pushed a commit to branch 3.3.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git

commit 567022973f8db62466ae230850cf04b8605a5418
Author: Andriy Redko <dr...@gmail.com>
AuthorDate: Wed Jul 7 21:52:21 2021 -0400

    CXF-8557: Incorrect Proxy Path Segmenting when @Path Annotation RegexExpression Contains '/' (#822)
    
    * CXF-8557: Incorrect Proxy Path Segmenting when @Path Annotation Regex Expression Contains '/'
    
    * Added more sophisticated handling of the incorrect template definitions and fallback to simple split by path segment separator
    
    (cherry picked from commit c0cae301ccfcb75b5ad011fd2192b5385539d9dd)
    (cherry picked from commit 8f7b5e9421428b8cfc8d6b898d85dbb288358e94)
---
 .../org/apache/cxf/jaxrs/utils/JAXRSUtils.java     |  73 ++++++++++++---
 .../apache/cxf/jaxrs/impl/UriBuilderImplTest.java  | 100 +++++++++++++++++++++
 2 files changed, 161 insertions(+), 12 deletions(-)

diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
index 5923836..38fab87 100644
--- a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
+++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
@@ -181,20 +181,69 @@ public final class JAXRSUtils {
         return getPathSegments(thePath, decode, true);
     }
 
+    /**
+     * Parses path segments taking into account the URI templates and template regexes. Per RFC-3986, 
+     * "A path consists of a sequence of path segments separated by a slash ("/") character.", however
+     * it is possible to include slash ("/") inside template regex, for example "/my/path/{a:b/c}", see 
+     * please {@link URITemplate}. In this case, the whole template definition is extracted as a path 
+     * segment, without breaking it.
+     * @param thePath path
+     * @param decode should the path segments be decoded or not
+     * @param ignoreLastSlash should the last slash be ignored or not
+     * @return
+     */
     public static List<PathSegment> getPathSegments(String thePath, boolean decode,
                                                     boolean ignoreLastSlash) {
-        List<PathSegment> theList =
-            Arrays.asList(thePath.split("/")).stream()
-            .filter(StringUtils.notEmpty())
-            .map(p -> new PathSegmentImpl(p, decode))
-            .collect(Collectors.toList());
-
-        int len = thePath.length();
-        if (len > 0 && thePath.charAt(len - 1) == '/') {
-            String value = ignoreLastSlash ? "" : "/";
-            theList.add(new PathSegmentImpl(value, false));
-        }
-        return theList;
+        
+        final List<PathSegment> segments = new ArrayList<>();
+        int templateDepth = 0;
+        int start = 0;
+        for (int i = 0; i < thePath.length(); ++i) {
+            if (thePath.charAt(i) == '/') {
+                // The '/' is in template (possibly, with arbitrary regex) definition
+                if (templateDepth != 0) {
+                    continue;
+                } else if (start != i) {
+                    final String segment = thePath.substring(start, i);
+                    segments.add(new PathSegmentImpl(segment, decode));
+                }
+                
+                // advance the positions, empty path segments
+                start = i + 1;
+            } else if (thePath.charAt(i) == '{') {
+                ++templateDepth;
+            } else if (thePath.charAt(i) == '}') {
+                --templateDepth; // could go negative, since the template could be unbalanced
+            }
+        }
+        
+        // the URI has unbalanced curly braces, backtrack to the last seen position of the path
+        // segment separator and just split segments as-is from there
+        if (templateDepth != 0) {
+            segments.addAll(
+                Arrays
+                    .stream(thePath.substring(start).split("/"))
+                    .filter(StringUtils.notEmpty())
+                    .map(p -> new PathSegmentImpl(p, decode))
+                    .collect(Collectors.toList()));
+
+            int len = thePath.length();
+            if (len > 0 && thePath.charAt(len - 1) == '/') {
+                String value = ignoreLastSlash ? "" : "/";
+                segments.add(new PathSegmentImpl(value, false));
+            }
+        } else {
+            // the last symbol is slash
+            if (start == thePath.length() && start > 0 && thePath.charAt(start - 1) == '/') {
+                String value = ignoreLastSlash ? "" : "/";
+                segments.add(new PathSegmentImpl(value, false));
+            } else if (!thePath.isEmpty()) {
+                final String segment = thePath.substring(start);
+                segments.add(new PathSegmentImpl(segment, decode));
+            }
+        }
+        
+        return segments;
     }
 
     private static String[] getUserMediaTypes(Object provider, boolean consumes) {
diff --git a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java
index bef65a4..b7d7c3a 100644
--- a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java
+++ b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java
@@ -1851,4 +1851,104 @@ public class UriBuilderImplTest {
             .toTemplate();
         assertEquals("my/path?p=%25250%25", template);
     }
+    
+    @Test
+    public void pathParamFromTemplateWithOrRegex() {
+        final URI uri = UriBuilder
+            .fromUri("my/path")
+            .path("{p:my|his}")
+            .build("my");
+        assertEquals("my/path/my", uri.toString());
+    }
+    
+    @Test
+    public void pathParamFromTemplateWithRegex() {
+        final URI uri = UriBuilder
+            .fromUri("my/path")
+            .path("{p:his/him}")
+            .buildFromEncoded("his/him");
+        assertEquals("my/path/his/him", uri.toString());
+    }
+    
+    @Test
+    public void pathParamFromNestedTemplateWithRegex() {
+        // The nested templates are not supported and are not detected 
+        final URI uri = UriBuilder
+            .fromUri("my/path")
+            .path("{{p:his/him}}")
+            .build();
+        assertEquals("my/path/%7B%7Bp:his/him%7D%7D", uri.toString());
+    }
+    
+    @Test
+    public void pathParamFromBadTemplateNested() {
+        final URI uri = UriBuilder
+            .fromUri("my/path")
+            .path("{p{d}}")
+            .build("my");
+        assertEquals("my/path/%7Bp%7Bd%7D%7D", uri.toString());
+    }
+    
+    @Test
+    public void pathParamFromBadTemplateUnopened() {
+        final URI uri = UriBuilder
+            .fromUri("my/path")
+            .path("p{d}/}")
+            .build("my");
+        assertEquals("my/path/pmy/%7D", uri.toString());
+    }
+    
+    @Test
+    public void pathParamFromBadTemplateUnclosed() {
+        final URI uri = UriBuilder
+            .fromUri("my/path")
+            .path("{p/{d}")
+            .build("my");
+        assertEquals("my/path/%7Bp/my", uri.toString());
+    }
+    
+    @Test
+    public void pathParamFromEmpty() {
+        final URI uri = UriBuilder
+            .fromUri("/")
+            .path("/")
+            .build();
+        assertEquals("/", uri.toString());
+    }
+    
+    @Test
+    public void pathParamFromEmptyWithSpaces() {
+        final URI uri = UriBuilder
+            .fromUri("/")
+            .path("   /   ")
+            .build();
+        assertEquals("/%20%20%20/%20%20%20", uri.toString());
+    }
+    
+    @Test
+    public void pathParamFromBadTemplateUnopenedAndEnclosedSlash() {
+        final URI uri = UriBuilder
+            .fromUri("my/path")
+            .path("p{d:my/day}/}")
+            .buildFromEncoded("my/day");
+        assertEquals("my/path/pmy/day/%7D", uri.toString());
+    }
+    
+    @Test
+    public void pathParamFromBadTemplateUnclosedAndEnclosedSlash() {
+        final URI uri = UriBuilder
+            .fromUri("my/path")
+            .path("{p/{d:my/day}")
+            .build();
+        assertEquals("my/path/%7Bp/%7Bd:my/day%7D", uri.toString());
+    }
+    
+    @Test
+    public void pathParamFromBadTemplate() {
+        final URI uri = UriBuilder
+            .fromUri("/")
+            .path("{")
+            .build();
+        assertEquals("/%7B", uri.toString());
+    }
 }
\ No newline at end of file

[cxf] 02/02: Recording .gitmergeinfo Changes

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

reta pushed a commit to branch 3.3.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git

commit 72b24f2ed799cd05e54e21c30f13424e50b5764c
Author: Andriy Redko <dr...@gmail.com>
AuthorDate: Thu Jul 8 08:24:18 2021 -0400

    Recording .gitmergeinfo Changes
---
 .gitmergeinfo | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitmergeinfo b/.gitmergeinfo
index 0527365..36f3c87 100644
--- a/.gitmergeinfo
+++ b/.gitmergeinfo
@@ -799,6 +799,7 @@ M 49a080d2d4c11bb272a182c178639afc588b5737
 M 49b765b1424d097757a53e4dbfadcde285a7a884
 M 49c1ca37a066dbfe0f4f32313da7ee4cdce61a15
 M 4b43096d1d79d3ba8e169eff1f09b38ea3ec929e
+M 4ba356d5b2889dace05dc58761ef12810c00e2f4
 M 4c3c5196be3e9295c31b5bc592ebc8f911c93c6d
 M 4d95d191ad25559deca8d5f010d5021446c1beed
 M 4fa9dd5faa934ad7c778a346b311b095764cec3a