Add allowHeader property to WebContentGenerator

The WebContentGenerator now maintains an additional property that
sub-classes can use for an "Allow" header in response to an HTTP
OPTIONS request. This property is pre-initialized once at startup
and does not have to rely on getSupportedMethods in addition to
adding HTTP OPTIONS if not explicitly listed.

Issue: SPR-13130
This commit is contained in:
Rossen Stoyanchev
2016-01-25 15:58:18 -05:00
parent 4a0fa69ce4
commit 319e8e2c2f
2 changed files with 121 additions and 2 deletions

View File

@@ -16,7 +16,9 @@
package org.springframework.web.servlet.support;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -25,6 +27,8 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.http.CacheControl;
import org.springframework.http.HttpMethod;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.HttpSessionRequiredException;
@@ -51,6 +55,7 @@ import org.springframework.web.context.support.WebApplicationObjectSupport;
* @author Rod Johnson
* @author Juergen Hoeller
* @author Brian Clozel
* @author Rossen Stoyanchev
* @see #setCacheSeconds
* @see #setCacheControl
* @see #setRequireSession
@@ -76,6 +81,8 @@ public abstract class WebContentGenerator extends WebApplicationObjectSupport {
/** Set of supported HTTP methods */
private Set<String> supportedMethods;
private String allowHeader;
private boolean requireSession = false;
private CacheControl cacheControl;
@@ -115,6 +122,7 @@ public abstract class WebContentGenerator extends WebApplicationObjectSupport {
this.supportedMethods.add(METHOD_HEAD);
this.supportedMethods.add(METHOD_POST);
}
initAllowHeader();
}
/**
@@ -122,7 +130,28 @@ public abstract class WebContentGenerator extends WebApplicationObjectSupport {
* @param supportedMethods the supported HTTP methods for this content generator
*/
public WebContentGenerator(String... supportedMethods) {
this.supportedMethods = new LinkedHashSet<String>(Arrays.asList(supportedMethods));
setSupportedMethods(supportedMethods);
}
private void initAllowHeader() {
Collection<String> allowedMethods;
if (this.supportedMethods == null) {
allowedMethods = new ArrayList<String>(HttpMethod.values().length - 1);
for (HttpMethod method : HttpMethod.values()) {
if (!HttpMethod.TRACE.equals(method)) {
allowedMethods.add(method.name());
}
}
}
else if (this.supportedMethods.contains(HttpMethod.OPTIONS.name())) {
allowedMethods = this.supportedMethods;
}
else {
allowedMethods = new ArrayList<String>(this.supportedMethods);
allowedMethods.add(HttpMethod.OPTIONS.name());
}
this.allowHeader = StringUtils.collectionToCommaDelimitedString(allowedMethods);
}
@@ -132,12 +161,13 @@ public abstract class WebContentGenerator extends WebApplicationObjectSupport {
* unrestricted for general controllers and interceptors.
*/
public final void setSupportedMethods(String... methods) {
if (methods != null) {
if (!ObjectUtils.isEmpty(methods)) {
this.supportedMethods = new LinkedHashSet<String>(Arrays.asList(methods));
}
else {
this.supportedMethods = null;
}
initAllowHeader();
}
/**
@@ -147,6 +177,19 @@ public abstract class WebContentGenerator extends WebApplicationObjectSupport {
return StringUtils.toStringArray(this.supportedMethods);
}
/**
* Return the "Allow" header value to use in response to an HTTP OPTIONS
* request based on the configured {@link #setSupportedMethods supported
* methods} also automatically adding "OPTIONS" to the list even if not
* present as a supported method. This means sub-classes don't have to
* explicitly list "OPTIONS" as a supported method as long as HTTP OPTIONS
* requests are handled before making a call to
* {@link #checkRequest(HttpServletRequest)}.
*/
protected String getAllowHeader() {
return this.allowHeader;
}
/**
* Set whether a session should be required to handle requests.
*/