Updated Branches: refs/heads/master 33279b482 -> b5872e29f
add cors filter Project: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/commit/415e899d Tree: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/tree/415e899d Diff: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/diff/415e899d Branch: refs/heads/master Commit: 415e899d221eba3a629e6a4fb3eec0b967ef6805 Parents: 85f427c Author: tkurz <[email protected]> Authored: Mon Apr 8 17:13:24 2013 +0200 Committer: tkurz <[email protected]> Committed: Mon Apr 8 17:13:24 2013 +0200 ---------------------------------------------------------------------- .../client/test/config/ConfigurationIT.java | 3 + launchers/marmotta-webapp/pom.xml | 7 + .../src/main/webapp/WEB-INF/web.xml | 17 ++ .../core/servlet/MarmottaOptionsFilter.java | 170 --------------- .../src/main/resources/config-defaults.properties | 6 - .../main/resources/config-descriptions.properties | 7 - .../platform/core/test/cors/CorsFilterTest.java | 114 ---------- 7 files changed, 27 insertions(+), 297 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/415e899d/client/marmotta-client-java/src/test/java/org/apache/marmotta/client/test/config/ConfigurationIT.java ---------------------------------------------------------------------- diff --git a/client/marmotta-client-java/src/test/java/org/apache/marmotta/client/test/config/ConfigurationIT.java b/client/marmotta-client-java/src/test/java/org/apache/marmotta/client/test/config/ConfigurationIT.java index f8ba338..f78298a 100644 --- a/client/marmotta-client-java/src/test/java/org/apache/marmotta/client/test/config/ConfigurationIT.java +++ b/client/marmotta-client-java/src/test/java/org/apache/marmotta/client/test/config/ConfigurationIT.java @@ -96,9 +96,12 @@ public class ConfigurationIT { Assert.assertNotNull(c_path); Assert.assertEquals(marmotta.getContext(), c_path.getString()); + /* + * is not managed by the webservice anymore Configuration c_allow = client.getConfiguration("kiwi.allow_methods"); Assert.assertNotNull(c_allow); Assert.assertThat(c_allow.getList(),Matchers.hasItem("POST")); + */ } http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/415e899d/launchers/marmotta-webapp/pom.xml ---------------------------------------------------------------------- diff --git a/launchers/marmotta-webapp/pom.xml b/launchers/marmotta-webapp/pom.xml index 2e29657..43cb57d 100644 --- a/launchers/marmotta-webapp/pom.xml +++ b/launchers/marmotta-webapp/pom.xml @@ -282,6 +282,13 @@ <artifactId>postgresql</artifactId> </dependency> + <!-- CORS filter --> + <dependency> + <groupId>com.thetransactioncompany</groupId> + <artifactId>cors-filter</artifactId> + <version>1.3.2</version> + </dependency> + </dependencies> </project> http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/415e899d/launchers/marmotta-webapp/src/main/webapp/WEB-INF/web.xml ---------------------------------------------------------------------- diff --git a/launchers/marmotta-webapp/src/main/webapp/WEB-INF/web.xml b/launchers/marmotta-webapp/src/main/webapp/WEB-INF/web.xml index 1e417bf..7eb98a3 100644 --- a/launchers/marmotta-webapp/src/main/webapp/WEB-INF/web.xml +++ b/launchers/marmotta-webapp/src/main/webapp/WEB-INF/web.xml @@ -70,6 +70,18 @@ <url-pattern>/*</url-pattern> </filter-mapping> --> + + <!-- enables a cors filter and maps it to any request --> + <!-- for more fine grained configuration have a look at http://software.dzhuvinov.com/cors-filter-configuration.html --> + <filter> + <filter-name>CORS</filter-name> + <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class> + </filter> + <filter-mapping> + <filter-name>CORS</filter-name> + <url-pattern>/*</url-pattern> + </filter-mapping> + <!-- Serve static resources from file system and from .jar files of the respective modules --> <filter> <filter-name>MarmottaResourceFilter</filter-name> @@ -143,6 +155,11 @@ <param-value>org.jboss.resteasy.cdi.CdiInjectorFactory</param-value> </context-param> + <!--<context-param> + <param-name>resteasy.providers</param-name> + <param-value>org.apache.marmotta.platform.core.filters.CorsInterceptor</param-value> + </context-param>--> + <filter> <filter-name>MarmottaPostStartupFilter</filter-name> <filter-class> http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/415e899d/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/servlet/MarmottaOptionsFilter.java ---------------------------------------------------------------------- diff --git a/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/servlet/MarmottaOptionsFilter.java b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/servlet/MarmottaOptionsFilter.java deleted file mode 100644 index 786f5af..0000000 --- a/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/servlet/MarmottaOptionsFilter.java +++ /dev/null @@ -1,170 +0,0 @@ -/** - * 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.marmotta.platform.core.servlet; - -import org.apache.marmotta.platform.core.api.config.ConfigurationService; -import org.jboss.resteasy.spi.DefaultOptionsMethodException; -import org.jboss.resteasy.spi.ResteasyProviderFactory; -import org.slf4j.Logger; - -import javax.inject.Inject; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.core.Response; -import javax.ws.rs.ext.ExceptionMapper; -import javax.ws.rs.ext.Provider; -import java.io.IOException; -import java.util.Arrays; - -/** - * This filter checks for OPTIONS requests. If the response returned by the other filters throws an exception - * org.jboss.resteasy.spi.DefaultOptionsMethodException, the filter writes to the response the default options - * of the Apache Marmotta system, in particular the following headers: - * - * Access-Control-Allow-Origin: * (or as configured in config.properties) - * Access-Control-Allow-Methods: POST, PUT, GET, DELETE, HEAD, OPTIONS - * - * <p/> - * Author: Sebastian Schaffert - */ -public class MarmottaOptionsFilter implements Filter { - - @Inject - private Logger log; - - @Inject - private ConfigurationService configurationService; - - /** - * Called by the web container to indicate to a filter that it is being placed into - * service. The servlet container calls the init method exactly once after instantiating the - * filter. The init method must complete successfully before the filter is asked to do any - * filtering work. <br><br> - * <p/> - * The web container cannot place the filter into service if the init method either<br> - * 1.Throws a ServletException <br> - * 2.Does not return within a time period defined by the web container - */ - @Override - public void init(FilterConfig filterConfig) throws ServletException { - ResteasyProviderFactory.getInstance().addExceptionMapper(new OptionsMapper()); - } - - /** - * The <code>doFilter</code> method of the Filter is called by the container - * each time a request/response pair is passed through the chain due - * to a client request for a resource at the end of the chain. The FilterChain passed in to this - * method allows the Filter to pass on the request and response to the next entity in the - * chain.<p> - * A typical implementation of this method would follow the following pattern:- <br> - * 1. Examine the request<br> - * 2. Optionally wrap the request object with a custom implementation to - * filter content or headers for input filtering <br> - * 3. Optionally wrap the response object with a custom implementation to - * filter content or headers for output filtering <br> - * 4. a) <strong>Either</strong> invoke the next entity in the chain using the FilterChain object (<code>chain.doFilter()</code>), <br> - * * 4. b) <strong>or</strong> not pass on the request/response pair to the next entity in the filter chain to block the request processing<br> - * * 5. Directly set headers on the response after invocation of the next entity in the filter chain. - */ - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - - - try { - - chain.doFilter(request,response); -// DG: The addition of the response header fails because the respons is already committed - so remote the code -// -/* if(response instanceof HttpServletResponse) { - HttpServletResponse resp = (HttpServletResponse)response; - HttpServletRequest req = (HttpServletRequest)request; - - // adjust the header only when the request is not yet com - if (! resp.isCommitted() ) { - if(!"OPTIONS".equalsIgnoreCase(req.getMethod()) && !resp.containsHeader("Access-Control-Allow-Origin")) { - resp.setHeader("Access-Control-Allow-Origin",configurationService.getStringConfiguration("kiwi.allow_origin","*")); - } - } - - } -*/ - } catch (DefaultOptionsMethodException ex) { - if(response instanceof HttpServletResponse) { - HttpServletResponse resp = (HttpServletResponse)response; - HttpServletRequest req = (HttpServletRequest)request; - - if(req.getMethod().equalsIgnoreCase("OPTIONS")) { - resp.setStatus(200); - resp.resetBuffer(); - - - if(!resp.containsHeader("Access-Control-Allow-Origin")) { - resp.setHeader("Access-Control-Allow-Origin",configurationService.getStringConfiguration("kiwi.allow_origin","*")); - } - if(!resp.containsHeader("Access-Control-Allow-Methods")) { - for(String method : configurationService.getListConfiguration("kiwi.allow_methods", Arrays.asList("POST, PUT, GET, DELETE, HEAD".split(",")))) { - resp.addHeader("Access-Control-Allow-Methods",method); - } - } - if(req.getHeader("Access-Control-Request-Headers") != null) { - String header = req.getHeader("Access-Control-Request-Headers"); - String[] values = header.split(","); - for(String value : values) { - resp.addHeader("Access-Control-Allow-Headers",value.trim()); - } - } - - } - } - } - - - - } - - /** - * Called by the web container to indicate to a filter that it is being taken out of service. This - * method is only called once all threads within the filter's doFilter method have exited or after - * a timeout period has passed. After the web container calls this method, it will not call the - * doFilter method again on this instance of the filter. <br><br> - * <p/> - * This method gives the filter an opportunity to clean up any resources that are being held (for - * example, memory, file handles, threads) and make sure that any persistent state is synchronized - * with the filter's current state in memory. - */ - @Override - public void destroy() { - //To change body of implemented methods use File | Settings | File Templates. - } - - @Provider - protected static class OptionsMapper implements ExceptionMapper<DefaultOptionsMethodException> { - - @Override - public Response toResponse(DefaultOptionsMethodException exception) { - throw exception; - } - - } -} http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/415e899d/platform/marmotta-core/src/main/resources/config-defaults.properties ---------------------------------------------------------------------- diff --git a/platform/marmotta-core/src/main/resources/config-defaults.properties b/platform/marmotta-core/src/main/resources/config-defaults.properties index ca6211c..6a5dcc8 100644 --- a/platform/marmotta-core/src/main/resources/config-defaults.properties +++ b/platform/marmotta-core/src/main/resources/config-defaults.properties @@ -62,12 +62,6 @@ kiwi.pages.project.custom.footer = Your Footer powered by <a href="http://marmot # supported styles kiwi.pages.style_path = core/public/style/blue/ -# allow the following origins for JavaScript webservice access (sets Access-Control-Allow-Origin header) -kiwi.allow_origin = * - -# allow the following HTTP methods for JavaScript webservice access (sets Access-Control-Allow-Methods header) -kiwi.allow_methods = POST, PUT, GET, DELETE, HEAD, OPTIONS - # enable or disable the logging of debugging messages for the whole system debug.enabled = false http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/415e899d/platform/marmotta-core/src/main/resources/config-descriptions.properties ---------------------------------------------------------------------- diff --git a/platform/marmotta-core/src/main/resources/config-descriptions.properties b/platform/marmotta-core/src/main/resources/config-descriptions.properties index 6704eb5..913ba5b 100644 --- a/platform/marmotta-core/src/main/resources/config-descriptions.properties +++ b/platform/marmotta-core/src/main/resources/config-descriptions.properties @@ -50,13 +50,6 @@ kiwi.pages.project.type = java.lang.Enum("marmotta"|"custom") kiwi.pages.style_path.description = path to stylesheets for LMF Admin page kiwi.pages.style.type = java.lang.String -kiwi.allow_origin.description = allow the following origins for JavaScript webservice access (sets Access-Control-Allow-Origin header); \ - you can use the wildcard * to allow all origins -kiwi.allow_origin.type = java.lang.String - -kiwi.allow_methods.description = allow the following HTTP methods for JavaScript webservice access (sets Access-Control-Allow-Methods header) -kiwi.allow_methods.type = java.util.List - debug.enabled.description = enable or disable the logging of debugging messages for the whole system debug.enabled.type = java.lang.Boolean http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/415e899d/platform/marmotta-core/src/test/java/org/apache/marmotta/platform/core/test/cors/CorsFilterTest.java ---------------------------------------------------------------------- diff --git a/platform/marmotta-core/src/test/java/org/apache/marmotta/platform/core/test/cors/CorsFilterTest.java b/platform/marmotta-core/src/test/java/org/apache/marmotta/platform/core/test/cors/CorsFilterTest.java deleted file mode 100644 index 09e9ba2..0000000 --- a/platform/marmotta-core/src/test/java/org/apache/marmotta/platform/core/test/cors/CorsFilterTest.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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.marmotta.platform.core.test.cors; - -import com.google.common.collect.Lists; -import com.jayway.restassured.RestAssured; -import org.apache.marmotta.platform.core.api.config.ConfigurationService; -import org.apache.marmotta.platform.core.test.base.JettyMarmotta; -import org.apache.marmotta.platform.core.webservices.config.ConfigurationWebService; -import org.codehaus.jackson.map.ObjectMapper; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; - -import static com.jayway.restassured.RestAssured.given; - -/** - * ... - * <p/> - * Author: Thomas Kurz ([email protected]) - */ -public class CorsFilterTest { - /* - private static JettyMarmotta marmotta; - private static ConfigurationService configurationService; - - @BeforeClass - public static void setUp() { - marmotta = new JettyMarmotta("/marmotta", ConfigurationWebService.class); - configurationService = marmotta.getService(ConfigurationService.class); - - RestAssured.baseURI = "http://localhost"; - RestAssured.port = marmotta.getPort(); - RestAssured.basePath = marmotta.getContext(); - - } - - @AfterClass - public static void tearDown() { - marmotta.shutdown(); - } - */ - - /** - * Sparql Service should use the basic cors functionality - */ - /* - @Test - public void testCorsRequestOnSparqlService() throws UnsupportedEncodingException { - - //options request - given().header("Origin", "http://otherhost.com"). - expect().statusCode(200). - expect().header("Access-Control-Allow-Origin", "*"). - expect().header("Access-Control-Allow-Methods","POST, PUT, GET, DELETE, HEAD"). - when().options("/config/list"); - - //change configuration and retry - configurationService.setConfiguration("Access-Control-Allow-Origin","http://otherhost.com"); - - given().header("Origin", "http://otherhost.com"). - expect().statusCode(200). - expect().header("Access-Control-Allow-Origin", "http://otherhost.com"). - expect().header("Access-Control-Allow-Methods","POST, PUT, GET, DELETE, HEAD"). - when().options("/config/list"); - - //get request - given().header("Origin", "http://otherhost.com"). - given().header("Content-Type","application/json"). - given().content("[\"test\"]"). - expect().statusCode(200). - expect().header("Access-Control-Allow-Origin", "http://otherhost.com"). - expect().header("Access-Control-Allow-Methods","POST, PUT, GET, DELETE, HEAD"). - when().post("/config/data/key"); - - } - */ - /** - * resource Service should overwrite the basic cors functionality - */ - /* - @Test - public void testCorsRequestOnResourceService() { - //change configuration - configurationService.setConfiguration("Access-Control-Allow-Origin","http://my.host.com"); - - //options request - given().header("Origin", "http://otherhost.com"). - expect().statusCode(201). - expect().header("Access-Control-Allow-Origin", "*"). - expect().header("Access-Control-Allow-Methods","POST, PUT, GET, DELETE, HEAD"). - when().post("/resource/123"); - } - */ -}
