parent
6e640c806f
commit
a40cc8bbe0
|
@ -48,18 +48,6 @@ public final class ContentDisposition {
|
||||||
private static final String INVALID_HEADER_FIELD_PARAMETER_FORMAT =
|
private static final String INVALID_HEADER_FIELD_PARAMETER_FORMAT =
|
||||||
"Invalid header field parameter format (as defined in RFC 5987)";
|
"Invalid header field parameter format (as defined in RFC 5987)";
|
||||||
|
|
||||||
/**
|
|
||||||
* The {@literal attachment} content-disposition type.
|
|
||||||
*/
|
|
||||||
private static final String ATTACHMENT = "attachment";
|
|
||||||
/**
|
|
||||||
* The {@literal form-data} content-disposition type.
|
|
||||||
*/
|
|
||||||
private static final String FORM_DATA = "form-data";
|
|
||||||
/**
|
|
||||||
* The {@literal inline} content-disposition type.
|
|
||||||
*/
|
|
||||||
private static final String INLINE = "inline";
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private final String type;
|
private final String type;
|
||||||
|
@ -105,8 +93,34 @@ public final class ContentDisposition {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the disposition type, like for example {@literal inline}, {@literal attachment},
|
* Return whether the {@link #getType() type} is {@literal "attachment"}.
|
||||||
* {@literal form-data}, or {@code null} if not defined.
|
* @since 5.3
|
||||||
|
*/
|
||||||
|
public boolean isAttachment() {
|
||||||
|
return (this.type != null && this.type.equalsIgnoreCase("attachment"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether the {@link #getType() type} is {@literal "form-data"}.
|
||||||
|
* @since 5.3
|
||||||
|
*/
|
||||||
|
public boolean isFormData() {
|
||||||
|
return (this.type != null && this.type.equalsIgnoreCase("form-data"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether the {@link #getType() type} is {@literal "inline"}.
|
||||||
|
* @since 5.3
|
||||||
|
*/
|
||||||
|
public boolean isInline() {
|
||||||
|
return (this.type != null && this.type.equalsIgnoreCase("inline"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the disposition type.
|
||||||
|
* @see #isAttachment()
|
||||||
|
* @see #isFormData()
|
||||||
|
* @see #isInline()
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public String getType() {
|
public String getType() {
|
||||||
|
@ -186,30 +200,6 @@ public final class ContentDisposition {
|
||||||
return this.readDate;
|
return this.readDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return whether the {@link #getType() type} is {@literal attachment}.
|
|
||||||
* @since 5.3
|
|
||||||
*/
|
|
||||||
public boolean isAttachment() {
|
|
||||||
return ATTACHMENT.equals(this.type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return whether the {@link #getType() type} is {@literal form-data}.
|
|
||||||
* @since 5.3
|
|
||||||
*/
|
|
||||||
public boolean isFormData() {
|
|
||||||
return FORM_DATA.equals(this.type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return whether the {@link #getType() type} is {@literal inline}.
|
|
||||||
* @since 5.3
|
|
||||||
*/
|
|
||||||
public boolean isInline() {
|
|
||||||
return INLINE.equals(this.type);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(@Nullable Object other) {
|
public boolean equals(@Nullable Object other) {
|
||||||
if (this == other) {
|
if (this == other) {
|
||||||
|
@ -289,6 +279,30 @@ public final class ContentDisposition {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a builder for a {@code ContentDisposition} of type {@literal "attachment"}.
|
||||||
|
* @since 5.3
|
||||||
|
*/
|
||||||
|
public static Builder attachment() {
|
||||||
|
return builder("attachment");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a builder for a {@code ContentDisposition} of type {@literal "form-data"}.
|
||||||
|
* @since 5.3
|
||||||
|
*/
|
||||||
|
public static Builder formData() {
|
||||||
|
return builder("form-data");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a builder for a {@code ContentDisposition} of type {@literal "inline"}.
|
||||||
|
* @since 5.3
|
||||||
|
*/
|
||||||
|
public static Builder inline() {
|
||||||
|
return builder("inline");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a builder for a {@code ContentDisposition}.
|
* Return a builder for a {@code ContentDisposition}.
|
||||||
* @param type the disposition type like for example {@literal inline},
|
* @param type the disposition type like for example {@literal inline},
|
||||||
|
@ -299,36 +313,6 @@ public final class ContentDisposition {
|
||||||
return new BuilderImpl(type);
|
return new BuilderImpl(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a builder for a {@code ContentDisposition} with
|
|
||||||
* the {@link #ATTACHMENT attachment} type.
|
|
||||||
* @return the builder
|
|
||||||
* @since 5.3
|
|
||||||
*/
|
|
||||||
public static Builder attachment() {
|
|
||||||
return builder(ATTACHMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a builder for a {@code ContentDisposition} with
|
|
||||||
* the {@link #FORM_DATA form-data} type.
|
|
||||||
* @return the builder
|
|
||||||
* @since 5.3
|
|
||||||
*/
|
|
||||||
public static Builder formData() {
|
|
||||||
return builder(FORM_DATA);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a builder for a {@code ContentDisposition} with
|
|
||||||
* the {@link #INLINE inline} type.
|
|
||||||
* @return the builder
|
|
||||||
* @since 5.3
|
|
||||||
*/
|
|
||||||
public static Builder inline() {
|
|
||||||
return builder(INLINE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an empty content disposition.
|
* Return an empty content disposition.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -25,8 +25,6 @@ import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||||
import static org.springframework.http.ContentDisposition.attachment;
|
|
||||||
import static org.springframework.http.ContentDisposition.formData;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for {@link ContentDisposition}
|
* Unit tests for {@link ContentDisposition}
|
||||||
|
@ -42,7 +40,7 @@ class ContentDispositionTests {
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
void parse() {
|
void parse() {
|
||||||
assertThat(parse("form-data; name=\"foo\"; filename=\"foo.txt\"; size=123"))
|
assertThat(parse("form-data; name=\"foo\"; filename=\"foo.txt\"; size=123"))
|
||||||
.isEqualTo(formData()
|
.isEqualTo(ContentDisposition.formData()
|
||||||
.name("foo")
|
.name("foo")
|
||||||
.filename("foo.txt")
|
.filename("foo.txt")
|
||||||
.size(123L)
|
.size(123L)
|
||||||
|
@ -52,7 +50,7 @@ class ContentDispositionTests {
|
||||||
@Test
|
@Test
|
||||||
void parseFilenameUnquoted() {
|
void parseFilenameUnquoted() {
|
||||||
assertThat(parse("form-data; filename=unquoted"))
|
assertThat(parse("form-data; filename=unquoted"))
|
||||||
.isEqualTo(formData()
|
.isEqualTo(ContentDisposition.formData()
|
||||||
.filename("unquoted")
|
.filename("unquoted")
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
@ -60,7 +58,7 @@ class ContentDispositionTests {
|
||||||
@Test // SPR-16091
|
@Test // SPR-16091
|
||||||
void parseFilenameWithSemicolon() {
|
void parseFilenameWithSemicolon() {
|
||||||
assertThat(parse("attachment; filename=\"filename with ; semicolon.txt\""))
|
assertThat(parse("attachment; filename=\"filename with ; semicolon.txt\""))
|
||||||
.isEqualTo(attachment()
|
.isEqualTo(ContentDisposition.attachment()
|
||||||
.filename("filename with ; semicolon.txt")
|
.filename("filename with ; semicolon.txt")
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
@ -68,7 +66,7 @@ class ContentDispositionTests {
|
||||||
@Test
|
@Test
|
||||||
void parseEncodedFilename() {
|
void parseEncodedFilename() {
|
||||||
assertThat(parse("form-data; name=\"name\"; filename*=UTF-8''%E4%B8%AD%E6%96%87.txt"))
|
assertThat(parse("form-data; name=\"name\"; filename*=UTF-8''%E4%B8%AD%E6%96%87.txt"))
|
||||||
.isEqualTo(formData()
|
.isEqualTo(ContentDisposition.formData()
|
||||||
.name("name")
|
.name("name")
|
||||||
.filename("中文.txt", StandardCharsets.UTF_8)
|
.filename("中文.txt", StandardCharsets.UTF_8)
|
||||||
.build());
|
.build());
|
||||||
|
@ -77,7 +75,7 @@ class ContentDispositionTests {
|
||||||
@Test // gh-24112
|
@Test // gh-24112
|
||||||
void parseEncodedFilenameWithPaddedCharset() {
|
void parseEncodedFilenameWithPaddedCharset() {
|
||||||
assertThat(parse("attachment; filename*= UTF-8''some-file.zip"))
|
assertThat(parse("attachment; filename*= UTF-8''some-file.zip"))
|
||||||
.isEqualTo(attachment()
|
.isEqualTo(ContentDisposition.attachment()
|
||||||
.filename("some-file.zip", StandardCharsets.UTF_8)
|
.filename("some-file.zip", StandardCharsets.UTF_8)
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
@ -85,7 +83,7 @@ class ContentDispositionTests {
|
||||||
@Test
|
@Test
|
||||||
void parseEncodedFilenameWithoutCharset() {
|
void parseEncodedFilenameWithoutCharset() {
|
||||||
assertThat(parse("form-data; name=\"name\"; filename*=test.txt"))
|
assertThat(parse("form-data; name=\"name\"; filename*=test.txt"))
|
||||||
.isEqualTo(formData()
|
.isEqualTo(ContentDisposition.formData()
|
||||||
.name("name")
|
.name("name")
|
||||||
.filename("test.txt")
|
.filename("test.txt")
|
||||||
.build());
|
.build());
|
||||||
|
@ -112,7 +110,7 @@ class ContentDispositionTests {
|
||||||
BiConsumer<String, String> tester = (description, filename) ->
|
BiConsumer<String, String> tester = (description, filename) ->
|
||||||
assertThat(parse("form-data; name=\"file\"; filename=\"" + filename + "\"; size=123"))
|
assertThat(parse("form-data; name=\"file\"; filename=\"" + filename + "\"; size=123"))
|
||||||
.as(description)
|
.as(description)
|
||||||
.isEqualTo(formData().name("file").filename(filename).size(123L).build());
|
.isEqualTo(ContentDisposition.formData().name("file").filename(filename).size(123L).build());
|
||||||
|
|
||||||
tester.accept("Escaped quotes should be ignored",
|
tester.accept("Escaped quotes should be ignored",
|
||||||
"\\\"The Twilight Zone\\\".txt");
|
"\\\"The Twilight Zone\\\".txt");
|
||||||
|
@ -131,7 +129,7 @@ class ContentDispositionTests {
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
void parseWithExtraSemicolons() {
|
void parseWithExtraSemicolons() {
|
||||||
assertThat(parse("form-data; name=\"foo\";; ; filename=\"foo.txt\"; size=123"))
|
assertThat(parse("form-data; name=\"foo\";; ; filename=\"foo.txt\"; size=123"))
|
||||||
.isEqualTo(formData()
|
.isEqualTo(ContentDisposition.formData()
|
||||||
.name("foo")
|
.name("foo")
|
||||||
.filename("foo.txt")
|
.filename("foo.txt")
|
||||||
.size(123L)
|
.size(123L)
|
||||||
|
@ -150,7 +148,7 @@ class ContentDispositionTests {
|
||||||
"creation-date=\"" + creationTime.format(formatter) + "\"; " +
|
"creation-date=\"" + creationTime.format(formatter) + "\"; " +
|
||||||
"modification-date=\"" + modificationTime.format(formatter) + "\"; " +
|
"modification-date=\"" + modificationTime.format(formatter) + "\"; " +
|
||||||
"read-date=\"" + readTime.format(formatter) + "\"")).isEqualTo(
|
"read-date=\"" + readTime.format(formatter) + "\"")).isEqualTo(
|
||||||
attachment()
|
ContentDisposition.attachment()
|
||||||
.creationDate(creationTime)
|
.creationDate(creationTime)
|
||||||
.modificationDate(modificationTime)
|
.modificationDate(modificationTime)
|
||||||
.readDate(readTime)
|
.readDate(readTime)
|
||||||
|
@ -167,7 +165,7 @@ class ContentDispositionTests {
|
||||||
"creation-date=\"-1\"; " +
|
"creation-date=\"-1\"; " +
|
||||||
"modification-date=\"-1\"; " +
|
"modification-date=\"-1\"; " +
|
||||||
"read-date=\"" + readTime.format(formatter) + "\"")).isEqualTo(
|
"read-date=\"" + readTime.format(formatter) + "\"")).isEqualTo(
|
||||||
attachment()
|
ContentDisposition.attachment()
|
||||||
.readDate(readTime)
|
.readDate(readTime)
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
@ -196,7 +194,7 @@ class ContentDispositionTests {
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
void format() {
|
void format() {
|
||||||
assertThat(
|
assertThat(
|
||||||
formData()
|
ContentDisposition.formData()
|
||||||
.name("foo")
|
.name("foo")
|
||||||
.filename("foo.txt")
|
.filename("foo.txt")
|
||||||
.size(123L)
|
.size(123L)
|
||||||
|
@ -207,7 +205,7 @@ class ContentDispositionTests {
|
||||||
@Test
|
@Test
|
||||||
void formatWithEncodedFilename() {
|
void formatWithEncodedFilename() {
|
||||||
assertThat(
|
assertThat(
|
||||||
formData()
|
ContentDisposition.formData()
|
||||||
.name("name")
|
.name("name")
|
||||||
.filename("中文.txt", StandardCharsets.UTF_8)
|
.filename("中文.txt", StandardCharsets.UTF_8)
|
||||||
.build().toString())
|
.build().toString())
|
||||||
|
@ -217,7 +215,7 @@ class ContentDispositionTests {
|
||||||
@Test
|
@Test
|
||||||
void formatWithEncodedFilenameUsingUsAscii() {
|
void formatWithEncodedFilenameUsingUsAscii() {
|
||||||
assertThat(
|
assertThat(
|
||||||
formData()
|
ContentDisposition.formData()
|
||||||
.name("name")
|
.name("name")
|
||||||
.filename("test.txt", StandardCharsets.US_ASCII)
|
.filename("test.txt", StandardCharsets.US_ASCII)
|
||||||
.build()
|
.build()
|
||||||
|
@ -230,10 +228,10 @@ class ContentDispositionTests {
|
||||||
|
|
||||||
BiConsumer<String, String> tester = (input, output) -> {
|
BiConsumer<String, String> tester = (input, output) -> {
|
||||||
|
|
||||||
assertThat(formData().filename(input).build().toString())
|
assertThat(ContentDisposition.formData().filename(input).build().toString())
|
||||||
.isEqualTo("form-data; filename=\"" + output + "\"");
|
.isEqualTo("form-data; filename=\"" + output + "\"");
|
||||||
|
|
||||||
assertThat(formData().filename(input, StandardCharsets.US_ASCII).build().toString())
|
assertThat(ContentDisposition.formData().filename(input, StandardCharsets.US_ASCII).build().toString())
|
||||||
.isEqualTo("form-data; filename=\"" + output + "\"");
|
.isEqualTo("form-data; filename=\"" + output + "\"");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -263,7 +261,7 @@ class ContentDispositionTests {
|
||||||
@Test
|
@Test
|
||||||
void formatWithEncodedFilenameUsingInvalidCharset() {
|
void formatWithEncodedFilenameUsingInvalidCharset() {
|
||||||
assertThatIllegalArgumentException().isThrownBy(() ->
|
assertThatIllegalArgumentException().isThrownBy(() ->
|
||||||
formData()
|
ContentDisposition.formData()
|
||||||
.name("name")
|
.name("name")
|
||||||
.filename("test.txt", StandardCharsets.UTF_16)
|
.filename("test.txt", StandardCharsets.UTF_16)
|
||||||
.build()
|
.build()
|
||||||
|
|
Loading…
Reference in New Issue