SPR-8536 When two methods match a request for any content type (i.e. Accept=*/* or no Accept header), choose the one that doesn't define any 'Accept' media types by default. This addresses an important use case where methods serving browsers typically don't specify Accept media types.
This commit is contained in:
@@ -16,6 +16,14 @@
|
||||
|
||||
package org.springframework.web.servlet.mvc.annotation;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
@@ -39,6 +47,7 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
@@ -51,7 +60,6 @@ import javax.validation.constraints.NotNull;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
|
||||
import org.springframework.aop.interceptor.SimpleTraceInterceptor;
|
||||
import org.springframework.aop.support.DefaultPointcutAdvisor;
|
||||
@@ -133,8 +141,6 @@ import org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMap
|
||||
import org.springframework.web.servlet.view.InternalResourceViewResolver;
|
||||
import org.springframework.web.util.NestedServletException;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
@@ -1869,6 +1875,40 @@ public class ServletAnnotationControllerTests {
|
||||
servlet.service(request, response);
|
||||
assertEquals(405, response.getStatus());
|
||||
}
|
||||
|
||||
// SPR-8536
|
||||
|
||||
@Test
|
||||
public void testHeadersCondition() throws Exception {
|
||||
initServlet(HeadersConditionController.class);
|
||||
|
||||
// No "Accept" header
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
|
||||
assertEquals(200, response.getStatus());
|
||||
assertEquals("home", response.getForwardedUrl());
|
||||
|
||||
// Accept "*/*"
|
||||
request = new MockHttpServletRequest("GET", "/");
|
||||
request.addHeader("Accept", "*/*");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
|
||||
assertEquals(200, response.getStatus());
|
||||
assertEquals("home", response.getForwardedUrl());
|
||||
|
||||
// Accept "application/json"
|
||||
request = new MockHttpServletRequest("GET", "/");
|
||||
request.addHeader("Accept", "application/json");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
|
||||
assertEquals(200, response.getStatus());
|
||||
assertEquals("application/json", response.getHeader("Content-Type"));
|
||||
assertEquals("homeJson", response.getContentAsString());
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@@ -3151,5 +3191,20 @@ public class ServletAnnotationControllerTests {
|
||||
writer.write("handle2");
|
||||
}
|
||||
}
|
||||
|
||||
@Controller
|
||||
static class HeadersConditionController {
|
||||
|
||||
@RequestMapping(value = "/", method = RequestMethod.GET)
|
||||
public String home() {
|
||||
return "home";
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/", method = RequestMethod.GET, headers="Accept=application/json")
|
||||
@ResponseBody
|
||||
public String homeJson() {
|
||||
return "homeJson";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ public class ProducesRequestConditionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareToSingle() {
|
||||
public void compareToWithSingleExpression() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Accept", "text/plain");
|
||||
|
||||
@@ -135,7 +135,7 @@ public class ProducesRequestConditionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareToMultiple() {
|
||||
public void compareToMultipleExpressions() {
|
||||
ProducesRequestCondition condition1 = new ProducesRequestCondition("*/*", "text/plain");
|
||||
ProducesRequestCondition condition2 = new ProducesRequestCondition("text/*", "text/plain;q=0.7");
|
||||
|
||||
@@ -147,22 +147,10 @@ public class ProducesRequestConditionTests {
|
||||
|
||||
result = condition2.compareTo(condition1, request);
|
||||
assertTrue("Invalid comparison result: " + result, result > 0);
|
||||
|
||||
condition1 = new ProducesRequestCondition("*/*");
|
||||
condition2 = new ProducesRequestCondition("text/*");
|
||||
|
||||
request = new MockHttpServletRequest();
|
||||
request.addHeader("Accept", "text/*");
|
||||
|
||||
result = condition1.compareTo(condition2, request);
|
||||
assertTrue("Invalid comparison result: " + result, result > 0);
|
||||
|
||||
result = condition2.compareTo(condition1, request);
|
||||
assertTrue("Invalid comparison result: " + result, result < 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareToMultipleAccept() {
|
||||
public void compareToMultipleExpressionsAndMultipeAcceptHeaderValues() {
|
||||
ProducesRequestCondition condition1 = new ProducesRequestCondition("text/*", "text/plain");
|
||||
ProducesRequestCondition condition2 = new ProducesRequestCondition("application/*", "application/xml");
|
||||
|
||||
@@ -186,7 +174,36 @@ public class ProducesRequestConditionTests {
|
||||
result = condition2.compareTo(condition1, request);
|
||||
assertTrue("Invalid comparison result: " + result, result < 0);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void compareToEmptyCondition() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Accept", "*/*");
|
||||
|
||||
ProducesRequestCondition condition1 = new ProducesRequestCondition();
|
||||
ProducesRequestCondition condition2 = new ProducesRequestCondition("application/json");
|
||||
|
||||
int result = condition1.compareTo(condition2, request);
|
||||
assertTrue("Invalid comparison result: " + result, result < 0);
|
||||
|
||||
result = condition2.compareTo(condition1, request);
|
||||
assertTrue("Invalid comparison result: " + result, result > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareToWithoutAcceptHeader() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
ProducesRequestCondition condition1 = new ProducesRequestCondition();
|
||||
ProducesRequestCondition condition2 = new ProducesRequestCondition("application/json");
|
||||
|
||||
int result = condition1.compareTo(condition2, request);
|
||||
assertTrue("Invalid comparison result: " + result, result < 0);
|
||||
|
||||
result = condition2.compareTo(condition1, request);
|
||||
assertTrue("Invalid comparison result: " + result, result > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void combine() {
|
||||
ProducesRequestCondition condition1 = new ProducesRequestCondition("text/plain");
|
||||
|
||||
@@ -1419,6 +1419,40 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
|
||||
assertEquals(405, response.getStatus());
|
||||
}
|
||||
|
||||
// SPR-8536
|
||||
|
||||
@Test
|
||||
public void testHeadersCondition() throws Exception {
|
||||
initServletWithControllers(HeadersConditionController.class);
|
||||
|
||||
// No "Accept" header
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
getServlet().service(request, response);
|
||||
|
||||
assertEquals(200, response.getStatus());
|
||||
assertEquals("home", response.getForwardedUrl());
|
||||
|
||||
// Accept "*/*"
|
||||
request = new MockHttpServletRequest("GET", "/");
|
||||
request.addHeader("Accept", "*/*");
|
||||
response = new MockHttpServletResponse();
|
||||
getServlet().service(request, response);
|
||||
|
||||
assertEquals(200, response.getStatus());
|
||||
assertEquals("home", response.getForwardedUrl());
|
||||
|
||||
// Accept "application/json"
|
||||
request = new MockHttpServletRequest("GET", "/");
|
||||
request.addHeader("Accept", "application/json");
|
||||
response = new MockHttpServletResponse();
|
||||
getServlet().service(request, response);
|
||||
|
||||
assertEquals(200, response.getStatus());
|
||||
assertEquals("application/json", response.getHeader("Content-Type"));
|
||||
assertEquals("homeJson", response.getContentAsString());
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Controllers
|
||||
@@ -2713,6 +2747,21 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
|
||||
}
|
||||
}
|
||||
|
||||
@Controller
|
||||
static class HeadersConditionController {
|
||||
|
||||
@RequestMapping(value = "/", method = RequestMethod.GET)
|
||||
public String home() {
|
||||
return "home";
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/", method = RequestMethod.GET, headers="Accept=application/json")
|
||||
@ResponseBody
|
||||
public String homeJson() {
|
||||
return "homeJson";
|
||||
}
|
||||
}
|
||||
|
||||
// Test cases deleted from the original SevletAnnotationControllerTests:
|
||||
|
||||
// @Ignore("Controller interface => no method-level @RequestMapping annotation")
|
||||
|
||||
Reference in New Issue
Block a user