diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/curl/CurlRequestSnippet.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/curl/CurlRequestSnippet.java index 9270c126..57cddd6c 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/curl/CurlRequestSnippet.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/curl/CurlRequestSnippet.java @@ -80,7 +80,6 @@ public class CurlRequestSnippet extends TemplatedSnippet { writeHttpMethodIfNecessary(operation.getRequest(), printer); writeHeaders(headers, printer); writePartsIfNecessary(operation.getRequest(), printer); - writeContent(operation.getRequest(), printer); return command.toString(); @@ -126,7 +125,7 @@ public class CurlRequestSnippet extends TemplatedSnippet { for (OperationRequestPart part : request.getParts()) { writer.printf(" -F '%s=", part.getName()); if (!StringUtils.hasText(part.getSubmittedFileName())) { - writer.append(new String(part.getContent())); + writer.append(part.getContentAsString()); } else { writer.printf("@%s", part.getSubmittedFileName()); @@ -141,8 +140,9 @@ public class CurlRequestSnippet extends TemplatedSnippet { } private void writeContent(OperationRequest request, PrintWriter writer) { - if (request.getContent().length > 0) { - writer.print(String.format(" -d '%s'", new String(request.getContent()))); + String content = request.getContentAsString(); + if (StringUtils.hasText(content)) { + writer.print(String.format(" -d '%s'", content)); } else if (!request.getParts().isEmpty()) { for (Entry> entry : request.getParameters().entrySet()) { diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/http/HttpRequestSnippet.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/http/HttpRequestSnippet.java index 092e1fdb..9b73fde4 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/http/HttpRequestSnippet.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/http/HttpRequestSnippet.java @@ -16,7 +16,6 @@ package org.springframework.restdocs.http; -import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; @@ -31,7 +30,6 @@ import org.springframework.http.MediaType; import org.springframework.restdocs.operation.Operation; import org.springframework.restdocs.operation.OperationRequest; import org.springframework.restdocs.operation.OperationRequestPart; -import org.springframework.restdocs.snippet.ModelCreationException; import org.springframework.restdocs.snippet.Snippet; import org.springframework.restdocs.snippet.TemplatedSnippet; import org.springframework.util.StringUtils; @@ -108,8 +106,9 @@ public class HttpRequestSnippet extends TemplatedSnippet { private String getRequestBody(OperationRequest request) { StringWriter httpRequest = new StringWriter(); PrintWriter writer = new PrintWriter(httpRequest); - if (request.getContent().length > 0) { - writer.print(requestBody(request)); + String content = request.getContentAsString(); + if (StringUtils.hasText(content)) { + writer.printf("%n%s", content); } else if (isPutOrPost(request)) { if (request.getParts().isEmpty()) { @@ -126,16 +125,6 @@ public class HttpRequestSnippet extends TemplatedSnippet { return httpRequest.toString(); } - private String requestBody(OperationRequest request) { - try { - String content = request.getContentAsString(); - return content.isEmpty() ? content : String.format("%n%s", content); - } - catch (IOException e) { - throw new ModelCreationException("Failed to create response body.", e); - } - } - private boolean isPutOrPost(OperationRequest request) { return HttpMethod.PUT.equals(request.getMethod()) || HttpMethod.POST.equals(request.getMethod()); @@ -163,7 +152,7 @@ public class HttpRequestSnippet extends TemplatedSnippet { } private void writePart(OperationRequestPart part, PrintWriter writer) { - writePart(part.getName(), new String(part.getContent()), part.getHeaders() + writePart(part.getName(), part.getContentAsString(), part.getHeaders() .getContentType(), writer); } diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/http/HttpResponseSnippet.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/http/HttpResponseSnippet.java index 69ee312f..9d2de12c 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/http/HttpResponseSnippet.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/http/HttpResponseSnippet.java @@ -16,7 +16,6 @@ package org.springframework.restdocs.http; -import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -26,7 +25,6 @@ import java.util.Map.Entry; import org.springframework.http.HttpStatus; import org.springframework.restdocs.operation.Operation; import org.springframework.restdocs.operation.OperationResponse; -import org.springframework.restdocs.snippet.ModelCreationException; import org.springframework.restdocs.snippet.Snippet; import org.springframework.restdocs.snippet.TemplatedSnippet; @@ -69,13 +67,8 @@ public class HttpResponseSnippet extends TemplatedSnippet { } private String responseBody(OperationResponse response) { - try { - String content = response.getContentAsString(); - return content.isEmpty() ? content : String.format("%n%s", content); - } - catch (IOException e) { - throw new ModelCreationException("Failed to create response body.", e); - } + String content = response.getContentAsString(); + return content.isEmpty() ? content : String.format("%n%s", content); } private List> headers(OperationResponse response) { diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/hypermedia/AbstractJsonLinkExtractor.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/hypermedia/AbstractJsonLinkExtractor.java index 4b952ca2..cc9f115a 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/hypermedia/AbstractJsonLinkExtractor.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/hypermedia/AbstractJsonLinkExtractor.java @@ -38,7 +38,7 @@ abstract class AbstractJsonLinkExtractor implements LinkExtractor { public Map> extractLinks(OperationResponse response) throws IOException { Map jsonContent = this.objectMapper.readValue( - new String(response.getContent()), Map.class); + response.getContent(), Map.class); return extractLinks(jsonContent); } diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/AbstractOperationMessage.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/AbstractOperationMessage.java new file mode 100644 index 00000000..c5ede617 --- /dev/null +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/AbstractOperationMessage.java @@ -0,0 +1,69 @@ +/* + * Copyright 2014-2015 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.restdocs.operation; + +import java.nio.charset.Charset; +import java.util.Arrays; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; + +/** + * Abstract base class for operation requests, request parts, and responses. + * + * @author Andy Wilkinson + */ +abstract class AbstractOperationMessage { + + private final byte[] content; + + private final HttpHeaders headers; + + AbstractOperationMessage(byte[] content, HttpHeaders headers) { + this.content = content == null ? new byte[0] : content; + this.headers = headers; + } + + public byte[] getContent() { + return Arrays.copyOf(this.content, this.content.length); + } + + public HttpHeaders getHeaders() { + return HttpHeaders.readOnlyHttpHeaders(this.headers); + } + + public String getContentAsString() { + if (this.content.length > 0) { + Charset charset = extractCharsetFromContentTypeHeader(); + return charset != null ? new String(this.content, charset) : new String( + this.content); + } + return ""; + } + + private Charset extractCharsetFromContentTypeHeader() { + if (this.headers == null) { + return null; + } + MediaType contentType = this.headers.getContentType(); + if (contentType == null) { + return null; + } + return contentType.getCharSet(); + } + +} diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationRequest.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationRequest.java index a56eae40..29153eec 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationRequest.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationRequest.java @@ -16,7 +16,6 @@ package org.springframework.restdocs.operation; -import java.io.IOException; import java.net.URI; import java.util.Collection; @@ -32,20 +31,22 @@ import org.springframework.http.HttpMethod; public interface OperationRequest { /** - * Returns the contents of the request. If the request has no content an empty array - * is returned. + * Returns the content of the request. If the request has no content an empty array is + * returned. * * @return the contents, never {@code null} */ byte[] getContent(); /** - * Returns the contents as string of the request. If the request has no content an empty string - * is returned + * Returns the content of the request as a {@link String}. If the request has no + * content an empty string is returned. If the request has a {@code Content-Type} + * header that specifies a charset then that charset will be used when converting the + * contents to a {@code String}. + * * @return the contents as string, never {@code null} - * @throws IOException if an input or output exception occurred */ - String getContentAsString() throws IOException; + String getContentAsString(); /** * Returns the headers that were included in the request. diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationRequestPart.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationRequestPart.java index 69a6feca..13cb8ed0 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationRequestPart.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationRequestPart.java @@ -47,6 +47,16 @@ public interface OperationRequestPart { */ byte[] getContent(); + /** + * Returns the content of the part as a {@link String}. If the part has no content an + * empty string is returned. If the part has a {@code Content-Type} header that + * specifies a charset then that charset will be used when converting the contents to + * a {@code String}. + * + * @return the contents as string, never {@code null} + */ + String getContentAsString(); + /** * Returns the part's headers. * diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationResponse.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationResponse.java index 4f0cd181..6a518679 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationResponse.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationResponse.java @@ -16,8 +16,6 @@ package org.springframework.restdocs.operation; -import java.io.IOException; - import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; @@ -45,7 +43,7 @@ public interface OperationResponse { HttpHeaders getHeaders(); /** - * Returns the contents of the response. If the response has no content an empty array + * Returns the content of the response. If the response has no content an empty array * is returned. * * @return the contents, never {@code null} @@ -53,10 +51,13 @@ public interface OperationResponse { byte[] getContent(); /** - * Returns the contents as string of the response. If the response has no content an empty string - * is returned + * Returns the content of the response as a {@link String}. If the response has no + * content an empty string is returned. If the response has a {@code Content-Type} + * header that specifies a charset then that charset will be used when converting the + * contents to a {@code String}. + * * @return the contents as string, never {@code null} - * @throws IOException if an input or output exception occurred */ - String getContentAsString() throws IOException; + String getContentAsString(); + } diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/StandardOperationRequest.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/StandardOperationRequest.java index f7885e5b..c869100b 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/StandardOperationRequest.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/StandardOperationRequest.java @@ -16,28 +16,20 @@ package org.springframework.restdocs.operation; -import java.io.UnsupportedEncodingException; import java.net.URI; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; -import org.springframework.http.MediaType; /** * Standard implementation of {@link OperationRequest}. * * @author Andy Wilkinson */ -public class StandardOperationRequest implements OperationRequest { - - private byte[] content; - - private String characterEncoding; - - private HttpHeaders headers; +public class StandardOperationRequest extends AbstractOperationMessage implements + OperationRequest { private HttpMethod method; @@ -61,36 +53,13 @@ public class StandardOperationRequest implements OperationRequest { public StandardOperationRequest(URI uri, HttpMethod method, byte[] content, HttpHeaders headers, Parameters parameters, Collection parts) { + super(content, headers); this.uri = uri; this.method = method; - this.content = content; - this.characterEncoding = detectCharsetFromContentTypeHeader(headers); - this.headers = headers; this.parameters = parameters; this.parts = parts; } - @Override - public byte[] getContent() { - return Arrays.copyOf(this.content, this.content.length); - } - - @Override - public String getContentAsString() throws UnsupportedEncodingException { - if (content.length > 0) { - return characterEncoding != null ? - new String(content, characterEncoding) : new String(content); - } - else { - return ""; - } - } - - @Override - public HttpHeaders getHeaders() { - return this.headers; - } - @Override public HttpMethod getMethod() { return this.method; @@ -111,14 +80,4 @@ public class StandardOperationRequest implements OperationRequest { return this.uri; } - private String detectCharsetFromContentTypeHeader(HttpHeaders headers) { - if (headers == null) { - return null; - } - MediaType contentType = headers.getContentType(); - if (contentType == null) { - return null; - } - return contentType.getParameter("charset"); - } } diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/StandardOperationRequestPart.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/StandardOperationRequestPart.java index b6c7bd03..c0f6e891 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/StandardOperationRequestPart.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/StandardOperationRequestPart.java @@ -23,16 +23,13 @@ import org.springframework.http.HttpHeaders; * * @author Andy Wilkinson */ -public class StandardOperationRequestPart implements OperationRequestPart { +public class StandardOperationRequestPart extends AbstractOperationMessage implements + OperationRequestPart { private final String name; private final String submittedFileName; - private final byte[] content; - - private final HttpHeaders headers; - /** * Creates a new {@code StandardOperationRequestPart} with the given {@code name}. * @@ -43,10 +40,9 @@ public class StandardOperationRequestPart implements OperationRequestPart { */ public StandardOperationRequestPart(String name, String submittedFileName, byte[] content, HttpHeaders headers) { + super(content, headers); this.name = name; this.submittedFileName = submittedFileName; - this.content = content; - this.headers = headers; } @Override @@ -59,14 +55,4 @@ public class StandardOperationRequestPart implements OperationRequestPart { return this.submittedFileName; } - @Override - public byte[] getContent() { - return this.content; - } - - @Override - public HttpHeaders getHeaders() { - return this.headers; - } - } diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/StandardOperationResponse.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/StandardOperationResponse.java index 628e6f19..1e42beb2 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/StandardOperationResponse.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/StandardOperationResponse.java @@ -16,27 +16,19 @@ package org.springframework.restdocs.operation; -import java.io.UnsupportedEncodingException; - import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; /** * Standard implementation of {@link OperationResponse}. * * @author Andy Wilkinson */ -public class StandardOperationResponse implements OperationResponse { +public class StandardOperationResponse extends AbstractOperationMessage implements + OperationResponse { private final HttpStatus status; - private final HttpHeaders headers; - - private final byte[] content; - - private String characterEncoding; - /** * Creates a new response with the given {@code status}, {@code headers}, and * {@code content}. @@ -47,10 +39,8 @@ public class StandardOperationResponse implements OperationResponse { */ public StandardOperationResponse(HttpStatus status, HttpHeaders headers, byte[] content) { + super(content, headers); this.status = status; - this.headers = headers; - this.content = content; - this.characterEncoding = detectCharsetFromContentTypeHeader(headers); } @Override @@ -58,35 +48,4 @@ public class StandardOperationResponse implements OperationResponse { return this.status; } - @Override - public HttpHeaders getHeaders() { - return this.headers; - } - - @Override - public byte[] getContent() { - return this.content; - } - - @Override - public String getContentAsString() throws UnsupportedEncodingException { - if (content.length > 0) { - return characterEncoding != null ? - new String(content, characterEncoding) : new String(content); - } - else { - return ""; - } - } - - private String detectCharsetFromContentTypeHeader(HttpHeaders headers) { - if (headers == null) { - return null; - } - MediaType contentType = headers.getContentType(); - if (contentType == null) { - return null; - } - return contentType.getParameter("charset"); - } } diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/ContentModifier.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/ContentModifier.java index 642c0027..8781a817 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/ContentModifier.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/ContentModifier.java @@ -16,6 +16,7 @@ package org.springframework.restdocs.operation.preprocess; +import org.springframework.http.MediaType; import org.springframework.restdocs.operation.OperationRequest; import org.springframework.restdocs.operation.OperationResponse; @@ -33,8 +34,9 @@ public interface ContentModifier { * Returns modified content based on the given {@code originalContent}. * * @param originalContent the original content + * @param contentType the type of the original content, may be {@code null} * @return the modified content */ - byte[] modifyContent(byte[] originalContent); + byte[] modifyContent(byte[] originalContent, MediaType contentType); } diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/ContentModifyingOperationPreprocessor.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/ContentModifyingOperationPreprocessor.java index 18f5602a..ad37baea 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/ContentModifyingOperationPreprocessor.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/ContentModifyingOperationPreprocessor.java @@ -44,7 +44,8 @@ public class ContentModifyingOperationPreprocessor implements OperationPreproces @Override public OperationRequest preprocess(OperationRequest request) { - byte[] modifiedContent = this.contentModifier.modifyContent(request.getContent()); + byte[] modifiedContent = this.contentModifier.modifyContent(request.getContent(), + request.getHeaders().getContentType()); return new StandardOperationRequest(request.getUri(), request.getMethod(), modifiedContent, getUpdatedHeaders(request.getHeaders(), modifiedContent), @@ -53,8 +54,8 @@ public class ContentModifyingOperationPreprocessor implements OperationPreproces @Override public OperationResponse preprocess(OperationResponse response) { - byte[] modifiedContent = this.contentModifier - .modifyContent(response.getContent()); + byte[] modifiedContent = this.contentModifier.modifyContent( + response.getContent(), response.getHeaders().getContentType()); return new StandardOperationResponse(response.getStatus(), getUpdatedHeaders( response.getHeaders(), modifiedContent), modifiedContent); } diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/LinkMaskingContentModifier.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/LinkMaskingContentModifier.java index 1a2b56cd..9af9c03f 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/LinkMaskingContentModifier.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/LinkMaskingContentModifier.java @@ -18,6 +18,8 @@ package org.springframework.restdocs.operation.preprocess; import java.util.regex.Pattern; +import org.springframework.http.MediaType; + /** * A content modifier the masks the {@code href} of any hypermedia links. * @@ -41,8 +43,8 @@ class LinkMaskingContentModifier implements ContentModifier { } @Override - public byte[] modifyContent(byte[] originalContent) { - return this.contentModifier.modifyContent(originalContent); + public byte[] modifyContent(byte[] originalContent, MediaType contentType) { + return this.contentModifier.modifyContent(originalContent, contentType); } } diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/PatternReplacingContentModifier.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/PatternReplacingContentModifier.java index 81464c91..58d4e3a7 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/PatternReplacingContentModifier.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/PatternReplacingContentModifier.java @@ -19,6 +19,8 @@ package org.springframework.restdocs.operation.preprocess; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.springframework.http.MediaType; + /** * A {@link ContentModifier} that modifies the content by replacing occurrences of a * regular expression {@link Pattern}. @@ -45,15 +47,29 @@ class PatternReplacingContentModifier implements ContentModifier { } @Override - public byte[] modifyContent(byte[] content) { - String original = new String(content); + public byte[] modifyContent(byte[] content, MediaType contentType) { + String original; + if (contentType != null && contentType.getCharSet() != null) { + original = new String(content, contentType.getCharSet()); + } + else { + original = new String(content); + } Matcher matcher = this.pattern.matcher(original); StringBuilder buffer = new StringBuilder(); int previous = 0; while (matcher.find()) { - buffer.append(original.substring(previous, matcher.start(1))); + String prefix; + if (matcher.groupCount() > 0) { + prefix = original.substring(previous, matcher.start(1)); + previous = matcher.end(1); + } + else { + prefix = original.substring(previous, matcher.start()); + previous = matcher.end(); + } + buffer.append(prefix); buffer.append(this.replacement); - previous = matcher.end(1); } if (previous < original.length()) { buffer.append(original.substring(previous)); diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/PrettyPrintingContentModifier.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/PrettyPrintingContentModifier.java index 6902e121..49af2bf4 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/PrettyPrintingContentModifier.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/PrettyPrintingContentModifier.java @@ -29,6 +29,8 @@ import javax.xml.transform.TransformerFactory; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; +import org.springframework.http.MediaType; + import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; @@ -44,7 +46,7 @@ public class PrettyPrintingContentModifier implements ContentModifier { new XmlPrettyPrinter())); @Override - public byte[] modifyContent(byte[] originalContent) { + public byte[] modifyContent(byte[] originalContent, MediaType contentType) { for (PrettyPrinter prettyPrinter : PRETTY_PRINTERS) { try { return prettyPrinter.prettyPrint(originalContent).getBytes(); diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/http/HttpRequestSnippetTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/http/HttpRequestSnippetTests.java index e225fa70..55cc9a07 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/http/HttpRequestSnippetTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/http/HttpRequestSnippetTests.java @@ -84,23 +84,22 @@ public class HttpRequestSnippetTests { .request("http://localhost/foo").method("POST").content("Hello, world") .build()); } - + @Test public void postRequestWithCharset() throws IOException { this.snippet.expectHttpRequest("post-request-with-charset").withContents( - httpRequest(POST, "/foo") - .header(HttpHeaders.HOST, "localhost") - .header("Content-Type", "text/plain;charset=UTF-8").content( - "こんにちわ, 世界")); // Hello, World in japanese. + httpRequest(RequestMethod.POST, "/foo") + .header(HttpHeaders.HOST, "localhost") + .header("Content-Type", "text/plain;charset=UTF-8") + .content("こんにちわ, 世界")); // Hello, World in Japanese new HttpRequestSnippet().document(new OperationBuilder( "post-request-with-charset", this.snippet.getOutputDirectory()) .request("http://localhost/foo").method("POST") - .header("Content-Type", "text/plain;charset=UTF-8") - .content("こんにちわ, 世界") + .header("Content-Type", "text/plain;charset=UTF-8").content("こんにちわ, 世界") .build()); } - + @Test public void postRequestWithParameter() throws IOException { this.snippet.expectHttpRequest("post-request-with-parameter").withContents( diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/http/HttpResponseSnippetTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/http/HttpResponseSnippetTests.java index 4349f5d0..cd6650f0 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/http/HttpResponseSnippetTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/http/HttpResponseSnippetTests.java @@ -68,8 +68,7 @@ public class HttpResponseSnippetTests { @Test public void responseWithHeaders() throws IOException { this.snippet.expectHttpResponse("response-with-headers").withContents( - httpResponse(HttpStatus.OK) // - .header("Content-Type", "application/json") // + httpResponse(HttpStatus.OK).header("Content-Type", "application/json") .header("a", "alpha")); new HttpResponseSnippet().document(new OperationBuilder("response-with-headers", this.snippet.getOutputDirectory()).response() @@ -84,15 +83,18 @@ public class HttpResponseSnippetTests { new HttpResponseSnippet().document(new OperationBuilder("response-with-content", this.snippet.getOutputDirectory()).response().content("content").build()); } - + @Test public void responseWithCharset() throws IOException { this.snippet.expectHttpResponse("response-with-charset").withContents( - httpResponse(OK).header("Content-Type", "text/plain;charset=UTF-8").content("コンテンツ")); + httpResponse(HttpStatus.OK).header("Content-Type", + "text/plain;charset=UTF-8").content("コンテンツ")); new HttpResponseSnippet().document(new OperationBuilder("response-with-charset", - this.snippet.getOutputDirectory()).response().header("Content-Type", "text/plain;charset=UTF-8").content("コンテンツ").build()); + this.snippet.getOutputDirectory()).response() + .header("Content-Type", "text/plain;charset=UTF-8").content("コンテンツ") + .build()); } - + @Test public void responseWithCustomSnippetAttributes() throws IOException { this.snippet.expectHttpResponse("response-with-snippet-attributes").withContents( diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/ContentModifyingOperationPreprocessorTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/ContentModifyingOperationPreprocessorTests.java index 6923b7db..5a38b1bd 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/ContentModifyingOperationPreprocessorTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/ContentModifyingOperationPreprocessorTests.java @@ -23,6 +23,7 @@ import org.junit.Test; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.restdocs.operation.OperationRequest; import org.springframework.restdocs.operation.OperationRequestPart; import org.springframework.restdocs.operation.OperationResponse; @@ -46,7 +47,7 @@ public class ContentModifyingOperationPreprocessorTests { new ContentModifier() { @Override - public byte[] modifyContent(byte[] originalContent) { + public byte[] modifyContent(byte[] originalContent, MediaType mediaType) { return "modified".getBytes(); } diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/LinkMaskingContentModifierTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/LinkMaskingContentModifierTests.java index e63b887c..2dfdf64b 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/LinkMaskingContentModifierTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/LinkMaskingContentModifierTests.java @@ -52,37 +52,36 @@ public class LinkMaskingContentModifierTests { @Test public void halLinksAreMasked() throws Exception { - assertThat(this.contentModifier.modifyContent(halPayloadWithLinks(this.links)), + assertThat( + this.contentModifier.modifyContent(halPayloadWithLinks(this.links), null), is(equalTo(halPayloadWithLinks(this.maskedLinks)))); } @Test public void formattedHalLinksAreMasked() throws Exception { - assertThat( - this.contentModifier - .modifyContent(formattedHalPayloadWithLinks(this.links)), + assertThat(this.contentModifier.modifyContent( + formattedHalPayloadWithLinks(this.links), null), is(equalTo(formattedHalPayloadWithLinks(this.maskedLinks)))); } @Test public void atomLinksAreMasked() throws Exception { - assertThat(this.contentModifier.modifyContent(atomPayloadWithLinks(this.links)), - is(equalTo(atomPayloadWithLinks(this.maskedLinks)))); + assertThat(this.contentModifier.modifyContent(atomPayloadWithLinks(this.links), + null), is(equalTo(atomPayloadWithLinks(this.maskedLinks)))); } @Test public void formattedAtomLinksAreMasked() throws Exception { - assertThat( - this.contentModifier - .modifyContent(formattedAtomPayloadWithLinks(this.links)), + assertThat(this.contentModifier.modifyContent( + formattedAtomPayloadWithLinks(this.links), null), is(equalTo(formattedAtomPayloadWithLinks(this.maskedLinks)))); } @Test public void maskCanBeCustomized() throws Exception { assertThat( - new LinkMaskingContentModifier("custom") - .modifyContent(formattedAtomPayloadWithLinks(this.links)), + new LinkMaskingContentModifier("custom").modifyContent( + formattedAtomPayloadWithLinks(this.links), null), is(equalTo(formattedAtomPayloadWithLinks(new Link("a", "custom"), new Link("b", "custom"))))); } diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/PatternReplacingContentModifierTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/PatternReplacingContentModifierTests.java index de9ba056..8fedbc3d 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/PatternReplacingContentModifierTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/PatternReplacingContentModifierTests.java @@ -16,9 +16,11 @@ package org.springframework.restdocs.operation.preprocess; +import java.nio.charset.Charset; import java.util.regex.Pattern; import org.junit.Test; +import org.springframework.http.MediaType; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; @@ -35,13 +37,23 @@ public class PatternReplacingContentModifierTests { @Test public void patternsAreReplaced() throws Exception { Pattern pattern = Pattern.compile( - "([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})", + "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}", Pattern.CASE_INSENSITIVE); PatternReplacingContentModifier contentModifier = new PatternReplacingContentModifier( pattern, "<>"); - assertThat( - contentModifier.modifyContent("{\"id\" : \"CA761232-ED42-11CE-BACD-00AA0057B223\"}" - .getBytes()), is(equalTo("{\"id\" : \"<>\"}".getBytes()))); + assertThat(contentModifier.modifyContent( + "{\"id\" : \"CA761232-ED42-11CE-BACD-00AA0057B223\"}".getBytes(), null), + is(equalTo("{\"id\" : \"<>\"}".getBytes()))); + } + + @Test + public void encodingIsPreserved() { + Pattern pattern = Pattern.compile("[0-9]+"); + PatternReplacingContentModifier contentModifier = new PatternReplacingContentModifier( + pattern, "<>"); + assertThat(contentModifier.modifyContent("こんにちわ, 世界 123".getBytes(), + new MediaType("text", "plain", Charset.forName("UTF-8"))), + is(equalTo("こんにちわ, 世界 <>".getBytes()))); } } diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/PrettyPrintingContentModifierTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/PrettyPrintingContentModifierTests.java index abedadf3..85e5edf9 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/PrettyPrintingContentModifierTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/PrettyPrintingContentModifierTests.java @@ -31,16 +31,16 @@ public class PrettyPrintingContentModifierTests { @Test public void prettyPrintJson() throws Exception { - assertThat( - new PrettyPrintingContentModifier().modifyContent("{\"a\":5}".getBytes()), - equalTo(String.format("{%n \"a\" : 5%n}").getBytes())); + assertThat(new PrettyPrintingContentModifier().modifyContent( + "{\"a\":5}".getBytes(), null), equalTo(String.format("{%n \"a\" : 5%n}") + .getBytes())); } @Test public void prettyPrintXml() throws Exception { - assertThat( - new PrettyPrintingContentModifier().modifyContent("" - .getBytes()), equalTo(String.format( + assertThat(new PrettyPrintingContentModifier().modifyContent( + "".getBytes(), null), + equalTo(String.format( "%n" + "%n %n%n") .getBytes())); @@ -48,14 +48,15 @@ public class PrettyPrintingContentModifierTests { @Test public void empytContentIsHandledGracefully() throws Exception { - assertThat(new PrettyPrintingContentModifier().modifyContent("".getBytes()), + assertThat( + new PrettyPrintingContentModifier().modifyContent("".getBytes(), null), equalTo("".getBytes())); } @Test public void nonJsonAndNonXmlContentIsHandledGracefully() throws Exception { String content = "abcdefg"; - assertThat(new PrettyPrintingContentModifier().modifyContent(content.getBytes()), - equalTo(content.getBytes())); + assertThat(new PrettyPrintingContentModifier().modifyContent(content.getBytes(), + null), equalTo(content.getBytes())); } }