Browse Source

Merge pull request #1188 from soldierkam/fix-encoding-bb

pull/1202/merge
Rossen Stoyanchev 8 years ago
parent
commit
ea319345ed
  1. 43
      spring-test/src/main/java/org/springframework/mock/http/server/reactive/MockServerHttpResponse.java
  2. 6
      spring-web/src/main/java/org/springframework/http/codec/EncoderHttpMessageWriter.java
  3. 80
      spring-web/src/test/java/org/springframework/http/codec/EncoderHttpMessageWriterTest.java
  4. 21
      spring-web/src/test/java/org/springframework/http/codec/ResourceHttpMessageWriterTests.java
  5. 22
      spring-web/src/test/java/org/springframework/http/codec/ResourceRegionHttpMessageWriterTests.java
  6. 31
      spring-web/src/test/java/org/springframework/mock/http/server/reactive/test/MockServerHttpResponse.java

43
spring-test/src/main/java/org/springframework/mock/http/server/reactive/MockServerHttpResponse.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.mock.http.server.reactive;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.function.Supplier;
import org.reactivestreams.Publisher;
@ -24,11 +26,14 @@ import reactor.core.publisher.Mono; @@ -24,11 +26,14 @@ import reactor.core.publisher.Mono;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseCookie;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@ -106,4 +111,42 @@ public class MockServerHttpResponse implements ServerHttpResponse { @@ -106,4 +111,42 @@ public class MockServerHttpResponse implements ServerHttpResponse {
return this.bufferFactory;
}
/**
* Return the body of the response aggregated and converted to a String
* using the charset of the Content-Type response or otherwise defaulting
* to "UTF-8".
*/
public Mono<String> getBodyAsString() {
Charset charset = getCharset();
Charset charsetToUse = (charset != null ? charset : StandardCharsets.UTF_8);
return Flux.from(this.body)
.reduce(this.bufferFactory.allocateBuffer(), (previous, current) -> {
previous.write(current);
DataBufferUtils.release(current);
return previous;
})
.map(buffer -> dumpString(buffer, charsetToUse));
}
private static String dumpString(DataBuffer buffer, Charset charset) {
Assert.notNull(charset, "'charset' must not be null");
byte[] bytes = dumpBytes(buffer);
return new String(bytes, charset);
}
private static byte[] dumpBytes(DataBuffer buffer) {
Assert.notNull(buffer, "'buffer' must not be null");
byte[] bytes = new byte[buffer.readableByteCount()];
buffer.read(bytes);
return bytes;
}
private Charset getCharset() {
MediaType contentType = getHeaders().getContentType();
if (contentType != null) {
return contentType.getCharset();
}
return null;
}
}

6
spring-web/src/main/java/org/springframework/http/codec/EncoderHttpMessageWriter.java

