cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From r...@apache.org
Subject [cxf] branch 3.1.x-fixes updated: CXF-7581: SwaggerUIResourceFilter doesn't allow call to service endpoint
Date Thu, 14 Dec 2017 19:27:02 GMT
This is an automated email from the ASF dual-hosted git repository.

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


The following commit(s) were added to refs/heads/3.1.x-fixes by this push:
     new 5444d97  CXF-7581: SwaggerUIResourceFilter doesn't allow call to service endpoint
5444d97 is described below

commit 5444d97e41e0411c30672c5f9ea8eae8a5544ad6
Author: reta <drreta@gmail.com>
AuthorDate: Thu Dec 14 14:26:48 2017 -0500

    CXF-7581: SwaggerUIResourceFilter doesn't allow call to service endpoint
---
 .../apache/cxf/jaxrs/swagger/Swagger2Feature.java  | 30 ++++-----
 .../jaxrs/swagger/SwaggerUiResourceLocator.java    | 72 ++++++++++++++++++++++
 .../AbstractSwagger2ServiceDescriptionTest.java    | 28 ++++++++-
 .../description/BookStoreStylesheetsSwagger2.java  | 34 ++++++++++
 .../jaxrs/description/BookStoreSwagger2.java       |  8 +++
 ...Swagger2NonAnnotatedServiceDescriptionTest.java |  3 +-
 .../resources/jaxrs_swagger2/WEB-INF/beans.xml     |  1 +
 7 files changed, 159 insertions(+), 17 deletions(-)

