SPR-6301 - Support @RequestHeader on HttpHeaders parameters
This commit is contained in:
parent
a62b413be4
commit
8de34c6fa7
|
|
@ -96,6 +96,10 @@ public class PortletWebRequest extends PortletRequestAttributes implements Nativ
|
||||||
return (!ObjectUtils.isEmpty(headerValues) ? headerValues : null);
|
return (!ObjectUtils.isEmpty(headerValues) ? headerValues : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Iterator<String> getHeaderNames() {
|
||||||
|
return CollectionUtils.toIterator(getRequest().getPropertyNames());
|
||||||
|
}
|
||||||
|
|
||||||
public String getParameter(String paramName) {
|
public String getParameter(String paramName) {
|
||||||
return getRequest().getParameter(paramName);
|
return getRequest().getParameter(paramName);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ import org.springframework.http.HttpInputMessage;
|
||||||
import org.springframework.http.HttpOutputMessage;
|
import org.springframework.http.HttpOutputMessage;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.converter.HttpMessageConverter;
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
import org.springframework.http.converter.HttpMessageNotReadableException;
|
import org.springframework.http.converter.HttpMessageNotReadableException;
|
||||||
import org.springframework.http.converter.HttpMessageNotWritableException;
|
import org.springframework.http.converter.HttpMessageNotWritableException;
|
||||||
|
|
@ -1134,6 +1135,31 @@ public class ServletAnnotationControllerTests {
|
||||||
assertEquals("key1=[value1],key2=[value21,value22]", response.getContentAsString());
|
assertEquals("key1=[value1],key2=[value21,value22]", response.getContentAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void requestHeaderMap() throws Exception {
|
||||||
|
initServlet(RequestHeaderMapController.class);
|
||||||
|
|
||||||
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/map");
|
||||||
|
request.addHeader("Content-Type", "text/html");
|
||||||
|
request.addHeader("Custom-Header", new String[]{"value21", "value22"});
|
||||||
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
|
|
||||||
|
servlet.service(request, response);
|
||||||
|
assertEquals("Content-Type=text/html,Custom-Header=value21", response.getContentAsString());
|
||||||
|
|
||||||
|
request.setRequestURI("/multiValueMap");
|
||||||
|
response = new MockHttpServletResponse();
|
||||||
|
|
||||||
|
servlet.service(request, response);
|
||||||
|
assertEquals("Content-Type=[text/html],Custom-Header=[value21,value22]", response.getContentAsString());
|
||||||
|
|
||||||
|
request.setRequestURI("/httpHeaders");
|
||||||
|
response = new MockHttpServletResponse();
|
||||||
|
|
||||||
|
servlet.service(request, response);
|
||||||
|
assertEquals("Content-Type=[text/html],Custom-Header=[value21,value22]", response.getContentAsString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Controllers
|
* Controllers
|
||||||
|
|
@ -1965,6 +1991,48 @@ public class ServletAnnotationControllerTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public static class RequestHeaderMapController {
|
||||||
|
|
||||||
|
@RequestMapping("/map")
|
||||||
|
public void map(@RequestHeader Map<String, String> headers, Writer writer) throws IOException {
|
||||||
|
for (Iterator<Map.Entry<String, String>> it = headers.entrySet().iterator(); it.hasNext();) {
|
||||||
|
Map.Entry<String, String> entry = it.next();
|
||||||
|
writer.write(entry.getKey() + "=" + entry.getValue());
|
||||||
|
if (it.hasNext()) {
|
||||||
|
writer.write(',');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/multiValueMap")
|
||||||
|
public void multiValueMap(@RequestHeader MultiValueMap<String, String> headers, Writer writer) throws IOException {
|
||||||
|
for (Iterator<Map.Entry<String, List<String>>> it1 = headers.entrySet().iterator(); it1.hasNext();) {
|
||||||
|
Map.Entry<String, List<String>> entry = it1.next();
|
||||||
|
writer.write(entry.getKey() + "=[");
|
||||||
|
for (Iterator<String> it2 = entry.getValue().iterator(); it2.hasNext();) {
|
||||||
|
String value = it2.next();
|
||||||
|
writer.write(value);
|
||||||
|
if (it2.hasNext()) {
|
||||||
|
writer.write(',');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writer.write(']');
|
||||||
|
if (it1.hasNext()) {
|
||||||
|
writer.write(',');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/httpHeaders")
|
||||||
|
public void httpHeaders(@RequestHeader HttpHeaders headers, Writer writer) throws IOException {
|
||||||
|
assertEquals("Invalid Content-Type", new MediaType("text", "html"), headers.getContentType());
|
||||||
|
multiValueMap(headers, writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,12 +77,16 @@ import java.lang.annotation.Target;
|
||||||
* <li>{@link RequestParam @RequestParam} annotated parameters for access to
|
* <li>{@link RequestParam @RequestParam} annotated parameters for access to
|
||||||
* specific Servlet/Portlet request parameters. Parameter values will be
|
* specific Servlet/Portlet request parameters. Parameter values will be
|
||||||
* converted to the declared method argument type. Additionally,
|
* converted to the declared method argument type. Additionally,
|
||||||
* {@code RequestParam @RequestParam} can be used on a {@link java.util.Map Map} or
|
* {@code @RequestParam} can be used on a {@link java.util.Map Map<String, String>} or
|
||||||
* {@link org.springframework.util.MultiValueMap MultiValueMap} to gain access
|
* {@link org.springframework.util.MultiValueMap MultiValueMap<String, String>}
|
||||||
* to all request parameters.
|
* method parameter to gain access to all request parameters.
|
||||||
* <li>{@link RequestHeader @RequestHeader} annotated parameters for access to
|
* <li>{@link RequestHeader @RequestHeader} annotated parameters for access to
|
||||||
* specific Servlet/Portlet request HTTP headers. Parameter values will be
|
* specific Servlet/Portlet request HTTP headers. Parameter values will be
|
||||||
* converted to the declared method argument type.
|
* converted to the declared method argument type. Additionally,
|
||||||
|
* {@code @RequestHeader} can be used on a {@link java.util.Map Map<String, String>},
|
||||||
|
* {@link org.springframework.util.MultiValueMap MultiValueMap<String, String>}, or
|
||||||
|
* {@link org.springframework.http.HttpHeaders HttpHeaders} method parameter to
|
||||||
|
* gain access to all request headers.
|
||||||
* <li>{@link RequestBody @RequestBody} annotated parameters for access to
|
* <li>{@link RequestBody @RequestBody} annotated parameters for access to
|
||||||
* the Servlet request HTTP contents. Parameter values will be
|
* the Servlet request HTTP contents. Parameter values will be
|
||||||
* converted to the declared method argument type using
|
* converted to the declared method argument type using
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
@ -41,6 +42,7 @@ import org.springframework.core.ParameterNameDiscoverer;
|
||||||
import org.springframework.core.annotation.AnnotationUtils;
|
import org.springframework.core.annotation.AnnotationUtils;
|
||||||
import org.springframework.http.HttpInputMessage;
|
import org.springframework.http.HttpInputMessage;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.converter.HttpMessageConverter;
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
import org.springframework.ui.ExtendedModelMap;
|
import org.springframework.ui.ExtendedModelMap;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
|
|
@ -457,11 +459,15 @@ public class HandlerMethodInvoker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
private Object resolveRequestHeader(String headerName, boolean required, String defaultValue,
|
private Object resolveRequestHeader(String headerName, boolean required, String defaultValue,
|
||||||
MethodParameter methodParam, NativeWebRequest webRequest, Object handlerForInitBinderCall)
|
MethodParameter methodParam, NativeWebRequest webRequest, Object handlerForInitBinderCall)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
Class<?> paramType = methodParam.getParameterType();
|
Class<?> paramType = methodParam.getParameterType();
|
||||||
|
if (Map.class.isAssignableFrom(paramType)) {
|
||||||
|
return resolveRequestHeaderMap((Class<? extends Map>) paramType, webRequest);
|
||||||
|
}
|
||||||
if (headerName.length() == 0) {
|
if (headerName.length() == 0) {
|
||||||
headerName = getRequiredParameterName(methodParam);
|
headerName = getRequiredParameterName(methodParam);
|
||||||
}
|
}
|
||||||
|
|
@ -484,6 +490,34 @@ public class HandlerMethodInvoker {
|
||||||
return binder.convertIfNecessary(headerValue, paramType, methodParam);
|
return binder.convertIfNecessary(headerValue, paramType, methodParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Map resolveRequestHeaderMap(Class<? extends Map> mapType, NativeWebRequest webRequest) {
|
||||||
|
if (MultiValueMap.class.isAssignableFrom(mapType)) {
|
||||||
|
MultiValueMap<String, String> result;
|
||||||
|
if (HttpHeaders.class.isAssignableFrom(mapType)) {
|
||||||
|
result = new HttpHeaders();
|
||||||
|
} else {
|
||||||
|
result = new LinkedMultiValueMap<String, String>();
|
||||||
|
}
|
||||||
|
for (Iterator<String> iterator = webRequest.getHeaderNames(); iterator.hasNext();) {
|
||||||
|
String headerName = iterator.next();
|
||||||
|
for (String headerValue : webRequest.getHeaderValues(headerName)) {
|
||||||
|
result.add(headerName, headerValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Map<String, String> result = new LinkedHashMap<String, String>();
|
||||||
|
for (Iterator<String> iterator = webRequest.getHeaderNames(); iterator.hasNext();) {
|
||||||
|
String headerName = iterator.next();
|
||||||
|
String headerValue = webRequest.getHeader(headerName);
|
||||||
|
result.put(headerName, headerValue);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves the given {@link RequestBody @RequestBody} annotation.
|
* Resolves the given {@link RequestBody @RequestBody} annotation.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,10 @@ public class FacesWebRequest extends FacesRequestAttributes implements NativeWeb
|
||||||
return getExternalContext().getRequestHeaderValuesMap().get(headerName);
|
return getExternalContext().getRequestHeaderValuesMap().get(headerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Iterator<String> getHeaderNames() {
|
||||||
|
return getExternalContext().getRequestHeaderMap().keySet().iterator();
|
||||||
|
}
|
||||||
|
|
||||||
public String getParameter(String paramName) {
|
public String getParameter(String paramName) {
|
||||||
return getExternalContext().getRequestParameterMap().get(paramName);
|
return getExternalContext().getRequestParameterMap().get(paramName);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,11 @@ public class ServletWebRequest extends ServletRequestAttributes implements Nativ
|
||||||
return (!ObjectUtils.isEmpty(headerValues) ? headerValues : null);
|
return (!ObjectUtils.isEmpty(headerValues) ? headerValues : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Iterator<String> getHeaderNames() {
|
||||||
|
return CollectionUtils.toIterator(getRequest().getHeaderNames());
|
||||||
|
}
|
||||||
|
|
||||||
public String getParameter(String paramName) {
|
public String getParameter(String paramName) {
|
||||||
return getRequest().getParameter(paramName);
|
return getRequest().getParameter(paramName);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,13 @@ public interface WebRequest extends RequestAttributes {
|
||||||
*/
|
*/
|
||||||
String[] getHeaderValues(String headerName);
|
String[] getHeaderValues(String headerName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a Iterator over request header names.
|
||||||
|
* @see javax.servlet.http.HttpServletRequest#getHeaderNames()
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
Iterator<String> getHeaderNames();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the request parameter of the given name, or <code>null</code> if none.
|
* Return the request parameter of the given name, or <code>null</code> if none.
|
||||||
* <p>Retrieves the first parameter value in case of a multi-value parameter.
|
* <p>Retrieves the first parameter value in case of a multi-value parameter.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue