Revert "WIP"
This reverts commit c09b0f57631905a7b9cca32be5516853e4263ac0.
This commit is contained in:
@@ -152,7 +152,7 @@ import org.springframework.util.StringUtils;
|
||||
* @see org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter
|
||||
* @see org.springframework.util.MultiValueMap
|
||||
*/
|
||||
public class FormHttpMessageConverter implements HttpMessageConverter<Map<String, ?>> {
|
||||
public class FormHttpMessageConverter implements HttpMessageConverter<MultiValueMap<String, ?>> {
|
||||
|
||||
/** The default charset used by the converter. */
|
||||
public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
|
||||
@@ -295,7 +295,7 @@ public class FormHttpMessageConverter implements HttpMessageConverter<Map<String
|
||||
|
||||
@Override
|
||||
public boolean canRead(Class<?> clazz, @Nullable MediaType mediaType) {
|
||||
if (!Map.class.isAssignableFrom(clazz)) {
|
||||
if (!MultiValueMap.class.isAssignableFrom(clazz)) {
|
||||
return false;
|
||||
}
|
||||
if (mediaType == null) {
|
||||
@@ -330,7 +330,7 @@ public class FormHttpMessageConverter implements HttpMessageConverter<Map<String
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, ?> read(@Nullable Class<? extends Map<String, ?>> clazz,
|
||||
public MultiValueMap<String, String> read(@Nullable Class<? extends MultiValueMap<String, ?>> clazz,
|
||||
HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
|
||||
|
||||
MediaType contentType = inputMessage.getHeaders().getContentType();
|
||||
@@ -339,76 +339,41 @@ public class FormHttpMessageConverter implements HttpMessageConverter<Map<String
|
||||
String body = StreamUtils.copyToString(inputMessage.getBody(), charset);
|
||||
|
||||
String[] pairs = StringUtils.tokenizeToStringArray(body, "&");
|
||||
Map<String, String> svResult = null;
|
||||
MultiValueMap<String, String> mvResult = null;
|
||||
if (clazz == null || MultiValueMap.class.isAssignableFrom(clazz)) {
|
||||
mvResult = new LinkedMultiValueMap<>(pairs.length);
|
||||
}
|
||||
else {
|
||||
svResult = CollectionUtils.newLinkedHashMap(pairs.length);
|
||||
}
|
||||
MultiValueMap<String, String> result = new LinkedMultiValueMap<>(pairs.length);
|
||||
for (String pair : pairs) {
|
||||
int idx = pair.indexOf('=');
|
||||
if (idx == -1) {
|
||||
String name = URLDecoder.decode(pair, charset);
|
||||
if (mvResult != null) {
|
||||
mvResult.add(name, null);
|
||||
}
|
||||
else if (svResult != null) {
|
||||
svResult.put(name, null);
|
||||
}
|
||||
result.add(URLDecoder.decode(pair, charset), null);
|
||||
}
|
||||
else {
|
||||
String name = URLDecoder.decode(pair.substring(0, idx), charset);
|
||||
String value = URLDecoder.decode(pair.substring(idx + 1), charset);
|
||||
if (mvResult != null) {
|
||||
mvResult.add(name, value);
|
||||
}
|
||||
else if (svResult != null) {
|
||||
svResult.put(name, value);
|
||||
}
|
||||
result.add(name, value);
|
||||
}
|
||||
}
|
||||
if (mvResult != null) {
|
||||
return mvResult;
|
||||
}
|
||||
else if (svResult != null) {
|
||||
return svResult;
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void write(Map<String, ?> map, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
|
||||
public void write(MultiValueMap<String, ?> map, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
|
||||
throws IOException, HttpMessageNotWritableException {
|
||||
|
||||
if (isMultipart(map, contentType)) {
|
||||
writeMultipart((Map<String, Object>) map, contentType, outputMessage);
|
||||
writeMultipart((MultiValueMap<String, Object>) map, contentType, outputMessage);
|
||||
}
|
||||
else {
|
||||
writeForm((Map<String, Object>) map, contentType, outputMessage);
|
||||
writeForm((MultiValueMap<String, Object>) map, contentType, outputMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean isMultipart(Map<String, ?> map, @Nullable MediaType contentType) {
|
||||
private boolean isMultipart(MultiValueMap<String, ?> map, @Nullable MediaType contentType) {
|
||||
if (contentType != null) {
|
||||
return contentType.getType().equalsIgnoreCase("multipart");
|
||||
}
|
||||
if (map instanceof MultiValueMap<?, ?> mvMap) {
|
||||
for (List<?> values : mvMap.values()) {
|
||||
for (Object value : values) {
|
||||
if (value != null && !(value instanceof String)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (Object value : map.values()) {
|
||||
for (List<?> values : map.values()) {
|
||||
for (Object value : values) {
|
||||
if (value != null && !(value instanceof String)) {
|
||||
return true;
|
||||
}
|
||||
@@ -417,7 +382,7 @@ public class FormHttpMessageConverter implements HttpMessageConverter<Map<String
|
||||
return false;
|
||||
}
|
||||
|
||||
private void writeForm(Map<String, Object> formData, @Nullable MediaType mediaType,
|
||||
private void writeForm(MultiValueMap<String, Object> formData, @Nullable MediaType mediaType,
|
||||
HttpOutputMessage outputMessage) throws IOException {
|
||||
|
||||
mediaType = getFormContentType(mediaType);
|
||||
@@ -465,37 +430,30 @@ public class FormHttpMessageConverter implements HttpMessageConverter<Map<String
|
||||
return contentType;
|
||||
}
|
||||
|
||||
protected String serializeForm(Map<String, Object> formData, Charset charset) {
|
||||
protected String serializeForm(MultiValueMap<String, Object> formData, Charset charset) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
formData.forEach((name, value) -> {
|
||||
formData.forEach((name, values) -> {
|
||||
if (name == null) {
|
||||
Assert.isTrue(value == null || value instanceof List<?> values && values.isEmpty(),
|
||||
() -> "Null name in form data: " + formData);
|
||||
Assert.isTrue(CollectionUtils.isEmpty(values), () -> "Null name in form data: " + formData);
|
||||
return;
|
||||
}
|
||||
if (value instanceof List<?> values) {
|
||||
values.forEach(v -> serializeFormValue(name, value, charset, builder));
|
||||
}
|
||||
else {
|
||||
serializeFormValue(name, value, charset, builder);
|
||||
}
|
||||
values.forEach(value -> {
|
||||
if (builder.length() != 0) {
|
||||
builder.append('&');
|
||||
}
|
||||
builder.append(URLEncoder.encode(name, charset));
|
||||
if (value != null) {
|
||||
builder.append('=');
|
||||
builder.append(URLEncoder.encode(String.valueOf(value), charset));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private static void serializeFormValue(String name, @Nullable Object value, Charset charset, StringBuilder builder) {
|
||||
if (!builder.isEmpty()) {
|
||||
builder.append('&');
|
||||
}
|
||||
builder.append(URLEncoder.encode(name, charset));
|
||||
if (value != null) {
|
||||
builder.append('=');
|
||||
builder.append(URLEncoder.encode(String.valueOf(value), charset));
|
||||
}
|
||||
}
|
||||
|
||||
private void writeMultipart(
|
||||
Map<String, Object> parts, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
|
||||
MultiValueMap<String, Object> parts, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
|
||||
throws IOException {
|
||||
|
||||
// If the supplied content type is null, fall back to multipart/form-data.
|
||||
@@ -542,23 +500,13 @@ public class FormHttpMessageConverter implements HttpMessageConverter<Map<String
|
||||
return (this.multipartCharset != null);
|
||||
}
|
||||
|
||||
private void writeParts(OutputStream os, Map<String, Object> parts, byte[] boundary) throws IOException {
|
||||
for (Map.Entry<String, Object> entry : parts.entrySet()) {
|
||||
private void writeParts(OutputStream os, MultiValueMap<String, Object> parts, byte[] boundary) throws IOException {
|
||||
for (Map.Entry<String, List<Object>> entry : parts.entrySet()) {
|
||||
String name = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
if (value instanceof List<?> values) {
|
||||
for (Object part : values) {
|
||||
if (part != null) {
|
||||
writeBoundary(os, boundary);
|
||||
writePart(name, getHttpEntity(part), os);
|
||||
writeNewLine(os);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (value != null) {
|
||||
for (Object part : entry.getValue()) {
|
||||
if (part != null) {
|
||||
writeBoundary(os, boundary);
|
||||
writePart(name, getHttpEntity(value), os);
|
||||
writePart(name, getHttpEntity(part), os);
|
||||
writeNewLine(os);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -94,7 +94,6 @@ public class FormContentFilter extends OncePerRequestFilter {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
private MultiValueMap<String, String> parseIfNecessary(HttpServletRequest request) throws IOException {
|
||||
if (!shouldParse(request)) {
|
||||
@@ -107,7 +106,7 @@ public class FormContentFilter extends OncePerRequestFilter {
|
||||
return request.getInputStream();
|
||||
}
|
||||
};
|
||||
return (MultiValueMap<String, String>) this.formConverter.read(null, inputMessage);
|
||||
return this.formConverter.read(null, inputMessage);
|
||||
}
|
||||
|
||||
private boolean shouldParse(HttpServletRequest request) {
|
||||
|
||||
Reference in New Issue
Block a user