Fix in MockMultipartHttpServletRequest#getMultipartHeaders
Previously this method returned headers only when a Content-Type part header was present. Now it is guaranteed to return headers (possibly empty) as long as there is a MultipartFile or Part with the given name. Closes gh-26501
This commit is contained in:
parent
7a329eba5b
commit
c52526ad42
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2020 the original author or authors.
|
* Copyright 2002-2021 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,6 +17,7 @@
|
||||||
package org.springframework.mock.web;
|
package org.springframework.mock.web;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
@ -33,6 +34,7 @@ import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.LinkedMultiValueMap;
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
|
import org.springframework.web.multipart.MultipartException;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||||
|
|
||||||
|
@ -155,15 +157,28 @@ public class MockMultipartHttpServletRequest extends MockHttpServletRequest impl
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpHeaders getMultipartHeaders(String paramOrFileName) {
|
public HttpHeaders getMultipartHeaders(String paramOrFileName) {
|
||||||
String contentType = getMultipartContentType(paramOrFileName);
|
MultipartFile file = getFile(paramOrFileName);
|
||||||
if (contentType != null) {
|
if (file != null) {
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
headers.add(HttpHeaders.CONTENT_TYPE, contentType);
|
if (file.getContentType() != null) {
|
||||||
|
headers.add(HttpHeaders.CONTENT_TYPE, file.getContentType());
|
||||||
|
}
|
||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
else {
|
try {
|
||||||
return null;
|
Part part = getPart(paramOrFileName);
|
||||||
|
if (part != null) {
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
for (String headerName : part.getHeaderNames()) {
|
||||||
|
headers.put(headerName, new ArrayList<>(part.getHeaders(headerName)));
|
||||||
|
}
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
catch (Throwable ex) {
|
||||||
|
throw new MultipartException("Could not access multipart servlet request", ex);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2021 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -60,9 +60,10 @@ public interface MultipartHttpServletRequest extends HttpServletRequest, Multipa
|
||||||
HttpHeaders getRequestHeaders();
|
HttpHeaders getRequestHeaders();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the headers associated with the specified part of the multipart request.
|
* Return the headers for the specified part of the multipart request.
|
||||||
* <p>If the underlying implementation supports access to headers, then all headers are returned.
|
* <p>If the underlying implementation supports access to part headers,
|
||||||
* Otherwise, the returned headers will include a 'Content-Type' header at the very least.
|
* then all headers are returned. Otherwise, e.g. for a file upload, the
|
||||||
|
* returned headers may expose a 'Content-Type' if available.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
HttpHeaders getMultipartHeaders(String paramOrFileName);
|
HttpHeaders getMultipartHeaders(String paramOrFileName);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2020 the original author or authors.
|
* Copyright 2002-2021 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,6 +17,7 @@
|
||||||
package org.springframework.web.testfixture.servlet;
|
package org.springframework.web.testfixture.servlet;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
@ -33,6 +34,7 @@ import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.LinkedMultiValueMap;
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
|
import org.springframework.web.multipart.MultipartException;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||||
|
|
||||||
|
@ -155,15 +157,28 @@ public class MockMultipartHttpServletRequest extends MockHttpServletRequest impl
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpHeaders getMultipartHeaders(String paramOrFileName) {
|
public HttpHeaders getMultipartHeaders(String paramOrFileName) {
|
||||||
String contentType = getMultipartContentType(paramOrFileName);
|
MultipartFile file = getFile(paramOrFileName);
|
||||||
if (contentType != null) {
|
if (file != null) {
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
headers.add(HttpHeaders.CONTENT_TYPE, contentType);
|
if (file.getContentType() != null) {
|
||||||
|
headers.add(HttpHeaders.CONTENT_TYPE, file.getContentType());
|
||||||
|
}
|
||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
else {
|
try {
|
||||||
return null;
|
Part part = getPart(paramOrFileName);
|
||||||
|
if (part != null) {
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
for (String headerName : part.getHeaderNames()) {
|
||||||
|
headers.put(headerName, new ArrayList<>(part.getHeaders(headerName)));
|
||||||
|
}
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
catch (Throwable ex) {
|
||||||
|
throw new MultipartException("Could not access multipart servlet request", ex);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2019 the original author or authors.
|
* Copyright 2002-2021 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -36,6 +36,7 @@ import org.springframework.core.annotation.SynthesizingMethodParameter;
|
||||||
import org.springframework.http.HttpInputMessage;
|
import org.springframework.http.HttpInputMessage;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.converter.HttpMessageConverter;
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
|
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.ReflectionUtils;
|
import org.springframework.util.ReflectionUtils;
|
||||||
import org.springframework.validation.BindingResult;
|
import org.springframework.validation.BindingResult;
|
||||||
|
@ -51,6 +52,7 @@ import org.springframework.web.method.support.ModelAndViewContainer;
|
||||||
import org.springframework.web.multipart.MultipartException;
|
import org.springframework.web.multipart.MultipartException;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import org.springframework.web.multipart.support.MissingServletRequestPartException;
|
import org.springframework.web.multipart.support.MissingServletRequestPartException;
|
||||||
|
import org.springframework.web.testfixture.method.ResolvableMethod;
|
||||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||||
import org.springframework.web.testfixture.servlet.MockHttpServletResponse;
|
import org.springframework.web.testfixture.servlet.MockHttpServletResponse;
|
||||||
import org.springframework.web.testfixture.servlet.MockMultipartFile;
|
import org.springframework.web.testfixture.servlet.MockMultipartFile;
|
||||||
|
@ -311,6 +313,22 @@ public class RequestPartMethodArgumentResolverTests {
|
||||||
testResolveArgument(new SimpleBean("foo"), paramValidRequestPart);
|
testResolveArgument(new SimpleBean("foo"), paramValidRequestPart);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // gh-26501
|
||||||
|
public void resolveRequestPartWithoutContentType() throws Exception {
|
||||||
|
MockMultipartHttpServletRequest servletRequest = new MockMultipartHttpServletRequest();
|
||||||
|
servletRequest.addPart(new MockPart("requestPartString", "part value".getBytes(StandardCharsets.UTF_8)));
|
||||||
|
ServletWebRequest webRequest = new ServletWebRequest(servletRequest, new MockHttpServletResponse());
|
||||||
|
|
||||||
|
List<HttpMessageConverter<?>> converters = Collections.singletonList(new StringHttpMessageConverter());
|
||||||
|
RequestPartMethodArgumentResolver resolver = new RequestPartMethodArgumentResolver(converters);
|
||||||
|
MethodParameter parameter = ResolvableMethod.on(getClass()).named("handle").build().arg(String.class);
|
||||||
|
|
||||||
|
Object actualValue = resolver.resolveArgument(
|
||||||
|
parameter, new ModelAndViewContainer(), webRequest, new ValidatingBinderFactory());
|
||||||
|
|
||||||
|
assertThat(actualValue).isEqualTo("part value");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isMultipartRequest() throws Exception {
|
public void isMultipartRequest() throws Exception {
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||||
|
@ -606,7 +624,8 @@ public class RequestPartMethodArgumentResolverTests {
|
||||||
@RequestPart("requestPart") Optional<List<MultipartFile>> optionalMultipartFileList,
|
@RequestPart("requestPart") Optional<List<MultipartFile>> optionalMultipartFileList,
|
||||||
Optional<Part> optionalPart,
|
Optional<Part> optionalPart,
|
||||||
@RequestPart("requestPart") Optional<List<Part>> optionalPartList,
|
@RequestPart("requestPart") Optional<List<Part>> optionalPartList,
|
||||||
@RequestPart("requestPart") Optional<SimpleBean> optionalRequestPart) {
|
@RequestPart("requestPart") Optional<SimpleBean> optionalRequestPart,
|
||||||
|
@RequestPart("requestPartString") String requestPartString) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue