mirror of
https://github.com/apache/struts.git
synced 2026-08-11 01:27:14 +00:00
WW-3017 - Making it possible to have a configurable list of uri-patterns telling struts not to handle the request
- applied patch provided by Andreas Joseph Krogh - made some refactoring to eliminate duplicate code and unneeded method calls - added integration test git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@768529 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
@@ -44,6 +44,9 @@ public final class StrutsConstants {
|
||||
/** The URL extension to use to determine if the request is meant for a Struts action */
|
||||
public static final String STRUTS_ACTION_EXTENSION = "struts.action.extension";
|
||||
|
||||
/** Comma separated list of patterns (java.util.regex.Pattern) to be excluded from Struts2-processing */
|
||||
public static final String STRUTS_ACTION_EXCLUDE_PATTERN = "struts.action.exclude_pattern";
|
||||
|
||||
/** Whether to use the alterative syntax for the tags or not */
|
||||
public static final String STRUTS_TAG_ALTSYNTAX = "struts.tag.altSyntax";
|
||||
|
||||
|
||||
@@ -25,10 +25,10 @@ import com.opensymphony.xwork2.ActionContext;
|
||||
import org.apache.struts2.dispatcher.Dispatcher;
|
||||
import org.apache.struts2.dispatcher.StaticContentLoader;
|
||||
import org.apache.struts2.util.ClassLoaderUtils;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Iterator;
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Contains initialization operations
|
||||
@@ -41,20 +41,20 @@ public class InitOperations {
|
||||
/**
|
||||
* Initializes the internal Struts logging
|
||||
*/
|
||||
public void initLogging(HostConfig filterConfig) {
|
||||
public void initLogging( HostConfig filterConfig ) {
|
||||
String factoryName = filterConfig.getInitParameter("loggerFactory");
|
||||
if (factoryName != null) {
|
||||
try {
|
||||
Class cls = ClassLoaderUtils.loadClass(factoryName, this.getClass());
|
||||
LoggerFactory fac = (LoggerFactory) cls.newInstance();
|
||||
LoggerFactory.setLoggerFactory(fac);
|
||||
} catch (InstantiationException e) {
|
||||
} catch ( InstantiationException e ) {
|
||||
System.err.println("Unable to instantiate logger factory: " + factoryName + ", using default");
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
} catch ( IllegalAccessException e ) {
|
||||
System.err.println("Unable to access logger factory: " + factoryName + ", using default");
|
||||
e.printStackTrace();
|
||||
} catch (ClassNotFoundException e) {
|
||||
} catch ( ClassNotFoundException e ) {
|
||||
System.err.println("Unable to locate logger factory class: " + factoryName + ", using default");
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -64,7 +64,7 @@ public class InitOperations {
|
||||
/**
|
||||
* Creates and initializes the dispatcher
|
||||
*/
|
||||
public Dispatcher initDispatcher(HostConfig filterConfig) {
|
||||
public Dispatcher initDispatcher( HostConfig filterConfig ) {
|
||||
Dispatcher dispatcher = createDispatcher(filterConfig);
|
||||
dispatcher.init();
|
||||
return dispatcher;
|
||||
@@ -73,7 +73,7 @@ public class InitOperations {
|
||||
/**
|
||||
* Initializes the static content loader with the filter configuration
|
||||
*/
|
||||
public StaticContentLoader initStaticContentLoader(HostConfig filterConfig, Dispatcher dispatcher) {
|
||||
public StaticContentLoader initStaticContentLoader( HostConfig filterConfig, Dispatcher dispatcher ) {
|
||||
StaticContentLoader loader = dispatcher.getContainer().getInstance(StaticContentLoader.class);
|
||||
loader.setHostConfig(filterConfig);
|
||||
return loader;
|
||||
@@ -81,6 +81,7 @@ public class InitOperations {
|
||||
|
||||
/**
|
||||
* @return The dispatcher on the thread.
|
||||
*
|
||||
* @throws IllegalStateException If there is no dispatcher available
|
||||
*/
|
||||
public Dispatcher findDispatcherOnThread() {
|
||||
@@ -92,11 +93,11 @@ public class InitOperations {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link Dispatcher}
|
||||
* Create a {@link Dispatcher}
|
||||
*/
|
||||
private Dispatcher createDispatcher(HostConfig filterConfig) {
|
||||
private Dispatcher createDispatcher( HostConfig filterConfig ) {
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
for (Iterator e = filterConfig.getInitParameterNames(); e.hasNext();) {
|
||||
for ( Iterator e = filterConfig.getInitParameterNames(); e.hasNext(); ) {
|
||||
String name = (String) e.next();
|
||||
String value = filterConfig.getInitParameter(name);
|
||||
params.put(name, value);
|
||||
@@ -107,4 +108,31 @@ public class InitOperations {
|
||||
public void cleanup() {
|
||||
ActionContext.setContext(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a list of patterns to exclude from request filtering
|
||||
*
|
||||
* @param dispatcher The dispatcher to check for exclude pattern configuration
|
||||
*
|
||||
* @return a List of Patterns for request to exclude if apply, or <tt>null</tt>
|
||||
*
|
||||
* @see org.apache.struts2.StrutsConstants#STRUTS_ACTION_EXCLUDE_PATTERN
|
||||
*/
|
||||
public List<Pattern> buildExcludedPatternsList( Dispatcher dispatcher ) {
|
||||
return buildExcludedPatternsList(dispatcher.getContainer().getInstance(String.class, StrutsConstants.STRUTS_ACTION_EXCLUDE_PATTERN));
|
||||
}
|
||||
|
||||
private List<Pattern> buildExcludedPatternsList( String patterns ) {
|
||||
if (null != patterns && patterns.trim().length() != 0) {
|
||||
List<Pattern> list = new ArrayList<Pattern>();
|
||||
String[] tokens = patterns.split(",");
|
||||
for ( String token : tokens ) {
|
||||
list.add(Pattern.compile(token.trim()));
|
||||
}
|
||||
return Collections.unmodifiableList(list);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.apache.struts2.dispatcher.Dispatcher;
|
||||
import org.apache.struts2.dispatcher.mapper.ActionMapping;
|
||||
import org.apache.struts2.dispatcher.mapper.ActionMapper;
|
||||
import org.apache.struts2.StrutsException;
|
||||
import org.apache.struts2.RequestUtils;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletContext;
|
||||
@@ -38,6 +39,8 @@ import com.opensymphony.xwork2.util.logging.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Contains preparation operations for a request before execution
|
||||
@@ -179,4 +182,48 @@ public class PrepareOperations {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the request matches a list of exclude patterns.
|
||||
*
|
||||
* @param request The request to check patterns against
|
||||
* @param excludedPatterns list of patterns for exclusion
|
||||
*
|
||||
* @return <tt>true</tt> if the request URI matches one of the given patterns
|
||||
*/
|
||||
public boolean isUrlExcluded( HttpServletRequest request, List<Pattern> excludedPatterns ) {
|
||||
if (excludedPatterns != null) {
|
||||
String uri = getUri(request);
|
||||
for ( Pattern pattern : excludedPatterns ) {
|
||||
if (pattern.matcher(uri).matches()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the uri from the request
|
||||
*
|
||||
* @param request The request
|
||||
*
|
||||
* @return The uri
|
||||
*/
|
||||
private String getUri( HttpServletRequest request ) {
|
||||
// handle http dispatcher includes.
|
||||
String uri = (String) request.getAttribute("javax.servlet.include.servlet_path");
|
||||
if (uri != null) {
|
||||
return uri;
|
||||
}
|
||||
|
||||
uri = RequestUtils.getServletPath(request);
|
||||
if (uri != null && !"".equals(uri)) {
|
||||
return uri;
|
||||
}
|
||||
|
||||
uri = request.getRequestURI();
|
||||
return uri.substring(request.getContextPath().length());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+13
-2
@@ -63,8 +63,15 @@ public class StrutsExecuteFilter implements StrutsStatics, Filter {
|
||||
HttpServletRequest request = (HttpServletRequest) req;
|
||||
HttpServletResponse response = (HttpServletResponse) res;
|
||||
|
||||
if (excludeUrl(request)) {
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
// This is necessary since we need the dispatcher instance, which was created by the prepare filter
|
||||
lazyInit();
|
||||
if (execute == null) {
|
||||
lazyInit();
|
||||
}
|
||||
|
||||
ActionMapping mapping = prepare.findActionMapping(request, response);
|
||||
if (mapping == null) {
|
||||
@@ -77,9 +84,13 @@ public class StrutsExecuteFilter implements StrutsStatics, Filter {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean excludeUrl(HttpServletRequest request) {
|
||||
return request.getAttribute(StrutsPrepareFilter.REQUEST_EXCLUDED_FROM_ACTION_MAPPING) != null;
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
prepare = null;
|
||||
execute = null;
|
||||
filterConfig = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+19
-11
@@ -22,15 +22,17 @@ package org.apache.struts2.dispatcher.ng.filter;
|
||||
|
||||
import org.apache.struts2.StrutsStatics;
|
||||
import org.apache.struts2.dispatcher.Dispatcher;
|
||||
import org.apache.struts2.dispatcher.ng.PrepareOperations;
|
||||
import org.apache.struts2.dispatcher.mapper.ActionMapping;
|
||||
import org.apache.struts2.dispatcher.ng.ExecuteOperations;
|
||||
import org.apache.struts2.dispatcher.ng.InitOperations;
|
||||
import org.apache.struts2.dispatcher.mapper.ActionMapping;
|
||||
import org.apache.struts2.dispatcher.ng.PrepareOperations;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Handles both the preparation and execution phases of the Struts dispatching process. This filter is better to use
|
||||
@@ -39,6 +41,7 @@ import java.io.IOException;
|
||||
public class StrutsPrepareAndExecuteFilter implements StrutsStatics, Filter {
|
||||
private PrepareOperations prepare;
|
||||
private ExecuteOperations execute;
|
||||
protected List<Pattern> excludedPatterns = null;
|
||||
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
InitOperations init = new InitOperations();
|
||||
@@ -50,6 +53,7 @@ public class StrutsPrepareAndExecuteFilter implements StrutsStatics, Filter {
|
||||
|
||||
prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
|
||||
execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);
|
||||
this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);
|
||||
} finally {
|
||||
init.cleanup();
|
||||
}
|
||||
@@ -66,15 +70,19 @@ public class StrutsPrepareAndExecuteFilter implements StrutsStatics, Filter {
|
||||
prepare.createActionContext(request, response);
|
||||
prepare.assignDispatcherToThread();
|
||||
request = prepare.wrapRequest(request);
|
||||
ActionMapping mapping = prepare.findActionMapping(request, response, true);
|
||||
if (mapping == null) {
|
||||
boolean handled = execute.executeStaticResourceRequest(request, response);
|
||||
if (!handled) {
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
} else {
|
||||
execute.executeAction(request, response, mapping);
|
||||
}
|
||||
if ( excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {
|
||||
chain.doFilter(request, response);
|
||||
} else {
|
||||
ActionMapping mapping = prepare.findActionMapping(request, response, true);
|
||||
if (mapping == null) {
|
||||
boolean handled = execute.executeStaticResourceRequest(request, response);
|
||||
if (!handled) {
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
} else {
|
||||
execute.executeAction(request, response, mapping);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
prepare.cleanupRequest(request);
|
||||
}
|
||||
|
||||
+16
-6
@@ -22,21 +22,27 @@ package org.apache.struts2.dispatcher.ng.filter;
|
||||
|
||||
import org.apache.struts2.StrutsStatics;
|
||||
import org.apache.struts2.dispatcher.Dispatcher;
|
||||
import org.apache.struts2.dispatcher.ng.PrepareOperations;
|
||||
import org.apache.struts2.dispatcher.ng.InitOperations;
|
||||
import org.apache.struts2.dispatcher.ng.PrepareOperations;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Prepares the request for execution by a later {@link org.apache.struts2.dispatcher.ng.filter.StrutsExecuteFilter} filter instance.
|
||||
*/
|
||||
public class StrutsPrepareFilter implements StrutsStatics, Filter {
|
||||
private PrepareOperations prepare;
|
||||
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
protected static final String REQUEST_EXCLUDED_FROM_ACTION_MAPPING = StrutsPrepareFilter.class.getName() + ".REQUEST_EXCLUDED_FROM_ACTION_MAPPING";
|
||||
|
||||
private PrepareOperations prepare;
|
||||
private List<Pattern> excludedPatterns = null;
|
||||
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
InitOperations init = new InitOperations();
|
||||
try {
|
||||
FilterHostConfig config = new FilterHostConfig(filterConfig);
|
||||
@@ -44,6 +50,7 @@ public class StrutsPrepareFilter implements StrutsStatics, Filter {
|
||||
Dispatcher dispatcher = init.initDispatcher(config);
|
||||
|
||||
prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
|
||||
this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);
|
||||
} finally {
|
||||
init.cleanup();
|
||||
}
|
||||
@@ -60,15 +67,18 @@ public class StrutsPrepareFilter implements StrutsStatics, Filter {
|
||||
prepare.createActionContext(request, response);
|
||||
prepare.assignDispatcherToThread();
|
||||
request = prepare.wrapRequest(request);
|
||||
prepare.findActionMapping(request, response);
|
||||
|
||||
if ( excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {
|
||||
request.setAttribute(REQUEST_EXCLUDED_FROM_ACTION_MAPPING, new Object());
|
||||
} else {
|
||||
prepare.findActionMapping(request, response);
|
||||
}
|
||||
chain.doFilter(request, response);
|
||||
} finally {
|
||||
prepare.cleanupRequest(request);
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
public void destroy() {
|
||||
prepare.cleanupDispatcher();
|
||||
}
|
||||
}
|
||||
+29
@@ -32,7 +32,10 @@ import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.FilterConfig;
|
||||
import java.io.IOException;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Integration tests for the filter
|
||||
@@ -113,6 +116,32 @@ public class StrutsPrepareAndExecuteFilterIntegrationTest extends TestCase {
|
||||
assertTrue((Boolean) request.getAttribute("__invoked"));
|
||||
}
|
||||
|
||||
public void testUriPatternExclusion() throws ServletException, IOException {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockFilterConfig filterConfig = new MockFilterConfig();
|
||||
MockFilterChain filterChain = new MockFilterChain() {
|
||||
@Override
|
||||
public void doFilter(ServletRequest req, ServletResponse res) {
|
||||
req.setAttribute("i_was", "invoked");
|
||||
}
|
||||
};
|
||||
|
||||
request.setRequestURI("/hello.action");
|
||||
StrutsPrepareAndExecuteFilter filter = new StrutsPrepareAndExecuteFilter() {
|
||||
@Override
|
||||
public void init( FilterConfig filterConfig ) throws ServletException {
|
||||
super.init(filterConfig);
|
||||
excludedPatterns = new ArrayList<Pattern>();
|
||||
excludedPatterns.add(Pattern.compile(".*hello.*"));
|
||||
}
|
||||
};
|
||||
filter.init(filterConfig);
|
||||
filter.doFilter(request, response, filterChain);
|
||||
assertEquals(200, response.getStatus());
|
||||
assertEquals("invoked", request.getAttribute("i_was"));
|
||||
}
|
||||
|
||||
public void testStaticFallthrough() throws ServletException, IOException {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
Reference in New Issue
Block a user