Modified: tomcat/trunk/test/org/apache/catalina/filters/TesterHttpServletResponse.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/filters/TesterHttpServletResponse.java?rev=1489385&r1=1489384&r2=1489385&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/catalina/filters/TesterHttpServletResponse.java (original) +++ tomcat/trunk/test/org/apache/catalina/filters/TesterHttpServletResponse.java Tue Jun 4 10:51:31 2013 @@ -19,7 +19,10 @@ package org.apache.catalina.filters; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.Locale; import javax.servlet.ServletOutputStream; @@ -36,10 +39,66 @@ import org.apache.catalina.connector.Req */ public class TesterHttpServletResponse implements HttpServletResponse { + private PrintWriter pw; + private List<String> headerNames = new ArrayList<>(); + private List<String> headerValues = new ArrayList<>(); + private int status; + public TesterHttpServletResponse() { // NOOP } + + @Override + public PrintWriter getWriter() throws IOException { + if (pw == null) { + pw = new PrintWriter(new StringWriter()); + } + return pw; + } + + + @Override + public String getHeader(String name) { + int index = headerNames.indexOf(name); + if (index != -1) { + return headerValues.get(index); + } + return null; + } + + + @Override + public void setHeader(String name, String value) { + int index = headerNames.indexOf(name); + if (index != -1) { + headerValues.set(index, value); + } else { + headerNames.add(name); + headerValues.add(value); + } + } + + + @Override + public void addHeader(String name, String value) { + headerNames.add(name); + headerValues.add(value); + } + + + @Override + public int getStatus() { + return status; + } + + + @Override + public void setStatus(int status) { + this.status = status; + } + + public void setAppCommitted( @SuppressWarnings("unused") boolean appCommitted) {/* NOOP */} public boolean isAppCommitted() { return false; } @@ -124,8 +183,6 @@ public class TesterHttpServletResponse i @Override public Locale getLocale() { return null; } @Override - public PrintWriter getWriter() throws IOException { return null; } - @Override public boolean isCommitted() { return false; } @Override public void reset() {/* NOOP */} @@ -140,14 +197,10 @@ public class TesterHttpServletResponse i @Override public void setLocale(Locale locale) {/* NOOP */} @Override - public String getHeader(String name) { return null; } - @Override public Collection<String> getHeaderNames() { return null; } @Override public Collection<String> getHeaders(String name) { return null; } public String getMessage() { return null; } - @Override - public int getStatus() { return -1; } public void reset(@SuppressWarnings("unused") int status, @SuppressWarnings("unused") String message) {/* NOOP */} @Override @@ -155,8 +208,6 @@ public class TesterHttpServletResponse i @Override public void addDateHeader(String name, long value) {/* NOOP */} @Override - public void addHeader(String name, String value) {/* NOOP */} - @Override public void addIntHeader(String name, int value) {/* NOOP */} @Override public boolean containsHeader(String name) { return false; } @@ -188,11 +239,7 @@ public class TesterHttpServletResponse i @Override public void setDateHeader(String name, long value) {/* NOOP */} @Override - public void setHeader(String name, String value) {/* NOOP */} - @Override public void setIntHeader(String name, int value) {/* NOOP */} - @Override - public void setStatus(int status) {/* NOOP */} /** @deprecated */ @Override @Deprecated
Added: tomcat/trunk/test/org/apache/catalina/filters/TesterServletContext.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/filters/TesterServletContext.java?rev=1489385&view=auto ============================================================================== --- tomcat/trunk/test/org/apache/catalina/filters/TesterServletContext.java (added) +++ tomcat/trunk/test/org/apache/catalina/filters/TesterServletContext.java Tue Jun 4 10:51:31 2013 @@ -0,0 +1,320 @@ +/* + * 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.catalina.filters; + +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Enumeration; +import java.util.EventListener; +import java.util.Map; +import java.util.Set; + +import javax.servlet.Filter; +import javax.servlet.FilterRegistration; +import javax.servlet.RequestDispatcher; +import javax.servlet.Servlet; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRegistration; +import javax.servlet.ServletRegistration.Dynamic; +import javax.servlet.SessionCookieConfig; +import javax.servlet.SessionTrackingMode; +import javax.servlet.descriptor.JspConfigDescriptor; + +public class TesterServletContext implements ServletContext { + + @Override + public String getContextPath() { + throw new RuntimeException("Not implemented"); + } + + @Override + public ServletContext getContext(String uripath) { + throw new RuntimeException("Not implemented"); + } + + @Override + public int getMajorVersion() { + throw new RuntimeException("Not implemented"); + } + + @Override + public int getMinorVersion() { + throw new RuntimeException("Not implemented"); + } + + @Override + public String getMimeType(String file) { + throw new RuntimeException("Not implemented"); + } + + @Override + public Set<String> getResourcePaths(String path) { + throw new RuntimeException("Not implemented"); + } + + @Override + public URL getResource(String path) throws MalformedURLException { + throw new RuntimeException("Not implemented"); + } + + @Override + public InputStream getResourceAsStream(String path) { + throw new RuntimeException("Not implemented"); + } + + @Override + public RequestDispatcher getRequestDispatcher(String path) { + + throw new RuntimeException("Not implemented"); + } + + @Override + public RequestDispatcher getNamedDispatcher(String name) { + + throw new RuntimeException("Not implemented"); + } + + @Override + public Servlet getServlet(String name) throws ServletException { + + throw new RuntimeException("Not implemented"); + } + + @Override + public Enumeration<Servlet> getServlets() { + + throw new RuntimeException("Not implemented"); + } + + @Override + public Enumeration<String> getServletNames() { + + throw new RuntimeException("Not implemented"); + } + + @Override + public void log(String msg) { + // NOOP + } + + @Override + public void log(Exception exception, String msg) { + // NOOP + } + + @Override + public void log(String message, Throwable throwable) { + // NOOP + } + + @Override + public String getRealPath(String path) { + + throw new RuntimeException("Not implemented"); + } + + @Override + public String getServerInfo() { + + throw new RuntimeException("Not implemented"); + } + + @Override + public String getInitParameter(String name) { + + throw new RuntimeException("Not implemented"); + } + + @Override + public Enumeration<String> getInitParameterNames() { + + throw new RuntimeException("Not implemented"); + } + + @Override + public Object getAttribute(String name) { + + throw new RuntimeException("Not implemented"); + } + + @Override + public Enumeration<String> getAttributeNames() { + + throw new RuntimeException("Not implemented"); + } + + @Override + public void setAttribute(String name, Object object) { + throw new RuntimeException("Not implemented"); + } + + @Override + public void removeAttribute(String name) { + throw new RuntimeException("Not implemented"); + } + + @Override + public String getServletContextName() { + throw new RuntimeException("Not implemented"); + } + + @Override + public int getEffectiveMajorVersion() { + throw new RuntimeException("Not implemented"); + } + + @Override + public int getEffectiveMinorVersion() { + throw new RuntimeException("Not implemented"); + } + + @Override + public boolean setInitParameter(String name, String value) { + throw new RuntimeException("Not implemented"); + } + + @Override + public Dynamic addServlet(String servletName, String className) { + throw new RuntimeException("Not implemented"); + } + + @Override + public Dynamic addServlet(String servletName, Servlet servlet) { + throw new RuntimeException("Not implemented"); + } + + @Override + public Dynamic addServlet(String servletName, + Class<? extends Servlet> servletClass) { + throw new RuntimeException("Not implemented"); + } + + @Override + public <T extends Servlet> T createServlet(Class<T> c) + throws ServletException { + throw new RuntimeException("Not implemented"); + } + + @Override + public ServletRegistration getServletRegistration(String servletName) { + throw new RuntimeException("Not implemented"); + } + + @Override + public Map<String, ? extends ServletRegistration> getServletRegistrations() { + throw new RuntimeException("Not implemented"); + } + + @Override + public javax.servlet.FilterRegistration.Dynamic addFilter( + String filterName, String className) { + throw new RuntimeException("Not implemented"); + } + + @Override + public javax.servlet.FilterRegistration.Dynamic addFilter( + String filterName, Filter filter) { + throw new RuntimeException("Not implemented"); + } + + @Override + public javax.servlet.FilterRegistration.Dynamic addFilter( + String filterName, Class<? extends Filter> filterClass) { + throw new RuntimeException("Not implemented"); + } + + @Override + public <T extends Filter> T createFilter(Class<T> c) + throws ServletException { + throw new RuntimeException("Not implemented"); + } + + @Override + public FilterRegistration getFilterRegistration(String filterName) { + throw new RuntimeException("Not implemented"); + } + + @Override + public Map<String, ? extends FilterRegistration> getFilterRegistrations() { + throw new RuntimeException("Not implemented"); + } + + @Override + public SessionCookieConfig getSessionCookieConfig() { + throw new RuntimeException("Not implemented"); + } + + @Override + public void setSessionTrackingModes( + Set<SessionTrackingMode> sessionTrackingModes) { + throw new RuntimeException("Not implemented"); + } + + @Override + public Set<SessionTrackingMode> getDefaultSessionTrackingModes() { + throw new RuntimeException("Not implemented"); + } + + @Override + public Set<SessionTrackingMode> getEffectiveSessionTrackingModes() { + throw new RuntimeException("Not implemented"); + } + + @Override + public void addListener(String className) { + throw new RuntimeException("Not implemented"); + } + + @Override + public <T extends EventListener> void addListener(T t) { + throw new RuntimeException("Not implemented"); + } + + @Override + public void addListener(Class<? extends EventListener> listenerClass) { + throw new RuntimeException("Not implemented"); + } + + @Override + public <T extends EventListener> T createListener(Class<T> c) + throws ServletException { + throw new RuntimeException("Not implemented"); + } + + @Override + public JspConfigDescriptor getJspConfigDescriptor() { + throw new RuntimeException("Not implemented"); + } + + @Override + public ClassLoader getClassLoader() { + throw new RuntimeException("Not implemented"); + } + + @Override + public void declareRoles(String... roleNames) { + throw new RuntimeException("Not implemented"); + } + + @Override + public String getVirtualServerName() { + throw new RuntimeException("Not implemented"); + } + +} Propchange: tomcat/trunk/test/org/apache/catalina/filters/TesterServletContext.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: tomcat/trunk/webapps/docs/config/filter.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/filter.xml?rev=1489385&r1=1489384&r2=1489385&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/config/filter.xml (original) +++ tomcat/trunk/webapps/docs/config/filter.xml Tue Jun 4 10:51:31 2013 @@ -98,6 +98,157 @@ </section> +<section name="CORS Filter"> + <subsection name="Introduction"> + <p>This filter is an implementation of W3C's CORS (Cross-Origin Resource + Sharing) <a href="http://www.w3.org/TR/cors/">specification</a>, which is a + mechanism that enables cross-origin requests.</p> + <p>The filter works by adding required <code>Access-Control-*</code> headers + to HttpServletResponse object. The filter also protects against HTTP + response splitting. If request is invalid, or is not permitted, then request + is rejected with HTTP status code 403 (Forbidden). A + <a href="../images/cors-flowchart.png">flowchart</a> that + demonstrates request processing by this filter is available.</p> + <p>The minimal configuration required to use this filter is:</p> + <source> +<filter> + <filter-name>CORSFilter</filter-name> + <filter-class>org.apache.catalina.filters.CORSFilter</filter-class> +</filter> +<filter-mapping> + <filter-name>CORSFilter</filter-name> + <url-pattern>/*</url-pattern> +</filter-mapping> + </source> + </subsection> + <subsection name="Filter Class Name"> + <p>The filter class name for the CORS Filter is + <strong><code>org.apache.catalina.filters.CORSFilter</code></strong>.</p> + </subsection> + <subsection name="Initialisation parameters"> + <p>The CORS Filter supports following initialisation parameters:</p> + <attributes> + <attribute name="cors.allowed.origins" required="false"> + <p>A list of <a href="http://tools.ietf.org/html/rfc6454">origins</a> + that are allowed to access the resource. A <code>'*'</code> can be + specified to enable access to resource from any origin. Otherwise, a + whitelist of comma separated origins can be provided. Eg: + http://www.w3.org, https://www.apache.org. + <strong>Defaults:</strong> <code>*</code> (Any origin is allowed to + access the resource).</p> + </attribute> + <attribute name="cors.allowed.methods" required="false"> + <p>A comma separated list of HTTP methods that can be used to access the + resource, using cross-origin requests. These are the methods which will + also be included as part of 'Access-Control-Allow-Methods' header in a + pre-flight response. Eg: <code>GET,POST</code>. + <strong>Defaults:</strong> <code>GET,POST,HEAD,OPTIONS</code></p> + </attribute> + <attribute name="cors.allowed.headers" required="false"> + <p>A comma separated list of request headers that can be used when + making an actual request. These header will also be returned as part of + <code>'Access-Control-Allow-Headers'</code> header in a pre-flight + response. Eg: <code>Origin,Accept</code>. <strong>Defaults:</strong> + <code>Origin, Accept, X-Requested-With, Content-Type, + Access-Control-Request-Method, Access-Control-Request-Headers</code></p> + </attribute> + <attribute name="cors.exposed.headers" required="false"> + <p>A comma separated list of headers other than the simple response + headers that browsers are allowed to access. These are the headers which + will also be included as part of 'Access-Control-Expose-Headers' header + in the pre-flight response. Eg: + <code>X-CUSTOM-HEADER-PING,X-CUSTOM-HEADER-PONG</code>. + <strong>Default:</strong> None. Non-simple headers are not exposed by + default.</p> + </attribute> + <attribute name="cors.preflight.maxage" required="false"> + <p>The amount of seconds, browser is allowed to cache the result of the + pre-flight request. This will be included as part of + <code>'Access-Control-Max-Age'</code> header in the pre-flight response. + A negative value will prevent CORS Filter from adding this response + header from pre-flight response. <strong>Defaults:</strong> + <code>1800</code></p> + </attribute> + <attribute name="cors.support.credentials" required="false"> + <p>A flag that indicates whether the resource supports user credentials. + This flag is exposed as part of + <code>'Access-Control-Allow-Credentials'</code> header in a pre-flight + response. It helps browser determine whether or not an actual request + can be made using credentials. <strong>Defaults:</strong> + <code>true</code></p> + </attribute> + <attribute name="cors.request.decorate" required="false"> + <p>A flag to control if CORS specific attributes should be added to + HttpServletRequest object or not. <strong>Defaults:</strong> + <code>true</code></p> + </attribute> + </attributes> + <p>Here's an example of a more advanced configuration, that overrides + defaults:</p> + <source> +<filter> + <filter-name>CORSFilter</filter-name> + <filter-class>org.apache.catalina.filters.CORSFilter</filter-class> + <init-param> + <param-name>cors.allowed.origins</param-name> + <param-value>*</param-value> + </init-param> + <init-param> + <param-name>cors.allowed.methods</param-name> + <param-value>GET,POST,HEAD,OPTIONS,PUT</param-value> + </init-param> + <init-param> + <param-name>cors.allowed.headers</param-name> + <param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers</param-value> + </init-param> + <init-param> + <param-name>cors.exposed.headers</param-name> + <param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials</param-value> + </init-param> + <init-param> + <param-name>cors.support.credentials</param-name> + <param-value>true</param-value> + </init-param> + <init-param> + <param-name>cors.preflight.maxage</param-name> + <param-value>10</param-value> + </init-param> +</filter> +<filter-mapping> + <filter-name>CORS Filter</filter-name> + <url-pattern>/*</url-pattern> +</filter-mapping> + </source> + </subsection> + <subsection name="CORS Filter and HttpServletRequest attributes"> + <p>CORS Filter adds information about a request, in the HttpServletRequest + object, for consumption downstream. Following attributes are set, if + <code>cors.request.decorate</code> initialisation parameter is + <code>true</code>:</p> + <ul> + <li><strong>cors.isCorsRequest:</strong> Flag to determine if a request is + a CORS request.</li> + <li><strong>cors.request.origin:</strong> The Origin URL, i.e. the URL of + the page from where the request is originated.</li> + <li><strong>cors.request.type:</strong> Type of CORS request. Possible + values: + <ul> + <li><code>SIMPLE</code>: A request which is not preceded by a + pre-flight request.</li> + <li><code>ACTUAL</code>: A request which is preceded by a pre-flight + request.</li> + <li><code>PRE_FLIGHT</code>: A pre-flight request.</li> + <li><code>NOT_CORS</code>: A normal same-origin request.</li> + <li><code>INVALID_CORS</code>: A cross-origin request, which is + invalid.</li> + </ul> + </li> + <li><strong>cors.request.headers:</strong> Request headers sent as + 'Access-Control-Request-Headers' header, for a pre-flight request. + </li> + </ul> + </subsection> +</section> <section name="CSRF Prevention Filter"> @@ -525,6 +676,49 @@ FINE: Request "/docs/config/manager.html </section> +<section name="Failed Request Filter"> + + <subsection name="Introduction"> + + <p>This filter triggers parameters parsing in a request and rejects the + request if some parameters were skipped during parameter parsing because + of parsing errors or request size limitations (such as + <code>maxParameterCount</code> attribute in a + <a href="http.html">Connector</a>). + This filter can be used to ensure that none parameter values submitted by + client are lost.</p> + + <p>Note that parameter parsing may consume the body of an HTTP request, so + caution is needed if the servlet protected by this filter uses + <code>request.getInputStream()</code> or <code>request.getReader()</code> + calls. In general the risk of breaking a web application by adding this + filter is not so high, because parameter parsing does check content type + of the request before consuming the request body.</p> + + <p>Note, that for the POST requests to be parsed correctly, a + <code>SetCharacterEncodingFilter</code> filter must be configured above + this one. See CharacterEncoding page in the FAQ for details.</p> + + <p>The request is rejected with HTTP status code 400 (Bad Request).</p> + + </subsection> + + <subsection name="Filter Class Name"> + + <p>The filter class name for the Failed Request Filter is + <strong><code>org.apache.catalina.filters.FailedRequestFilter</code> + </strong>.</p> + + </subsection> + + <subsection name="Initialisation parameters"> + + <p>The Failed Request Filter does not support any initialization parameters.</p> + + </subsection> + +</section> + <section name="Remote Address Filter"> <subsection name="Introduction"> @@ -1265,52 +1459,6 @@ org.apache.catalina.filters.RequestDumpe </section> - -<section name="Failed Request Filter"> - - <subsection name="Introduction"> - - <p>This filter triggers parameters parsing in a request and rejects the - request if some parameters were skipped during parameter parsing because - of parsing errors or request size limitations (such as - <code>maxParameterCount</code> attribute in a - <a href="http.html">Connector</a>). - This filter can be used to ensure that none parameter values submitted by - client are lost.</p> - - <p>Note that parameter parsing may consume the body of an HTTP request, so - caution is needed if the servlet protected by this filter uses - <code>request.getInputStream()</code> or <code>request.getReader()</code> - calls. In general the risk of breaking a web application by adding this - filter is not so high, because parameter parsing does check content type - of the request before consuming the request body.</p> - - <p>Note, that for the POST requests to be parsed correctly, a - <code>SetCharacterEncodingFilter</code> filter must be configured above - this one. See CharacterEncoding page in the FAQ for details.</p> - - <p>The request is rejected with HTTP status code 400 (Bad Request).</p> - - </subsection> - - <subsection name="Filter Class Name"> - - <p>The filter class name for the Failed Request Filter is - <strong><code>org.apache.catalina.filters.FailedRequestFilter</code> - </strong>.</p> - - </subsection> - - <subsection name="Initialisation parameters"> - - <p>The Failed Request Filter does not support any initialization parameters.</p> - - </subsection> - -</section> - - </body> - </document> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org