Polishing
This commit is contained in:
@@ -233,9 +233,9 @@ public final class ContentDisposition {
|
||||
result = 31 * result + ObjectUtils.nullSafeHashCode(this.filename);
|
||||
result = 31 * result + ObjectUtils.nullSafeHashCode(this.charset);
|
||||
result = 31 * result + ObjectUtils.nullSafeHashCode(this.size);
|
||||
result = 31 * result + (this.creationDate != null ? this.creationDate.hashCode() : 0);
|
||||
result = 31 * result + (this.modificationDate != null ? this.modificationDate.hashCode() : 0);
|
||||
result = 31 * result + (this.readDate != null ? this.readDate.hashCode() : 0);
|
||||
result = 31 * result + ObjectUtils.nullSafeHashCode(this.creationDate);
|
||||
result = 31 * result + ObjectUtils.nullSafeHashCode(this.modificationDate);
|
||||
result = 31 * result + ObjectUtils.nullSafeHashCode(this.readDate);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -360,7 +360,7 @@ public final class ContentDisposition {
|
||||
if (idx1 != -1 && idx2 != -1) {
|
||||
charset = Charset.forName(value.substring(0, idx1).trim());
|
||||
Assert.isTrue(UTF_8.equals(charset) || ISO_8859_1.equals(charset),
|
||||
"Charset should be UTF-8 or ISO-8859-1");
|
||||
"Charset must be UTF-8 or ISO-8859-1");
|
||||
filename = decodeFilename(value.substring(idx2 + 1), charset);
|
||||
}
|
||||
else {
|
||||
@@ -532,10 +532,11 @@ public final class ContentDisposition {
|
||||
* @see <a href="https://tools.ietf.org/html/rfc5987">RFC 5987</a>
|
||||
*/
|
||||
private static String encodeFilename(String input, Charset charset) {
|
||||
Assert.notNull(input, "'input' is required");
|
||||
Assert.notNull(charset, "'charset' is required");
|
||||
Assert.notNull(input, "'input' must not be null");
|
||||
Assert.notNull(charset, "'charset' must not be null");
|
||||
Assert.isTrue(!StandardCharsets.US_ASCII.equals(charset), "ASCII does not require encoding");
|
||||
Assert.isTrue(UTF_8.equals(charset) || ISO_8859_1.equals(charset), "Only UTF-8 and ISO-8859-1 are supported");
|
||||
|
||||
byte[] source = input.getBytes(charset);
|
||||
int len = source.length;
|
||||
StringBuilder sb = new StringBuilder(len << 1);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -65,12 +65,12 @@ public class JettyHttpHandlerAdapter extends ServletHttpHandlerAdapter {
|
||||
protected ServletServerHttpRequest createRequest(HttpServletRequest request, AsyncContext context)
|
||||
throws IOException, URISyntaxException {
|
||||
|
||||
// TODO: need to compile against Jetty 10 to use HttpFields (class->interface)
|
||||
if (jetty10Present) {
|
||||
// No HttpFields optimization on Jetty 10 due to binary incompatibility
|
||||
return super.createRequest(request, context);
|
||||
}
|
||||
|
||||
Assert.notNull(getServletPath(), "Servlet path is not initialized");
|
||||
Assert.state(getServletPath() != null, "Servlet path is not initialized");
|
||||
return new JettyServerHttpRequest(
|
||||
request, context, getServletPath(), getDataBufferFactory(), getBufferSize());
|
||||
}
|
||||
@@ -79,15 +79,14 @@ public class JettyHttpHandlerAdapter extends ServletHttpHandlerAdapter {
|
||||
protected ServletServerHttpResponse createResponse(HttpServletResponse response,
|
||||
AsyncContext context, ServletServerHttpRequest request) throws IOException {
|
||||
|
||||
// TODO: need to compile against Jetty 10 to use HttpFields (class->interface)
|
||||
if (jetty10Present) {
|
||||
// No HttpFields optimization on Jetty 10 due to binary incompatibility
|
||||
return new BaseJettyServerHttpResponse(
|
||||
response, context, getDataBufferFactory(), getBufferSize(), request);
|
||||
}
|
||||
else {
|
||||
return new JettyServerHttpResponse(
|
||||
response, context, getDataBufferFactory(), getBufferSize(), request);
|
||||
}
|
||||
|
||||
return new JettyServerHttpResponse(
|
||||
response, context, getDataBufferFactory(), getBufferSize(), request);
|
||||
}
|
||||
|
||||
|
||||
@@ -120,8 +119,6 @@ public class JettyHttpHandlerAdapter extends ServletHttpHandlerAdapter {
|
||||
"] to org.eclipse.jetty.server.Request");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -170,7 +170,7 @@ public class ServletHttpHandlerAdapter implements Servlet {
|
||||
AsyncListener requestListener;
|
||||
String logPrefix;
|
||||
try {
|
||||
httpRequest = createRequest(((HttpServletRequest) request), asyncContext);
|
||||
httpRequest = createRequest((HttpServletRequest) request, asyncContext);
|
||||
requestListener = httpRequest.getAsyncListener();
|
||||
logPrefix = httpRequest.getLogPrefix();
|
||||
}
|
||||
@@ -183,8 +183,10 @@ public class ServletHttpHandlerAdapter implements Servlet {
|
||||
return;
|
||||
}
|
||||
|
||||
ServerHttpResponse httpResponse = createResponse(((HttpServletResponse) response), asyncContext, httpRequest);
|
||||
AsyncListener responseListener = ((ServletServerHttpResponse) httpResponse).getAsyncListener();
|
||||
ServletServerHttpResponse wrappedResponse =
|
||||
createResponse((HttpServletResponse) response, asyncContext, httpRequest);
|
||||
ServerHttpResponse httpResponse = wrappedResponse;
|
||||
AsyncListener responseListener = wrappedResponse.getAsyncListener();
|
||||
if (httpRequest.getMethod() == HttpMethod.HEAD) {
|
||||
httpResponse = new HttpHeadResponseDecorator(httpResponse);
|
||||
}
|
||||
@@ -201,7 +203,7 @@ public class ServletHttpHandlerAdapter implements Servlet {
|
||||
protected ServletServerHttpRequest createRequest(HttpServletRequest request, AsyncContext context)
|
||||
throws IOException, URISyntaxException {
|
||||
|
||||
Assert.notNull(this.servletPath, "Servlet path is not initialized");
|
||||
Assert.state(this.servletPath != null, "Servlet path is not initialized");
|
||||
return new ServletServerHttpRequest(
|
||||
request, context, this.servletPath, getDataBufferFactory(), getBufferSize());
|
||||
}
|
||||
@@ -264,9 +266,7 @@ public class ServletHttpHandlerAdapter implements Servlet {
|
||||
|
||||
private final String logPrefix;
|
||||
|
||||
|
||||
public HttpHandlerAsyncListener(
|
||||
AsyncListener requestAsyncListener, AsyncListener responseAsyncListener,
|
||||
public HttpHandlerAsyncListener(AsyncListener requestAsyncListener, AsyncListener responseAsyncListener,
|
||||
Runnable handlerDisposeTask, AtomicBoolean completionFlag, String logPrefix) {
|
||||
|
||||
this.requestAsyncListener = requestAsyncListener;
|
||||
@@ -276,7 +276,6 @@ public class ServletHttpHandlerAdapter implements Servlet {
|
||||
this.logPrefix = logPrefix;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onTimeout(AsyncEvent event) {
|
||||
// Should never happen since we call asyncContext.setTimeout(-1)
|
||||
@@ -362,9 +361,7 @@ public class ServletHttpHandlerAdapter implements Servlet {
|
||||
@Nullable
|
||||
private volatile Subscription subscription;
|
||||
|
||||
public HandlerResultSubscriber(
|
||||
AsyncContext asyncContext, AtomicBoolean completionFlag, String logPrefix) {
|
||||
|
||||
public HandlerResultSubscriber(AsyncContext asyncContext, AtomicBoolean completionFlag, String logPrefix) {
|
||||
this.asyncContext = asyncContext;
|
||||
this.completionFlag = completionFlag;
|
||||
this.logPrefix = logPrefix;
|
||||
|
||||
@@ -58,7 +58,6 @@ import org.springframework.util.ReflectionUtils;
|
||||
*/
|
||||
public class TomcatHttpHandlerAdapter extends ServletHttpHandlerAdapter {
|
||||
|
||||
|
||||
public TomcatHttpHandlerAdapter(HttpHandler httpHandler) {
|
||||
super(httpHandler);
|
||||
}
|
||||
@@ -68,7 +67,7 @@ public class TomcatHttpHandlerAdapter extends ServletHttpHandlerAdapter {
|
||||
protected ServletServerHttpRequest createRequest(HttpServletRequest request, AsyncContext asyncContext)
|
||||
throws IOException, URISyntaxException {
|
||||
|
||||
Assert.notNull(getServletPath(), "Servlet path is not initialized");
|
||||
Assert.state(getServletPath() != null, "Servlet path is not initialized");
|
||||
return new TomcatServerHttpRequest(
|
||||
request, asyncContext, getServletPath(), getDataBufferFactory(), getBufferSize());
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -25,20 +25,22 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.springframework.http.ContentDisposition.parse;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ContentDisposition}
|
||||
* Unit tests for {@link ContentDisposition}.
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
class ContentDispositionTests {
|
||||
|
||||
private static DateTimeFormatter formatter = DateTimeFormatter.RFC_1123_DATE_TIME;
|
||||
private static final DateTimeFormatter formatter = DateTimeFormatter.RFC_1123_DATE_TIME;
|
||||
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
void parse() {
|
||||
@Test
|
||||
void parseFilenameQuoted() {
|
||||
assertThat(parse("form-data; name=\"foo\"; filename=\"foo.txt\"; size=123"))
|
||||
.isEqualTo(ContentDisposition.formData()
|
||||
.name("foo")
|
||||
@@ -72,7 +74,7 @@ class ContentDispositionTests {
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test // gh-24112
|
||||
@Test // gh-24112
|
||||
void parseEncodedFilenameWithPaddedCharset() {
|
||||
assertThat(parse("attachment; filename*= UTF-8''some-file.zip"))
|
||||
.isEqualTo(ContentDisposition.attachment()
|
||||
@@ -80,13 +82,13 @@ class ContentDispositionTests {
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test // gh-26463
|
||||
@Test // gh-26463
|
||||
void parseBase64EncodedFilename() {
|
||||
String input = "attachment; filename=\"=?UTF-8?B?5pel5pys6KqeLmNzdg==?=\"";
|
||||
assertThat(parse(input).getFilename()).isEqualTo("日本語.csv");
|
||||
}
|
||||
|
||||
@Test // gh-26463
|
||||
@Test // gh-26463
|
||||
void parseBase64EncodedShiftJISFilename() {
|
||||
String input = "attachment; filename=\"=?SHIFT_JIS?B?k/qWe4zqLmNzdg==?=\"";
|
||||
assertThat(parse(input).getFilename()).isEqualTo("日本語.csv");
|
||||
@@ -116,7 +118,7 @@ class ContentDispositionTests {
|
||||
.isThrownBy(() -> parse("form-data; name=\"name\"; filename*=UTF-8''%A.txt"));
|
||||
}
|
||||
|
||||
@Test // gh-23077
|
||||
@Test // gh-23077
|
||||
@SuppressWarnings("deprecation")
|
||||
void parseWithEscapedQuote() {
|
||||
BiConsumer<String, String> tester = (description, filename) ->
|
||||
@@ -137,8 +139,8 @@ class ContentDispositionTests {
|
||||
"The Twilight Zone \\\\\\\\");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
void parseWithExtraSemicolons() {
|
||||
assertThat(parse("form-data; name=\"foo\";; ; filename=\"foo.txt\"; size=123"))
|
||||
.isEqualTo(ContentDisposition.formData()
|
||||
@@ -148,8 +150,8 @@ class ContentDispositionTests {
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
void parseDates() {
|
||||
ZonedDateTime creationTime = ZonedDateTime.parse("Mon, 12 Feb 2007 10:15:30 -0500", formatter);
|
||||
ZonedDateTime modificationTime = ZonedDateTime.parse("Tue, 13 Feb 2007 10:15:30 -0500", formatter);
|
||||
@@ -167,8 +169,8 @@ class ContentDispositionTests {
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
void parseIgnoresInvalidDates() {
|
||||
ZonedDateTime readTime = ZonedDateTime.parse("Wed, 14 Feb 2007 10:15:30 -0500", formatter);
|
||||
|
||||
@@ -197,13 +199,8 @@ class ContentDispositionTests {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> parse("foo;bar"));
|
||||
}
|
||||
|
||||
private static ContentDisposition parse(String input) {
|
||||
return ContentDisposition.parse(input);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
void format() {
|
||||
assertThat(
|
||||
ContentDisposition.formData()
|
||||
@@ -235,14 +232,11 @@ class ContentDispositionTests {
|
||||
.isEqualTo("form-data; name=\"name\"; filename=\"test.txt\"");
|
||||
}
|
||||
|
||||
@Test // gh-24220
|
||||
@Test // gh-24220
|
||||
void formatWithFilenameWithQuotes() {
|
||||
|
||||
BiConsumer<String, String> tester = (input, output) -> {
|
||||
|
||||
assertThat(ContentDisposition.formData().filename(input).build().toString())
|
||||
.isEqualTo("form-data; filename=\"" + output + "\"");
|
||||
|
||||
assertThat(ContentDisposition.formData().filename(input, StandardCharsets.US_ASCII).build().toString())
|
||||
.isEqualTo("form-data; filename=\"" + output + "\"");
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user