Tolerate invalid mimetype in Reactory Netty compression predicate

Fixes gh-18018
pull/18464/head
Andy Wilkinson 5 years ago
parent 6ca92418b5
commit 3d23277b8f

@ -28,6 +28,7 @@ import reactor.netty.http.server.HttpServerRequest;
import reactor.netty.http.server.HttpServerResponse; import reactor.netty.http.server.HttpServerResponse;
import org.springframework.boot.web.server.Compression; import org.springframework.boot.web.server.Compression;
import org.springframework.util.InvalidMimeTypeException;
import org.springframework.util.MimeType; import org.springframework.util.MimeType;
import org.springframework.util.MimeTypeUtils; import org.springframework.util.MimeTypeUtils;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
@ -73,8 +74,13 @@ final class CompressionCustomizer implements NettyServerCustomizer {
if (StringUtils.isEmpty(contentType)) { if (StringUtils.isEmpty(contentType)) {
return false; return false;
} }
MimeType contentMimeType = MimeTypeUtils.parseMimeType(contentType); try {
return mimeTypes.stream().anyMatch((candidate) -> candidate.isCompatibleWith(contentMimeType)); MimeType contentMimeType = MimeTypeUtils.parseMimeType(contentType);
return mimeTypes.stream().anyMatch((candidate) -> candidate.isCompatibleWith(contentMimeType));
}
catch (InvalidMimeTypeException ex) {
return false;
}
}; };
} }

@ -16,6 +16,7 @@
package org.springframework.boot.web.embedded.netty; package org.springframework.boot.web.embedded.netty;
import java.time.Duration;
import java.util.Arrays; import java.util.Arrays;
import org.junit.Test; import org.junit.Test;
@ -24,7 +25,10 @@ import reactor.netty.http.server.HttpServer;
import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactory; import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactory;
import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactoryTests; import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactoryTests;
import org.springframework.boot.web.server.Compression;
import org.springframework.boot.web.server.PortInUseException; import org.springframework.boot.web.server.PortInUseException;
import org.springframework.http.ResponseEntity;
import org.springframework.web.reactive.function.client.WebClient;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@ -83,4 +87,15 @@ public class NettyReactiveWebServerFactoryTests extends AbstractReactiveWebServe
assertForwardHeaderIsUsed(factory); assertForwardHeaderIsUsed(factory);
} }
@Test
public void noCompressionForResponseWithInvalidContentType() {
Compression compression = new Compression();
compression.setEnabled(true);
compression.setMimeTypes(new String[] { "application/json" });
WebClient client = prepareCompressionTest(compression, "test~plain");
ResponseEntity<Void> response = client.get().exchange().flatMap((res) -> res.toEntity(Void.class))
.block(Duration.ofSeconds(30));
assertResponseIsNotCompressed(response);
}
} }

@ -53,6 +53,7 @@ import org.springframework.boot.web.server.WebServer;
import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory; import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DefaultDataBufferFactory; import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@ -273,6 +274,7 @@ public abstract class AbstractReactiveWebServerFactoryTests {
@Test @Test
public void noCompressionForMimeType() { public void noCompressionForMimeType() {
Compression compression = new Compression(); Compression compression = new Compression();
compression.setEnabled(true);
compression.setMimeTypes(new String[] { "application/json" }); compression.setMimeTypes(new String[] { "application/json" });
WebClient client = prepareCompressionTest(compression); WebClient client = prepareCompressionTest(compression);
ResponseEntity<Void> response = client.get().exchange().flatMap((res) -> res.toEntity(Void.class)) ResponseEntity<Void> response = client.get().exchange().flatMap((res) -> res.toEntity(Void.class))
@ -305,9 +307,13 @@ public abstract class AbstractReactiveWebServerFactoryTests {
} }
protected WebClient prepareCompressionTest(Compression compression) { protected WebClient prepareCompressionTest(Compression compression) {
return prepareCompressionTest(compression, MediaType.TEXT_PLAIN_VALUE);
}
protected WebClient prepareCompressionTest(Compression compression, String responseContentType) {
AbstractReactiveWebServerFactory factory = getFactory(); AbstractReactiveWebServerFactory factory = getFactory();
factory.setCompression(compression); factory.setCompression(compression);
this.webServer = factory.getWebServer(new CharsHandler(3000, MediaType.TEXT_PLAIN)); this.webServer = factory.getWebServer(new CharsHandler(3000, responseContentType));
this.webServer.start(); this.webServer.start();
HttpClient client = HttpClient.create().wiretap(true).compress(true) HttpClient client = HttpClient.create().wiretap(true).compress(true)
@ -368,9 +374,9 @@ public abstract class AbstractReactiveWebServerFactoryTests {
private final DataBuffer bytes; private final DataBuffer bytes;
private final MediaType mediaType; private final String mediaType;
public CharsHandler(int contentSize, MediaType mediaType) { public CharsHandler(int contentSize, String mediaType) {
char[] chars = new char[contentSize]; char[] chars = new char[contentSize];
Arrays.fill(chars, 'F'); Arrays.fill(chars, 'F');
this.bytes = factory.wrap(new String(chars).getBytes(StandardCharsets.UTF_8)); this.bytes = factory.wrap(new String(chars).getBytes(StandardCharsets.UTF_8));
@ -380,7 +386,7 @@ public abstract class AbstractReactiveWebServerFactoryTests {
@Override @Override
public Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response) { public Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response) {
response.setStatusCode(HttpStatus.OK); response.setStatusCode(HttpStatus.OK);
response.getHeaders().setContentType(this.mediaType); response.getHeaders().set(HttpHeaders.CONTENT_TYPE, this.mediaType);
response.getHeaders().setContentLength(this.bytes.readableByteCount()); response.getHeaders().setContentLength(this.bytes.readableByteCount());
return response.writeWith(Mono.just(this.bytes)); return response.writeWith(Mono.just(this.bytes));
} }

Loading…
Cancel
Save