From 135738f9bfb5b9dacf164d6561144589dc98deb8 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Mon, 25 Jan 2016 08:47:52 -0500 Subject: [PATCH] AbstractController supports HTTP OPTIONS Issue: SPR-13130 --- .../web/servlet/setup/AbstractMockMvcBuilder.java | 4 ++-- .../web/servlet/mvc/AbstractController.java | 15 ++++++++++++++- .../mvc/ParameterizableViewController.java | 6 ++++++ .../web/servlet/support/WebContentGenerator.java | 9 ++++----- .../mvc/ParameterizableViewControllerTests.java | 13 ++++++++++++- 5 files changed, 38 insertions(+), 9 deletions(-) diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/setup/AbstractMockMvcBuilder.java b/spring-test/src/main/java/org/springframework/test/web/servlet/setup/AbstractMockMvcBuilder.java index 21dd9ebbf8..50c4db84c2 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/setup/AbstractMockMvcBuilder.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/setup/AbstractMockMvcBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * 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. @@ -55,7 +55,7 @@ public abstract class AbstractMockMvcBuilder private final List globalResultHandlers = new ArrayList(); - private Boolean dispatchOptions = Boolean.FALSE; + private Boolean dispatchOptions = Boolean.TRUE; private final List configurers = new ArrayList(4); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/AbstractController.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/AbstractController.java index fcd27016d4..42ce91e6ed 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/AbstractController.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/AbstractController.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * 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. @@ -16,10 +16,15 @@ package org.springframework.web.servlet.mvc; +import java.util.Arrays; +import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import org.springframework.http.HttpMethod; +import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.support.WebContentGenerator; import org.springframework.web.util.WebUtils; @@ -87,6 +92,7 @@ import org.springframework.web.util.WebUtils; * * @author Rod Johnson * @author Juergen Hoeller + * @author Rossen Stoyanchev * @see WebContentInterceptor */ public abstract class AbstractController extends WebContentGenerator implements Controller { @@ -149,6 +155,13 @@ public abstract class AbstractController extends WebContentGenerator implements public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { + String[] supportedMethods = getSupportedMethods(); + if (HttpMethod.OPTIONS.matches(request.getMethod()) && !ObjectUtils.isEmpty(supportedMethods)) { + List value = Arrays.asList(supportedMethods); + response.setHeader("Allow", StringUtils.collectionToCommaDelimitedString(value)); + return null; + } + // Delegate to WebContentGenerator for checking and preparing. checkRequest(request); prepareResponse(response); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/ParameterizableViewController.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/ParameterizableViewController.java index bee1886117..5d512887dd 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/ParameterizableViewController.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/ParameterizableViewController.java @@ -19,6 +19,7 @@ package org.springframework.web.servlet.mvc; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.View; @@ -43,6 +44,11 @@ public class ParameterizableViewController extends AbstractController { private boolean statusOnly; + public ParameterizableViewController() { + super(false); + setSupportedMethods(HttpMethod.GET.name(), HttpMethod.HEAD.name()); + } + /** * Set a view name for the ModelAndView to return, to be resolved by the * DispatcherServlet via a ViewResolver. Will override any pre-existing diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/support/WebContentGenerator.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/support/WebContentGenerator.java index 8bf68bba4a..dca9e5dcb2 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/support/WebContentGenerator.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/support/WebContentGenerator.java @@ -17,10 +17,9 @@ package org.springframework.web.servlet.support; import java.util.Arrays; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Set; import java.util.concurrent.TimeUnit; - import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -111,7 +110,7 @@ public abstract class WebContentGenerator extends WebApplicationObjectSupport { */ public WebContentGenerator(boolean restrictDefaultSupportedMethods) { if (restrictDefaultSupportedMethods) { - this.supportedMethods = new HashSet(4); + this.supportedMethods = new LinkedHashSet(4); this.supportedMethods.add(METHOD_GET); this.supportedMethods.add(METHOD_HEAD); this.supportedMethods.add(METHOD_POST); @@ -123,7 +122,7 @@ public abstract class WebContentGenerator extends WebApplicationObjectSupport { * @param supportedMethods the supported HTTP methods for this content generator */ public WebContentGenerator(String... supportedMethods) { - this.supportedMethods = new HashSet(Arrays.asList(supportedMethods)); + this.supportedMethods = new LinkedHashSet(Arrays.asList(supportedMethods)); } @@ -134,7 +133,7 @@ public abstract class WebContentGenerator extends WebApplicationObjectSupport { */ public final void setSupportedMethods(String... methods) { if (methods != null) { - this.supportedMethods = new HashSet(Arrays.asList(methods)); + this.supportedMethods = new LinkedHashSet(Arrays.asList(methods)); } else { this.supportedMethods = null; diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/ParameterizableViewControllerTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/ParameterizableViewControllerTests.java index f7d416e5d5..efa34af223 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/ParameterizableViewControllerTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/ParameterizableViewControllerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * 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. @@ -19,6 +19,7 @@ package org.springframework.web.servlet.mvc; import org.junit.Before; import org.junit.Test; +import org.springframework.http.HttpMethod; import org.springframework.mock.web.test.MockHttpServletRequest; import org.springframework.mock.web.test.MockHttpServletResponse; import org.springframework.ui.ModelMap; @@ -69,4 +70,14 @@ public class ParameterizableViewControllerTests { assertEquals("value", mav.getModel().get("name")); } + @Test + public void handleRequestHttpOptions() throws Exception { + this.request.setMethod(HttpMethod.OPTIONS.name()); + MockHttpServletResponse response = new MockHttpServletResponse(); + ModelAndView mav = this.controller.handleRequest(this.request, response); + + assertNull(mav); + assertEquals("GET,HEAD", response.getHeader("Allow")); + } + }