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

duncangrant pushed a commit to branch fix-multipart
in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git

commit 1163f1ddd6c59b7519122d2e54f558d305365aa6
Author: Duncan Grant <[email protected]>
AuthorDate: Tue Jul 27 16:07:20 2021 +0100

    Fix disallowed characters in multipart form
    
    Specifically if posting a multipart form with %s then we would get an
    error.
---
 rest/rest-api/pom.xml                              |  4 ++++
 .../apache/brooklyn/rest/api/ApplicationApi.java   | 23 +++++++++++++++---
 .../rest/resources/ApplicationResource.java        |  9 ++++++++
 .../brooklyn/rest/api/ApplicationApiTest.java      | 27 ++++++++++++++++++++++
 4 files changed, 60 insertions(+), 3 deletions(-)

diff --git a/rest/rest-api/pom.xml b/rest/rest-api/pom.xml
index e06640f..d8a0b82 100644
--- a/rest/rest-api/pom.xml
+++ b/rest/rest-api/pom.xml
@@ -99,6 +99,10 @@
             <version>${project.version}</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
+        </dependency>
     </dependencies>
 
     <build>
diff --git 
a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/ApplicationApi.java 
b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/ApplicationApi.java
index f73c85c..800b778 100644
--- 
a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/ApplicationApi.java
+++ 
b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/ApplicationApi.java
@@ -33,6 +33,8 @@ import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
+import org.apache.cxf.jaxrs.ext.multipart.Multipart;
+
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
@@ -236,7 +238,7 @@ public interface ApplicationApi {
 
     @Beta
     @POST
-    @Consumes({MediaType.MULTIPART_FORM_DATA, 
MediaType.APPLICATION_FORM_URLENCODED})
+    @Consumes(MediaType.MULTIPART_FORM_DATA)
     @ApiOperation(
             value = "[BETA] Create and start a new application from YAML",
             response = org.apache.brooklyn.rest.domain.TaskSummary.class
@@ -244,13 +246,28 @@ public interface ApplicationApi {
     @ApiResponses(value = {
             @ApiResponse(code = 404, message = "Undefined entity or location")
     })
-    public Response createWithFormat(
+    public Response createWithFormatMultipart(
+            @ApiParam(name = "plan", value = "Application plan to deploy", 
required = true)
+            @Multipart("plan") String plan,
+            @ApiParam(name = "format", value = "Type plan format e.g. 
brooklyn-camp", required = false)
+            @Multipart("format") String format);
+
+    @Beta
+    @POST
+    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+    @ApiOperation(
+            value = "[BETA] Create and start a new application from YAML",
+            response = org.apache.brooklyn.rest.domain.TaskSummary.class
+    )
+    @ApiResponses(value = {
+            @ApiResponse(code = 404, message = "Undefined entity or location")
+    })
+    public Response createWithFormatForm(
             @ApiParam(name = "plan", value = "Application plan to deploy", 
required = true)
             @FormParam("plan") String plan,
             @ApiParam(name = "format", value = "Type plan format e.g. 
brooklyn-camp", required = false)
             @FormParam("format") String format);
 
-
     @DELETE
     @Path("/{application}")
     @ApiOperation(
diff --git 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
index 13d7773..8ceb1b9 100644
--- 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
+++ 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
@@ -533,6 +533,15 @@ public class ApplicationResource extends 
AbstractBrooklynRestResource implements
     }
 
     @Override
+    public Response createWithFormatForm(String plan, String format) {
+        return createWithFormat(plan, format);
+    }
+
+    @Override
+    public Response createWithFormatMultipart(String plan, String format) {
+        return createWithFormat(plan, format);
+    }
+
     public Response createWithFormat(String inputToAutodetectType, String 
format) {
         log.debug("Creating app from autodetecting input");
 
diff --git 
a/rest/rest-server/src/test/java/org/apache/brooklyn/rest/api/ApplicationApiTest.java
 
b/rest/rest-server/src/test/java/org/apache/brooklyn/rest/api/ApplicationApiTest.java
new file mode 100644
index 0000000..9ede0d0
--- /dev/null
+++ 
b/rest/rest-server/src/test/java/org/apache/brooklyn/rest/api/ApplicationApiTest.java
@@ -0,0 +1,27 @@
+package org.apache.brooklyn.rest.api;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.brooklyn.rest.BrooklynRestApiLauncherTestFixture;
+import org.apache.brooklyn.util.http.HttpToolResponse;
+import org.testng.annotations.Test;
+
+import java.util.Map;
+
+public class ApplicationApiTest extends BrooklynRestApiLauncherTestFixture {
+
+
+    @Test(groups = "Integration")
+    public void testMultipartFormWithInvalidChar() throws Exception {
+        useServerForTest(newServer());
+        String body = 
"------WebKitFormBoundaryaQhM7RFMi4ZiXOj2\n\rContent-Disposition: form-data; 
services:\n\r- type: 
org.apache.brooklyn.entity.stock.BasicEntity\n\rbrooklyn.config:\n\rexample: 
$brooklyn:formatString(\"%s\", 
\"vault\")\n\r\n\r\n\r------WebKitFormBoundaryaQhM7RFMi4ZiXOj2\n\rContent-Disposition:
 form-data; 
name=\"format\"\n\r\n\rcamp\n\r------WebKitFormBoundaryaQhM7RFMi4ZiXOj2--\n\r";
+        ImmutableMap<String, String> headers = ImmutableMap.of("Content-Type", 
"multipart/form-data; boundary=----WebKitFormBoundaryaQhM7RFMi4ZiXOj2");
+        assertPostMultiPart("admin", "/v1/applications", body.getBytes(), 
headers);
+    }
+
+    public void assertPostMultiPart(String user, String path, byte[] body, 
Map<String, String> headers) throws Exception {
+        HttpToolResponse response = httpPost(user, path, body, headers);
+        assertHealthyStatusCode(response);
+    }
+
+
+}
\ No newline at end of file

Reply via email to