diff --git a/pom.xml b/pom.xml index 4ae97dc..39265f9 100644 --- a/pom.xml +++ b/pom.xml @@ -32,6 +32,14 @@ + + + net.java.dev.jna + jna + 3.2.2 + + + scm:git:git://github.com/jenkinsci/${project.artifactId}-plugin.git scm:git:git@github.com:jenkinsci/${project.artifactId}-plugin.git diff --git a/src/main/java/org/jenkinsci/plugins/corsfilter/AccessControlsFilter.java b/src/main/java/org/jenkinsci/plugins/corsfilter/AccessControlsFilter.java index e364b0f..be0ae57 100644 --- a/src/main/java/org/jenkinsci/plugins/corsfilter/AccessControlsFilter.java +++ b/src/main/java/org/jenkinsci/plugins/corsfilter/AccessControlsFilter.java @@ -18,7 +18,9 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.ArrayList; import java.util.logging.Logger; +import org.apache.commons.lang.StringUtils; /** * Filter to support CORS @@ -35,6 +37,7 @@ public class AccessControlsFilter implements Filter, Describable allowedOriginsList = null; + private List allowedHeadersList = null; @Initializer(after = InitMilestone.JOB_LOADED) public static void init() throws ServletException { @@ -88,9 +91,53 @@ private void processAccessControls(HttpServletRequest req, HttpServletResponse r resp.addHeader("Access-Control-Allow-Methods", getDescriptor().getAllowedMethods()); resp.addHeader("Access-Control-Allow-Credentials", "true"); resp.addHeader("Access-Control-Allow-Origin", origin); + + /** + * Requested headers + */ + String requestedHeaders = req.getHeader("Access-Control-Request-Headers"); + if (requestedHeaders != null && !requestedHeaders.trim().isEmpty()) { + List acceptedHeadersList = processRequestedHeaders(Arrays.asList(requestedHeaders.split("\\s*,\\s*"))); + if (!acceptedHeadersList.isEmpty()) { + // JAVA 8+ + //resp.addHeader("Access-Control-Allow-Headers", String.join(", ", acceptedHeadersList)); + // JAVA 7 + if (acceptedHeadersList.size() == 1) { + resp.addHeader("Access-Control-Allow-Headers", acceptedHeadersList.get(0)); + } else { + StringBuilder sb = new StringBuilder(); + sb.append(acceptedHeadersList.get(0)); + for (int i = 1; i < acceptedHeadersList.size(); i++) { + sb.append(", ").append(acceptedHeadersList.get(i)); + } + resp.addHeader("Access-Control-Allow-Headers", sb.toString()); + } + } + } } } + private List processRequestedHeaders(List requestedList) { + List acceptedList = new ArrayList(); + + if (allowedHeadersList == null) { + String allowedHeaders = getDescriptor().getAllowedHeaders(); + if (allowedHeaders != null && !allowedHeaders.trim().isEmpty()) { + allowedHeadersList = Arrays.asList(allowedHeaders.split("\\s*,\\s*")); + } else { + allowedHeadersList = Collections.EMPTY_LIST; + } + } + + for (int i = 0; i < requestedList.size(); i++) { + if (allowedHeadersList.contains(requestedList.get(i))) { + acceptedList.add(requestedList.get(i)); + } + } + + return acceptedList; + } + /** * Check if the origin is allowed * @@ -141,6 +188,7 @@ public static final class DescriptorImpl extends Descriptor + + + diff --git a/src/main/resources/org/jenkinsci/plugins/corsfilter/AccessControlsFilter/help-allowedHeaders.html b/src/main/resources/org/jenkinsci/plugins/corsfilter/AccessControlsFilter/help-allowedHeaders.html new file mode 100644 index 0000000..7407bce --- /dev/null +++ b/src/main/resources/org/jenkinsci/plugins/corsfilter/AccessControlsFilter/help-allowedHeaders.html @@ -0,0 +1,6 @@ +
+ Specifies the header or headers allowed when accessing the Jenkins resources. This is used in response to a pre-flight + request containing Access-Control-Request-Headers + + For example: Content-Type +
diff --git a/src/test/java/org/jenkinsci/plugins/corsfilter/AccessControlsFilterTest.java b/src/test/java/org/jenkinsci/plugins/corsfilter/AccessControlsFilterTest.java index 721f22b..059aae2 100644 --- a/src/test/java/org/jenkinsci/plugins/corsfilter/AccessControlsFilterTest.java +++ b/src/test/java/org/jenkinsci/plugins/corsfilter/AccessControlsFilterTest.java @@ -62,4 +62,19 @@ public void testAllowOrigins() throws Exception { assertEquals(htmlPage.getWebResponse().getResponseHeaderValue("Access-Control-Allow-Origin"), "http://localhost:9000"); } + @Test + public void testAllowHeaders() throws Exception { + descriptor.setAllowedMethods("GET, OPTIONS"); + descriptor.setAllowedOrigins("http://localhost:9000, http://localhost:8080"); + descriptor.setAllowedHeaders("Origin, Content-Type, X-Foo"); + descriptor.setEnabled(true); + + client.addRequestHeader("Origin", "http://localhost:9000"); + client.addRequestHeader("Access-Control-Request-Headers", "Content-Type"); + HtmlPage htmlPage = client.goTo(""); + + assertTrue(Boolean.valueOf(htmlPage.getWebResponse().getResponseHeaderValue("Access-Control-Allow-Credentials"))); + assertEquals(htmlPage.getWebResponse().getResponseHeaderValue("Access-Control-Allow-Headers"), "Content-Type"); + } + } \ No newline at end of file