Honour Content-Type charset whenever content is turned into a String
This commit builds on the changes made in the previous commit to make wider use of the new getContentAsString methods on OperationRequest and OperationResponse. It also adds such a method to OperationRequestPart. Any code that previously got the content as a byte array and then created a String has been updated to either use getContentAsString or to use the charset from the Content-Type header when creating a String. See gh-126
This commit is contained in:
@@ -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<String, List<String>> entry : request.getParameters().entrySet()) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Map<String, String>> headers(OperationResponse response) {
|
||||
|
||||
@@ -38,7 +38,7 @@ abstract class AbstractJsonLinkExtractor implements LinkExtractor {
|
||||
public Map<String, List<Link>> extractLinks(OperationResponse response)
|
||||
throws IOException {
|
||||
Map<String, Object> jsonContent = this.objectMapper.readValue(
|
||||
new String(response.getContent()), Map.class);
|
||||
response.getContent(), Map.class);
|
||||
return extractLinks(jsonContent);
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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();
|
||||
|
||||
}
|
||||
|
||||
@@ -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<OperationRequestPart> 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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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")))));
|
||||
}
|
||||
|
||||
@@ -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, "<<uuid>>");
|
||||
assertThat(
|
||||
contentModifier.modifyContent("{\"id\" : \"CA761232-ED42-11CE-BACD-00AA0057B223\"}"
|
||||
.getBytes()), is(equalTo("{\"id\" : \"<<uuid>>\"}".getBytes())));
|
||||
assertThat(contentModifier.modifyContent(
|
||||
"{\"id\" : \"CA761232-ED42-11CE-BACD-00AA0057B223\"}".getBytes(), null),
|
||||
is(equalTo("{\"id\" : \"<<uuid>>\"}".getBytes())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodingIsPreserved() {
|
||||
Pattern pattern = Pattern.compile("[0-9]+");
|
||||
PatternReplacingContentModifier contentModifier = new PatternReplacingContentModifier(
|
||||
pattern, "<<number>>");
|
||||
assertThat(contentModifier.modifyContent("こんにちわ, 世界 123".getBytes(),
|
||||
new MediaType("text", "plain", Charset.forName("UTF-8"))),
|
||||
is(equalTo("こんにちわ, 世界 <<number>>".getBytes())));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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("<one a=\"alpha\"><two b=\"bravo\"/></one>"
|
||||
.getBytes()), equalTo(String.format(
|
||||
assertThat(new PrettyPrintingContentModifier().modifyContent(
|
||||
"<one a=\"alpha\"><two b=\"bravo\"/></one>".getBytes(), null),
|
||||
equalTo(String.format(
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>%n"
|
||||
+ "<one a=\"alpha\">%n <two b=\"bravo\"/>%n</one>%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()));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user