Browse Source

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
pull/1120/head
Rossen Stoyanchev 9 years ago
parent
commit
319e8e2c2f
  1. 47
      spring-webmvc/src/main/java/org/springframework/web/servlet/support/WebContentGenerator.java
  2. 76
      spring-webmvc/src/test/java/org/springframework/web/servlet/support/WebContentGeneratorTests.java

47
spring-webmvc/src/main/java/org/springframework/web/servlet/support/WebContentGenerator.java

@ -16,7 +16,9 @@ @@ -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; @@ -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; @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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.
*/

76
spring-webmvc/src/test/java/org/springframework/web/servlet/support/WebContentGeneratorTests.java

@ -0,0 +1,76 @@ @@ -0,0 +1,76 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed 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.springframework.web.servlet.support;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/**
* Unit tests for {@link WebContentGenerator}.
* @author Rossen Stoyanchev
*/
public class WebContentGeneratorTests {
@Test
public void getAllowHeaderWithConstructorTrue() throws Exception {
WebContentGenerator generator = new TestWebContentGenerator(true);
assertEquals("GET,HEAD,POST,OPTIONS", generator.getAllowHeader());
}
@Test
public void getAllowHeaderWithConstructorFalse() throws Exception {
WebContentGenerator generator = new TestWebContentGenerator(false);
assertEquals("GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS", generator.getAllowHeader());
}
@Test
public void getAllowHeaderWithSupportedMethodsConstructor() throws Exception {
WebContentGenerator generator = new TestWebContentGenerator("POST");
assertEquals("POST,OPTIONS", generator.getAllowHeader());
}
@Test
public void getAllowHeaderWithSupportedMethodsSetter() throws Exception {
WebContentGenerator generator = new TestWebContentGenerator();
generator.setSupportedMethods("POST");
assertEquals("POST,OPTIONS", generator.getAllowHeader());
}
@Test
public void getAllowHeaderWithSupportedMethodsSetterEmpty() throws Exception {
WebContentGenerator generator = new TestWebContentGenerator();
generator.setSupportedMethods();
assertEquals("Effectively \"no restriction\" on supported methods",
"GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS", generator.getAllowHeader());
}
private static class TestWebContentGenerator extends WebContentGenerator {
public TestWebContentGenerator() {
}
public TestWebContentGenerator(boolean restrictDefaultSupportedMethods) {
super(restrictDefaultSupportedMethods);
}
public TestWebContentGenerator(String... supportedMethods) {
super(supportedMethods);
}
}
}
Loading…
Cancel
Save