Update HTTP request and response snippets to honour charset of content
Closes gh-126
This commit is contained in:
committed by
Andy Wilkinson
parent
e04d361dcd
commit
9b31c0ce9b
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.restdocs.http;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
@@ -30,6 +31,7 @@ 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;
|
||||
@@ -107,8 +109,7 @@ public class HttpRequestSnippet extends TemplatedSnippet {
|
||||
StringWriter httpRequest = new StringWriter();
|
||||
PrintWriter writer = new PrintWriter(httpRequest);
|
||||
if (request.getContent().length > 0) {
|
||||
writer.println();
|
||||
writer.print(new String(request.getContent()));
|
||||
writer.print(requestBody(request));
|
||||
}
|
||||
else if (isPutOrPost(request)) {
|
||||
if (request.getParts().isEmpty()) {
|
||||
@@ -125,6 +126,16 @@ 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());
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.restdocs.http;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -25,6 +26,7 @@ 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;
|
||||
|
||||
@@ -59,16 +61,23 @@ public class HttpResponseSnippet extends TemplatedSnippet {
|
||||
OperationResponse response = operation.getResponse();
|
||||
HttpStatus status = response.getStatus();
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
model.put(
|
||||
"responseBody",
|
||||
response.getContent().length > 0 ? String.format("%n%s", new String(
|
||||
response.getContent())) : "");
|
||||
model.put("responseBody", responseBody(response));
|
||||
model.put("statusCode", status.value());
|
||||
model.put("statusReason", status.getReasonPhrase());
|
||||
model.put("headers", headers(response));
|
||||
return model;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
private List<Map<String, String>> headers(OperationResponse response) {
|
||||
List<Map<String, String>> headers = new ArrayList<>();
|
||||
for (Entry<String, List<String>> header : response.getHeaders().entrySet()) {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.restdocs.operation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Collection;
|
||||
|
||||
@@ -38,6 +39,14 @@ public interface OperationRequest {
|
||||
*/
|
||||
byte[] getContent();
|
||||
|
||||
/**
|
||||
* Returns the contents as string of the request. If the request has no content an empty string
|
||||
* is returned
|
||||
* @return the contents as string, never {@code null}
|
||||
* @throws IOException if an input or output exception occurred
|
||||
*/
|
||||
String getContentAsString() throws IOException;
|
||||
|
||||
/**
|
||||
* Returns the headers that were included in the request.
|
||||
*
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.restdocs.operation;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
@@ -49,4 +51,12 @@ public interface OperationResponse {
|
||||
* @return the contents, never {@code null}
|
||||
*/
|
||||
byte[] getContent();
|
||||
|
||||
/**
|
||||
* Returns the contents as string of the response. If the response has no content an empty string
|
||||
* is returned
|
||||
* @return the contents as string, never {@code null}
|
||||
* @throws IOException if an input or output exception occurred
|
||||
*/
|
||||
String getContentAsString() throws IOException;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.restdocs.operation;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@@ -23,6 +24,7 @@ import java.util.Collections;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
/**
|
||||
* Standard implementation of {@link OperationRequest}.
|
||||
@@ -33,6 +35,8 @@ public class StandardOperationRequest implements OperationRequest {
|
||||
|
||||
private byte[] content;
|
||||
|
||||
private String characterEncoding;
|
||||
|
||||
private HttpHeaders headers;
|
||||
|
||||
private HttpMethod method;
|
||||
@@ -60,6 +64,7 @@ public class StandardOperationRequest implements OperationRequest {
|
||||
this.uri = uri;
|
||||
this.method = method;
|
||||
this.content = content;
|
||||
this.characterEncoding = detectCharsetFromContentTypeHeader(headers);
|
||||
this.headers = headers;
|
||||
this.parameters = parameters;
|
||||
this.parts = parts;
|
||||
@@ -69,6 +74,17 @@ public class StandardOperationRequest implements OperationRequest {
|
||||
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() {
|
||||
@@ -95,4 +111,14 @@ 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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,11 @@
|
||||
|
||||
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}.
|
||||
@@ -32,6 +35,8 @@ public class StandardOperationResponse implements OperationResponse {
|
||||
|
||||
private final byte[] content;
|
||||
|
||||
private String characterEncoding;
|
||||
|
||||
/**
|
||||
* Creates a new response with the given {@code status}, {@code headers}, and
|
||||
* {@code content}.
|
||||
@@ -45,6 +50,7 @@ public class StandardOperationResponse implements OperationResponse {
|
||||
this.status = status;
|
||||
this.headers = headers;
|
||||
this.content = content;
|
||||
this.characterEncoding = detectCharsetFromContentTypeHeader(headers);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -62,4 +68,25 @@ public class StandardOperationResponse implements OperationResponse {
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,23 @@ 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.
|
||||
|
||||
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("こんにちわ, 世界")
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postRequestWithParameter() throws IOException {
|
||||
this.snippet.expectHttpRequest("post-request-with-parameter").withContents(
|
||||
|
||||
@@ -84,7 +84,15 @@ 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("コンテンツ"));
|
||||
new HttpResponseSnippet().document(new OperationBuilder("response-with-charset",
|
||||
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(
|
||||
|
||||
Reference in New Issue
Block a user