diff --git a/rt/rs/description-swagger/src/main/java/org/apache/cxf/jaxrs/swagger/Swagger2Feature.java
b/rt/rs/description-swagger/src/main/java/org/apache/cxf/jaxrs/swagger/Swagger2Feature.java
index 9e6b64c..9161997 100644
--- a/rt/rs/description-swagger/src/main/java/org/apache/cxf/jaxrs/swagger/Swagger2Feature.java
+++ b/rt/rs/description-swagger/src/main/java/org/apache/cxf/jaxrs/swagger/Swagger2Feature.java
@@ -163,13 +163,14 @@ public class Swagger2Feature extends AbstractSwaggerFeature {
             String swaggerUiRoot = SwaggerUiResolver.findSwaggerUiRoot(swaggerUiMavenGroupAndArtifact,

                                                                        swaggerUiVersion);
             if (swaggerUiRoot != null) {
-                SwaggerUIService swaggerUiService = new SwaggerUIService(swaggerUiRoot, swaggerUiMediaTypes);
+                final SwaggerUiResourceLocator locator = new SwaggerUiResourceLocator(swaggerUiRoot);
+                final SwaggerUIService swaggerUiService = new SwaggerUIService(locator, swaggerUiMediaTypes);
                 if (!isRunAsFilter()) {
                     swaggerResources.add(swaggerUiService);
                 } else {
                     providers.add(new SwaggerUIServiceFilter(swaggerUiService));
                 }
-                providers.add(new SwaggerUIResourceFilter());
+                providers.add(new SwaggerUIResourceFilter(locator));
                 
                 bus.setProperty("swagger.service.ui.available", "true");
             }
@@ -595,30 +596,23 @@ public class Swagger2Feature extends AbstractSwaggerFeature {
             DEFAULT_MEDIA_TYPES.put("woff2", "application/font-woff2");
         }
 
-        private final String swaggerUiRoot;
-
+        private final SwaggerUiResourceLocator locator;
         private final Map<String, String> mediaTypes;
 
-        public SwaggerUIService(String swaggerUiRoot, Map<String, String> mediaTypes)
{
-            this.swaggerUiRoot = swaggerUiRoot;
+        public SwaggerUIService(SwaggerUiResourceLocator locator, Map<String, String>
mediaTypes) {
+            this.locator = locator;
             this.mediaTypes = mediaTypes;
         }
         
         @GET
         @Path("{resource:.*}")
         public Response getResource(@Context UriInfo uriInfo, @PathParam("resource") String
resourcePath) {
-            if (StringUtils.isEmpty(resourcePath) || "/".equals(resourcePath)) {        
-                resourcePath = "index.html";
-            }
-            if (resourcePath.contains(FAVICON)) {        
+            if (resourcePath.contains(FAVICON)) {
                 return Response.status(404).build();
             }
-            if (resourcePath.startsWith("/")) {
-                resourcePath = resourcePath.substring(1);
-            }
             
             try {
-                URL resourceURL = URI.create(swaggerUiRoot + resourcePath).toURL();
+                URL resourceURL = locator.locate(resourcePath);
                 
                 String mediaType = null;
                 int ind = resourcePath.lastIndexOf('.');
@@ -650,13 +644,19 @@ public class Swagger2Feature extends AbstractSwaggerFeature {
                   ".*[.]js|.*[.]gz|.*[.]map|oauth2*[.]html|.*[.]png|.*[.]css|.*[.]ico|"
                   + "/css/.*|/images/.*|/lib/.*|/fonts/.*"
             );
+        
+        private final SwaggerUiResourceLocator locator;
+        
+        SwaggerUIResourceFilter(SwaggerUiResourceLocator locator) {
+            this.locator = locator;
+        }
 
         @Override
         public void filter(ContainerRequestContext rc) throws IOException {
             if (HttpMethod.GET.equals(rc.getRequest().getMethod())) {
                 UriInfo ui = rc.getUriInfo();
                 String path = "/" + ui.getPath();
-                if (PATTERN.matcher(path).matches()) {
+                if (PATTERN.matcher(path).matches() && locator.exists(path)) {
                     rc.setRequestUri(URI.create("api-docs" + path));
                 }
             }
diff --git a/rt/rs/description-swagger/src/main/java/org/apache/cxf/jaxrs/swagger/SwaggerUiResourceLocator.java
b/rt/rs/description-swagger/src/main/java/org/apache/cxf/jaxrs/swagger/SwaggerUiResourceLocator.java
new file mode 100644
index 0000000..7b2f081
--- /dev/null
+++ b/rt/rs/description-swagger/src/main/java/org/apache/cxf/jaxrs/swagger/SwaggerUiResourceLocator.java
@@ -0,0 +1,72 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.jaxrs.swagger;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+
+import org.apache.cxf.common.util.StringUtils;
+
+/**
+ * Swagger UI resource locator
+ */
+class SwaggerUiResourceLocator {
+    private final String swaggerUiRoot;
+    
+    SwaggerUiResourceLocator(String swaggerUiRoot) {
+        this.swaggerUiRoot = swaggerUiRoot;
+    }
+
+    /**
+     * Locate Swagger UI resource corresponding to resource path
+     * @param resourcePath resource path
+     * @return Swagger UI resource URL
+     * @throws MalformedURLException
+     */
+    URL locate(String resourcePath) throws MalformedURLException {
+        if (StringUtils.isEmpty(resourcePath) || "/".equals(resourcePath)) {
+            resourcePath = "index.html";
+        }
+    
+        if (resourcePath.startsWith("/")) {
+            resourcePath = resourcePath.substring(1);
+        }
+        
+        return URI.create(swaggerUiRoot + resourcePath).toURL();
+    }
+    
+    /**
+     * Checks the existence of the Swagger UI resource corresponding to resource path
+     * @param resourcePath resource path
+     * @return "true" if Swagger UI resource exists, "false" otherwise
+     */
+    boolean exists(String resourcePath) {
+        try {
+            // The connect() will try to locate the entry (jar file, classpath resource)

+            // and fail with FileNotFoundException /IOException if there is none.
+            locate(resourcePath).openConnection().connect();
+            return true;
+        } catch (IOException ex) {
+            return false;
+        }
+    }
+}
diff --git a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/description/AbstractSwagger2ServiceDescriptionTest.java
b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/description/AbstractSwagger2ServiceDescriptionTest.java
index c9ecd4e..ccf8c39 100644
--- a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/description/AbstractSwagger2ServiceDescriptionTest.java
+++ b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/description/AbstractSwagger2ServiceDescriptionTest.java
@@ -56,6 +56,9 @@ import org.junit.Test;
 
 import org.yaml.snakeyaml.Yaml;
 
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.equalTo;
+
 public abstract class AbstractSwagger2ServiceDescriptionTest extends AbstractBusClientServerTestBase
{
     static final String SECURITY_DEFINITION_NAME = "basicAuth";
     
@@ -79,7 +82,8 @@ public abstract class AbstractSwagger2ServiceDescriptionTest extends AbstractBus
         protected void run() {
             final JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
             sf.setResourceClasses(BookStoreSwagger2.class);
-            sf.setResourceProvider(BookStoreSwagger2.class, 
+            sf.setResourceClasses(BookStoreStylesheetsSwagger2.class);
+            sf.setResourceProvider(BookStoreSwagger2.class,
                 new SingletonResourceProvider(new BookStoreSwagger2()));
             sf.setProvider(new JacksonJsonProvider());
             final Swagger2Feature feature = createSwagger2Feature();
@@ -191,6 +195,28 @@ public abstract class AbstractSwagger2ServiceDescriptionTest extends
AbstractBus
     }
 
     @Test
+    public void testNonUiResource() {
+        // Test that Swagger UI resources do not interfere with 
+        // application-specific ones.
+        WebClient uiClient = WebClient
+            .create("http://localhost:" + getPort() + "/css/book.css")
+            .accept("text/css");
+        String css = uiClient.get(String.class);
+        assertThat(css, equalTo("body { background-color: lightblue; }"));
+    }
+    
+    @Test
+    public void testUiResource() {
+        // Test that Swagger UI resources do not interfere with 
+        // application-specific ones and are accessible.
+        WebClient uiClient = WebClient
+            .create("http://localhost:" + getPort() + "/css/print.css")
+            .accept("text/css");
+        String css = uiClient.get(String.class);
+        assertThat(css, containsString(".swagger-section pre code{display"));
+    }
+    
+    @Test
     @Ignore
     public void testApiListingIsProperlyReturnedYAML() throws Exception {
         final WebClient client = createWebClient("/swagger.yaml");
diff --git a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/description/BookStoreStylesheetsSwagger2.java
b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/description/BookStoreStylesheetsSwagger2.java
new file mode 100644
index 0000000..ca49c0f
--- /dev/null
+++ b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/description/BookStoreStylesheetsSwagger2.java
@@ -0,0 +1,34 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.systest.jaxrs.description;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+@Path("/")
+public class BookStoreStylesheetsSwagger2 {
+    @Produces({ "text/css" })
+    @Path("/css/book.css")
+    @GET
+    public String getCss() {
+        return "body { background-color: lightblue; }"; 
+    }
+}
diff --git a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/description/BookStoreSwagger2.java
b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/description/BookStoreSwagger2.java
index 755a89b..8032c0c 100644
--- a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/description/BookStoreSwagger2.java
+++ b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/description/BookStoreSwagger2.java
@@ -79,4 +79,12 @@ public class BookStoreSwagger2 {
     public Response delete(@ApiParam(value = "id", required = true) @PathParam("id") String
id) {
         return Response.ok().build();
     }
+    
+    @ApiOperation(hidden = true, value = "css")
+    @Produces({ "text/css" })
+    @Path("/css/book.css")
+    @GET
+    public String getCss() {
+        return "body { background-color: lightblue; }"; 
+    }
 }
diff --git a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/description/Swagger2NonAnnotatedServiceDescriptionTest.java
b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/description/Swagger2NonAnnotatedServiceDescriptionTest.java
index 439baf5..3215d92 100644
--- a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/description/Swagger2NonAnnotatedServiceDescriptionTest.java
+++ b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/description/Swagger2NonAnnotatedServiceDescriptionTest.java
@@ -42,7 +42,8 @@ public class Swagger2NonAnnotatedServiceDescriptionTest extends AbstractSwagger2
         protected void run() {
             final JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
             sf.setResourceClasses(BookStore.class);
-            sf.setResourceProvider(BookStore.class, 
+            sf.setResourceClasses(BookStoreStylesheetsSwagger2.class);
+            sf.setResourceProvider(BookStore.class,
                 new SingletonResourceProvider(new BookStore()));
             sf.setProvider(new JacksonJsonProvider());
             final Swagger2Feature feature = createSwagger2Feature();
diff --git a/systests/jaxrs/src/test/resources/jaxrs_swagger2/WEB-INF/beans.xml b/systests/jaxrs/src/test/resources/jaxrs_swagger2/WEB-INF/beans.xml
index bed1e35..fba423e 100644
--- a/systests/jaxrs/src/test/resources/jaxrs_swagger2/WEB-INF/beans.xml
+++ b/systests/jaxrs/src/test/resources/jaxrs_swagger2/WEB-INF/beans.xml
@@ -40,6 +40,7 @@
     <jaxrs:server address="/">
         <jaxrs:serviceBeans>
             <bean class="org.apache.cxf.systest.jaxrs.description.BookStoreSwagger2"/>
+            <bean class="org.apache.cxf.systest.jaxrs.description.BookStoreStylesheetsSwagger2"/>
         </jaxrs:serviceBeans>
         <jaxrs:features>
             <bean class="org.apache.cxf.jaxrs.swagger.Swagger2Feature">

-- 
To stop receiving notification emails like this one, please contact
['"commits@cxf.apache.org" <commits@cxf.apache.org>'].

Mime
View raw message