@ -110,13 +110,15 @@ public class EncoderHttpMessageWriter<T> implements HttpMessageWriter<T> { @@ -110,13 +110,15 @@ public class EncoderHttpMessageWriter<T> implements HttpMessageWriter<T> {
* Used when {@link #write} is called without a concrete content type.
*
* <p>By default returns the first of {@link Encoder#getEncodableMimeTypes()
* encodableMimeTypes}, if any.
* encodableMimeTypes} that is concrete({@link MediaType#isConcrete()}), if any.
*
* @param elementType the type of element for encoding
* @return the content type, or {@code null}
*/
protected MediaType getDefaultContentType(ResolvableType elementType) {
return (!this.writableMediaTypes.isEmpty() ? this.writableMediaTypes.get(0) : null);
return writableMediaTypes.stream()
.filter(MediaType::isConcrete)
.findFirst().orElse(null);
}
}

80
spring-web/src/test/java/org/springframework/http/codec/EncoderHttpMessageWriterTest.java

@ -0,0 +1,80 @@ @@ -0,0 +1,80 @@
/*
* Copyright 2002-2016 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.http.codec;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import org.jetbrains.annotations.NotNull;
import org.junit.Test;
import reactor.core.publisher.Mono;
import org.springframework.core.ResolvableType;
import org.springframework.core.codec.ByteBufferEncoder;
import org.springframework.core.codec.Encoder;
import org.springframework.http.MediaType;
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
import org.springframework.tests.TestSubscriber;
import org.springframework.util.MimeTypeUtils;
/**
* Unit tests for {@link EncoderHttpMessageWriter}.
*
* @author Marcin Kamionowski
* @author Rossen Stoyanchev
*/
public class EncoderHttpMessageWriterTest {
private MockServerHttpResponse response = new MockServerHttpResponse();
@Test
public void writableMediaTypes() throws Exception {
EncoderHttpMessageWriter<ByteBuffer> writer = createWriter(new ByteBufferEncoder());
assertThat(writer.getWritableMediaTypes(), containsInAnyOrder(MimeTypeUtils.ALL));
}
@Test
public void supportedMediaTypes() throws Exception {
EncoderHttpMessageWriter<ByteBuffer> writer = createWriter(new ByteBufferEncoder());
assertTrue(writer.canWrite(ResolvableType.forClass(ByteBuffer.class), MediaType.ALL));
assertTrue(writer.canWrite(ResolvableType.forClass(ByteBuffer.class), MediaType.TEXT_PLAIN));
}
@Test
public void encodeByteBuffer(){
String payload = "Buffer payload";
Mono<ByteBuffer> source = Mono.just(ByteBuffer.wrap(payload.getBytes(UTF_8)));
EncoderHttpMessageWriter<ByteBuffer> writer = createWriter(new ByteBufferEncoder());
writer.write(source, ResolvableType.forClass(ByteBuffer.class),
MediaType.APPLICATION_OCTET_STREAM, this.response, Collections.emptyMap());
assertThat(this.response.getHeaders().getContentType(), is(MediaType.APPLICATION_OCTET_STREAM));
TestSubscriber.subscribe(this.response.getBodyAsString()).assertComplete().assertValues(payload);
}
@NotNull
private <T> EncoderHttpMessageWriter<T> createWriter(Encoder<T> encoder) {
return new EncoderHttpMessageWriter<>(encoder);
}
}

21
spring-web/src/test/java/org/springframework/http/codec/ResourceHttpMessageWriterTests.java

@ -21,17 +21,11 @@ import java.util.Collections; @@ -21,17 +21,11 @@ import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.core.ResolvableType;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.support.DataBufferTestUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRange;
import org.springframework.http.HttpStatus;
@ -82,7 +76,7 @@ public class ResourceHttpMessageWriterTests { @@ -82,7 +76,7 @@ public class ResourceHttpMessageWriterTests {
assertThat(this.response.getHeaders().getContentLength(), is(39L));
assertThat(this.response.getHeaders().getFirst(HttpHeaders.ACCEPT_RANGES), is("bytes"));
Mono<String> result = reduceToString(this.response.getBody(), this.response.bufferFactory());
Mono<String> result = this.response.getBodyAsString();
TestSubscriber.subscribe(result).assertComplete().assertValues("Spring Framework test resource content.");
}
@ -98,7 +92,7 @@ public class ResourceHttpMessageWriterTests { @@ -98,7 +92,7 @@ public class ResourceHttpMessageWriterTests {
assertThat(this.response.getHeaders().getFirst(HttpHeaders.ACCEPT_RANGES), is("bytes"));
assertThat(this.response.getHeaders().getContentLength(), is(6L));
Mono<String> result = reduceToString(this.response.getBody(), this.response.bufferFactory());
Mono<String> result = this.response.getBodyAsString();
TestSubscriber.subscribe(result).assertComplete().assertValues("Spring");
}
@ -113,15 +107,4 @@ public class ResourceHttpMessageWriterTests { @@ -113,15 +107,4 @@ public class ResourceHttpMessageWriterTests {
assertThat(this.response.getStatusCode(), is(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE));
}
private Mono<String> reduceToString(Publisher<DataBuffer> buffers, DataBufferFactory bufferFactory) {
return Flux.from(buffers)
.reduce(bufferFactory.allocateBuffer(), (previous, current) -> {
previous.write(current);
DataBufferUtils.release(current);
return previous;
})
.map(buffer -> DataBufferTestUtils.dumpString(buffer, StandardCharsets.UTF_8));
}
}

22
spring-web/src/test/java/org/springframework/http/codec/ResourceRegionHttpMessageWriterTests.java

@ -16,8 +16,8 @@ @@ -16,8 +16,8 @@
package org.springframework.http.codec;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
@ -28,17 +28,12 @@ import org.junit.Before; @@ -28,17 +28,12 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.core.ResolvableType;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.support.DataBufferTestUtils;
import org.springframework.core.io.support.ResourceRegion;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
@ -94,7 +89,7 @@ public class ResourceRegionHttpMessageWriterTests { @@ -94,7 +89,7 @@ public class ResourceRegionHttpMessageWriterTests {
assertThat(this.response.getHeaders().getFirst(HttpHeaders.CONTENT_RANGE), is("bytes 0-5/39"));
assertThat(this.response.getHeaders().getContentLength(), is(6L));
Mono<String> result = reduceToString(this.response.getBody(), this.response.bufferFactory());
Mono<String> result = response.getBodyAsString();
TestSubscriber.subscribe(result).assertComplete().assertValues("Spring");
}
@ -118,7 +113,7 @@ public class ResourceRegionHttpMessageWriterTests { @@ -118,7 +113,7 @@ public class ResourceRegionHttpMessageWriterTests {
HttpHeaders headers = this.response.getHeaders();
assertThat(headers.getContentType().toString(), startsWith("multipart/byteranges;boundary=" + boundary));
Mono<String> result = reduceToString(this.response.getBody(), this.response.bufferFactory());
Mono<String> result = response.getBodyAsString();
TestSubscriber
.subscribe(result).assertNoError()
.assertComplete()
@ -149,15 +144,4 @@ public class ResourceRegionHttpMessageWriterTests { @@ -149,15 +144,4 @@ public class ResourceRegionHttpMessageWriterTests {
});
}
private Mono<String> reduceToString(Publisher<DataBuffer> buffers, DataBufferFactory bufferFactory) {
return Flux.from(buffers)
.reduce(bufferFactory.allocateBuffer(), (previous, current) -> {
previous.write(current);
DataBufferUtils.release(current);
return previous;
})
.map(buffer -> DataBufferTestUtils.dumpString(buffer, StandardCharsets.UTF_8));
}
}

31
spring-web/src/test/java/org/springframework/mock/http/server/reactive/test/MockServerHttpResponse.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.mock.http.server.reactive.test;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.function.Supplier;
import org.reactivestreams.Publisher;
@ -24,9 +26,12 @@ import reactor.core.publisher.Mono; @@ -24,9 +26,12 @@ import reactor.core.publisher.Mono;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.core.io.buffer.support.DataBufferTestUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseCookie;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.util.LinkedMultiValueMap;
@ -57,6 +62,7 @@ public class MockServerHttpResponse implements ServerHttpResponse { @@ -57,6 +62,7 @@ public class MockServerHttpResponse implements ServerHttpResponse {
return true;
}
@Override
public HttpStatus getStatusCode() {
return this.status;
}
@ -105,4 +111,29 @@ public class MockServerHttpResponse implements ServerHttpResponse { @@ -105,4 +111,29 @@ public class MockServerHttpResponse implements ServerHttpResponse {
return this.bufferFactory;
}
/**
* Return the body of the response aggregated and converted to a String
* using the charset of the Content-Type response or otherwise defaulting
* to "UTF-8".
*/
public Mono<String> getBodyAsString() {
Charset charset = getCharset();
Charset charsetToUse = (charset != null ? charset : StandardCharsets.UTF_8);
return Flux.from(this.body)
.reduce(this.bufferFactory.allocateBuffer(), (previous, current) -> {
previous.write(current);
DataBufferUtils.release(current);
return previous;
})
.map(buffer -> DataBufferTestUtils.dumpString(buffer, charsetToUse));
}
private Charset getCharset() {
MediaType contentType = getHeaders().getContentType();
if (contentType != null) {
return contentType.getCharset();
}
return null;
}
}

Loading…
Cancel
Save