diff --git a/docs/src/docs/asciidoc/customizing-requests-and-responses.adoc b/docs/src/docs/asciidoc/customizing-requests-and-responses.adoc index d88fb06d..f88a5879 100644 --- a/docs/src/docs/asciidoc/customizing-requests-and-responses.adoc +++ b/docs/src/docs/asciidoc/customizing-requests-and-responses.adoc @@ -77,10 +77,6 @@ different replacement can also be specified if you wish. `removeHeaders` on `Preprocessors` removes any occurrences of the named headers from the request or response. -NOTE: For an HTTP 1.1 request to be valid it must contain a `Host` header. Therefore, -irrespective of any preprocessing, the default HTTP request snippet will always contain a -`Host` header. - [[customizing-requests-and-responses-preprocessors-replace-patterns]] diff --git a/docs/src/docs/asciidoc/documenting-your-api.adoc b/docs/src/docs/asciidoc/documenting-your-api.adoc index e0e477f3..7fd84cdf 100644 --- a/docs/src/docs/asciidoc/documenting-your-api.adoc +++ b/docs/src/docs/asciidoc/documenting-your-api.adoc @@ -388,8 +388,7 @@ call that is being documented | `http-request.adoc` | Contains the HTTP request that is equivalent to the `MockMvc` call that is being - documented. HTTP 1.1 requires a `Host` header. If you do not provide one via the - `MockMvc` API the snippet will add one automatically. +documented | `http-response.adoc` | Contains the HTTP response that was returned 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 4d1ce446..73829f24 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 @@ -18,10 +18,13 @@ package org.springframework.restdocs.curl; import java.io.PrintWriter; import java.io.StringWriter; +import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; @@ -43,6 +46,15 @@ import org.springframework.util.StringUtils; */ public class CurlRequestSnippet extends TemplatedSnippet { + private static final Set HEADER_FILTERS; + static { + Set headerFilters = new HashSet(); + headerFilters.add(new NamedHeaderFilter(HttpHeaders.HOST)); + headerFilters.add(new NamedHeaderFilter(HttpHeaders.CONTENT_LENGTH)); + headerFilters.add(new BasicAuthHeaderFilter()); + HEADER_FILTERS = Collections.unmodifiableSet(headerFilters); + } + /** * Creates a new {@code CurlRequestSnippet} with no additional attributes. */ @@ -76,9 +88,9 @@ public class CurlRequestSnippet extends TemplatedSnippet { StringWriter command = new StringWriter(); PrintWriter printer = new PrintWriter(command); writeIncludeHeadersInOutputOption(printer); - HttpHeaders headers = writeUserOptionIfNecessary(operation.getRequest(), printer); + writeUserOptionIfNecessary(operation.getRequest(), printer); writeHttpMethodIfNecessary(operation.getRequest(), printer); - writeHeaders(headers, printer); + writeHeaders(operation.getRequest().getHeaders(), printer); writePartsIfNecessary(operation.getRequest(), printer); writeContent(operation.getRequest(), printer); @@ -89,22 +101,12 @@ public class CurlRequestSnippet extends TemplatedSnippet { writer.print("-i"); } - private HttpHeaders writeUserOptionIfNecessary(OperationRequest request, - PrintWriter writer) { - HttpHeaders headers = new HttpHeaders(); - headers.putAll(request.getHeaders()); - String authorization = headers.getFirst(HttpHeaders.AUTHORIZATION); - if (isAuthorizationBasicHeader(authorization)) { - String credentials = new String(Base64Utils.decodeFromString(authorization - .substring(5).trim())); + private void writeUserOptionIfNecessary(OperationRequest request, PrintWriter writer) { + List headerValue = request.getHeaders().get(HttpHeaders.AUTHORIZATION); + if (BasicAuthHeaderFilter.isBasicAuthHeader(headerValue)) { + String credentials = BasicAuthHeaderFilter.decodeBasicAuthHeader(headerValue); writer.print(String.format(" -u '%s'", credentials)); - headers.remove(HttpHeaders.AUTHORIZATION); } - return headers; - } - - private boolean isAuthorizationBasicHeader(String header) { - return header != null && header.startsWith("Basic"); } private void writeHttpMethodIfNecessary(OperationRequest request, PrintWriter writer) { @@ -115,7 +117,7 @@ public class CurlRequestSnippet extends TemplatedSnippet { private void writeHeaders(HttpHeaders headers, PrintWriter writer) { for (Entry> entry : headers.entrySet()) { - if (!HttpHeaders.CONTENT_LENGTH.equalsIgnoreCase(entry.getKey())) { + if (allowedHeader(entry)) { for (String header : entry.getValue()) { writer.print(String.format(" -H '%s: %s'", entry.getKey(), header)); } @@ -123,6 +125,15 @@ public class CurlRequestSnippet extends TemplatedSnippet { } } + private boolean allowedHeader(Entry> header) { + for (HeaderFilter headerFilter : HEADER_FILTERS) { + if (!headerFilter.allow(header.getKey(), header.getValue())) { + return false; + } + } + return true; + } + private void writePartsIfNecessary(OperationRequest request, PrintWriter writer) { for (OperationRequestPart part : request.getParts()) { writer.printf(" -F '%s=", part.getName()); @@ -166,4 +177,45 @@ public class CurlRequestSnippet extends TemplatedSnippet { || HttpMethod.POST.equals(request.getMethod()); } + private interface HeaderFilter { + + boolean allow(String name, List value); + } + + private static final class BasicAuthHeaderFilter implements HeaderFilter { + + @Override + public boolean allow(String name, List value) { + if (HttpHeaders.AUTHORIZATION.equals(name) && isBasicAuthHeader(value)) { + return false; + } + return true; + } + + static boolean isBasicAuthHeader(List value) { + return value != null && (!value.isEmpty()) + && value.get(0).startsWith("Basic "); + } + + static String decodeBasicAuthHeader(List value) { + return new String(Base64Utils.decodeFromString(value.get(0).substring(6))); + } + + } + + private static final class NamedHeaderFilter implements HeaderFilter { + + private final String name; + + private NamedHeaderFilter(String name) { + this.name = name; + } + + @Override + public boolean allow(String name, List value) { + return !this.name.equalsIgnoreCase(name); + } + + } + } 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 9b73fde4..9060ada9 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 @@ -79,9 +79,6 @@ public class HttpRequestSnippet extends TemplatedSnippet { private List> getHeaders(OperationRequest request) { List> headers = new ArrayList<>(); - if (requiresHostHeader(request)) { - headers.add(header(HttpHeaders.HOST, request.getUri().getHost())); - } for (Entry> header : request.getHeaders().entrySet()) { for (String value : header.getValue()) { @@ -170,10 +167,6 @@ public class HttpRequestSnippet extends TemplatedSnippet { writer.printf("--%s--", MULTIPART_BOUNDARY); } - private boolean requiresHostHeader(OperationRequest request) { - return request.getHeaders().get(HttpHeaders.HOST) == null; - } - private boolean requiresFormEncodingContentTypeHeader(OperationRequest request) { return request.getHeaders().get(HttpHeaders.CONTENT_TYPE) == null && isPutOrPost(request) && !request.getParameters().isEmpty(); 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 index d111f321..c5ede617 100644 --- 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 @@ -35,18 +35,7 @@ abstract class AbstractOperationMessage { AbstractOperationMessage(byte[] content, HttpHeaders headers) { this.content = content == null ? new byte[0] : content; - this.headers = createHeaders(content, headers); - } - - private static HttpHeaders createHeaders(byte[] content, HttpHeaders input) { - HttpHeaders headers = new HttpHeaders(); - if (input != null) { - headers.putAll(input); - } - if (content != null && content.length > 0 && headers.getContentLength() == -1) { - headers.setContentLength(content.length); - } - return headers; + this.headers = headers; } public byte[] getContent() { diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/HttpHeadersHelper.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/HttpHeadersHelper.java new file mode 100644 index 00000000..a9cb7c5a --- /dev/null +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/HttpHeadersHelper.java @@ -0,0 +1,66 @@ +/* + * 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 org.springframework.http.HttpHeaders; + +/** + * Helper for working with {@link HttpHeaders}. + * + * @author Andy Wilkinson + */ +class HttpHeadersHelper { + + private final HttpHeaders httpHeaders; + + HttpHeadersHelper(HttpHeaders httpHeaders) { + HttpHeaders headers = new HttpHeaders(); + if (httpHeaders != null) { + headers.putAll(httpHeaders); + } + this.httpHeaders = headers; + } + + HttpHeadersHelper addIfAbsent(String name, String value) { + if (this.httpHeaders.get(name) == null) { + this.httpHeaders.add(name, value); + } + return this; + } + + HttpHeadersHelper updateContentLengthHeaderIfPresent(byte[] content) { + if (this.httpHeaders.getContentLength() != -1) { + setContentLengthHeader(content); + } + return this; + } + + HttpHeadersHelper setContentLengthHeader(byte[] content) { + if (content == null || content.length == 0) { + this.httpHeaders.remove(HttpHeaders.CONTENT_LENGTH); + } + else { + this.httpHeaders.setContentLength(content.length); + } + return this; + } + + HttpHeaders getHeaders() { + return HttpHeaders.readOnlyHttpHeaders(this.httpHeaders); + } + +} diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationRequestFactory.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationRequestFactory.java new file mode 100644 index 00000000..693be1dd --- /dev/null +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationRequestFactory.java @@ -0,0 +1,96 @@ +/* + * 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.net.URI; +import java.util.Collection; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; + +/** + * A factory for creating {@link OperationRequest OperationRequests}. + * + * @author Andy Wilkinson + */ +public class OperationRequestFactory { + + /** + * Creates a new {@link OperationRequest}. The given {@code headers} will be augmented + * to ensure that they always include a {@code Content-Length} header if the request + * has any content and a {@code Host} header. + * + * @param uri the request's uri + * @param method the request method + * @param content the content of the request + * @param headers the request's headers + * @param parameters the request's parameters + * @param parts the request's parts + * @return the {@code OperationRequest} + */ + public OperationRequest create(URI uri, HttpMethod method, byte[] content, + HttpHeaders headers, Parameters parameters, + Collection parts) { + return new StandardOperationRequest(uri, method, content, augmentHeaders(headers, + uri, content), parameters, parts); + } + + /** + * Creates a new {@code OperationRequest} based on the given {@code original} but with + * the given {@code newContent}. If the original request had a {@code Content-Length} + * header it will be modified to match the length of the new content. + * + * @param original The original request + * @param newContent The new content + * + * @return The new request with the new content + */ + public OperationRequest createFrom(OperationRequest original, byte[] newContent) { + return new StandardOperationRequest(original.getUri(), original.getMethod(), + newContent, getUpdatedHeaders(original.getHeaders(), newContent), + original.getParameters(), original.getParts()); + } + + /** + * Creates a new {@code OperationRequest} based on the given {@code original} but with + * the given {@code newHeaders}. + * + * @param original The original request + * @param newHeaders The new headers + * + * @return The new request with the new content + */ + public OperationRequest createFrom(OperationRequest original, HttpHeaders newHeaders) { + return new StandardOperationRequest(original.getUri(), original.getMethod(), + original.getContent(), newHeaders, original.getParameters(), + original.getParts()); + } + + private HttpHeaders augmentHeaders(HttpHeaders originalHeaders, URI uri, + byte[] content) { + return new HttpHeadersHelper(originalHeaders) + .addIfAbsent(HttpHeaders.HOST, uri.getHost()) + .setContentLengthHeader(content).getHeaders(); + } + + private HttpHeaders getUpdatedHeaders(HttpHeaders originalHeaders, + byte[] updatedContent) { + return new HttpHeadersHelper(originalHeaders).updateContentLengthHeaderIfPresent( + updatedContent).getHeaders(); + } + +} diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationRequestPartFactory.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationRequestPartFactory.java new file mode 100644 index 00000000..47aa7e43 --- /dev/null +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationRequestPartFactory.java @@ -0,0 +1,49 @@ +/* + * 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 org.springframework.http.HttpHeaders; + +/** + * A factory for creating {@link OperationRequestPart OperationRequestParts}. + * + * @author Andy Wilkinson + */ +public class OperationRequestPartFactory { + + /** + * Creates a new {@link OperationRequestPart}. The given {@code headers} will be + * augmented to ensure that they always include a {@code Content-Length} header if the + * part has any content. + * + * @param name the name of the part + * @param submittedFileName the name of the file being submitted by the part + * @param content the content of the part + * @param headers the headers of the part + * @return the {@code OperationRequestPart} + */ + public OperationRequestPart create(String name, String submittedFileName, + byte[] content, HttpHeaders headers) { + return new StandardOperationRequestPart(name, submittedFileName, content, + augmentHeaders(headers, content)); + } + + private HttpHeaders augmentHeaders(HttpHeaders input, byte[] content) { + return new HttpHeadersHelper(input).setContentLengthHeader(content).getHeaders(); + } + +} diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationResponseFactory.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationResponseFactory.java new file mode 100644 index 00000000..c3417c9f --- /dev/null +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationResponseFactory.java @@ -0,0 +1,85 @@ +/* + * 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 org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; + +/** + * A factory for creating {@link OperationResponse OperationResponses}. + * + * @author Andy Wilkinson + */ +public class OperationResponseFactory { + + /** + * Creates a new {@link OperationResponse}. If the response has any content, the given + * {@code headers} will be augmented to ensure that they include a + * {@code Content-Length} header. + * + * @param status the status of the response + * @param headers the request's headers + * @param content the content of the request + * @return the {@code OperationResponse} + */ + public OperationResponse create(HttpStatus status, HttpHeaders headers, byte[] content) { + return new StandardOperationResponse(status, augmentHeaders(headers, content), + content); + } + + /** + * Creates a new {@code OperationResponse} based on the given {@code original} but + * with the given {@code newContent}. If the original response had a + * {@code Content-Length} header it will be modified to match the length of the new + * content. + * + * @param original The original response + * @param newContent The new content + * + * @return The new response with the new content + */ + public OperationResponse createFrom(OperationResponse original, byte[] newContent) { + return new StandardOperationResponse(original.getStatus(), getUpdatedHeaders( + original.getHeaders(), newContent), newContent); + } + + /** + * Creates a new {@code OperationResponse} based on the given {@code original} but + * with the given {@code newHeaders}. + * + * @param original The original response + * @param newHeaders The new headers + * + * @return The new response with the new headers + */ + public OperationResponse createFrom(OperationResponse original, HttpHeaders newHeaders) { + return new StandardOperationResponse(original.getStatus(), newHeaders, + original.getContent()); + } + + private HttpHeaders augmentHeaders(HttpHeaders originalHeaders, byte[] content) { + return new HttpHeadersHelper(originalHeaders).setContentLengthHeader(content) + .getHeaders(); + } + + private HttpHeaders getUpdatedHeaders(HttpHeaders originalHeaders, + byte[] updatedContent) { + return new HttpHeadersHelper(originalHeaders).updateContentLengthHeaderIfPresent( + updatedContent).getHeaders(); + } + +} 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 c869100b..305d7b2a 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 @@ -28,7 +28,7 @@ import org.springframework.http.HttpMethod; * * @author Andy Wilkinson */ -public class StandardOperationRequest extends AbstractOperationMessage implements +class StandardOperationRequest extends AbstractOperationMessage implements OperationRequest { private HttpMethod method; @@ -50,7 +50,7 @@ public class StandardOperationRequest extends AbstractOperationMessage implement * @param parameters the parameters * @param parts the parts */ - public StandardOperationRequest(URI uri, HttpMethod method, byte[] content, + StandardOperationRequest(URI uri, HttpMethod method, byte[] content, HttpHeaders headers, Parameters parameters, Collection parts) { super(content, headers); 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 c0f6e891..8ea231a4 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,7 +23,7 @@ import org.springframework.http.HttpHeaders; * * @author Andy Wilkinson */ -public class StandardOperationRequestPart extends AbstractOperationMessage implements +class StandardOperationRequestPart extends AbstractOperationMessage implements OperationRequestPart { private final String name; @@ -38,8 +38,8 @@ public class StandardOperationRequestPart extends AbstractOperationMessage imple * @param content the contents of the part * @param headers the headers of the part */ - public StandardOperationRequestPart(String name, String submittedFileName, - byte[] content, HttpHeaders headers) { + StandardOperationRequestPart(String name, String submittedFileName, byte[] content, + HttpHeaders headers) { super(content, headers); this.name = name; this.submittedFileName = submittedFileName; 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 1e42beb2..32dfa57f 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 @@ -24,7 +24,7 @@ import org.springframework.http.HttpStatus; * * @author Andy Wilkinson */ -public class StandardOperationResponse extends AbstractOperationMessage implements +class StandardOperationResponse extends AbstractOperationMessage implements OperationResponse { private final HttpStatus status; @@ -37,8 +37,7 @@ public class StandardOperationResponse extends AbstractOperationMessage implemen * @param headers the headers of the response * @param content the content of the response */ - public StandardOperationResponse(HttpStatus status, HttpHeaders headers, - byte[] content) { + StandardOperationResponse(HttpStatus status, HttpHeaders headers, byte[] content) { super(content, headers); this.status = status; } 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 5cc31561..60c704aa 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 @@ -16,11 +16,10 @@ package org.springframework.restdocs.operation.preprocess; -import org.springframework.http.HttpHeaders; import org.springframework.restdocs.operation.OperationRequest; +import org.springframework.restdocs.operation.OperationRequestFactory; import org.springframework.restdocs.operation.OperationResponse; -import org.springframework.restdocs.operation.StandardOperationRequest; -import org.springframework.restdocs.operation.StandardOperationResponse; +import org.springframework.restdocs.operation.OperationResponseFactory; /** * An {@link OperationPreprocessor} that applies a {@link ContentModifier} to the content @@ -30,6 +29,10 @@ import org.springframework.restdocs.operation.StandardOperationResponse; */ public class ContentModifyingOperationPreprocessor implements OperationPreprocessor { + private final OperationRequestFactory requestFactory = new OperationRequestFactory(); + + private final OperationResponseFactory responseFactory = new OperationResponseFactory(); + private final ContentModifier contentModifier; /** @@ -46,30 +49,14 @@ public class ContentModifyingOperationPreprocessor implements OperationPreproces public OperationRequest preprocess(OperationRequest request) { byte[] modifiedContent = this.contentModifier.modifyContent(request.getContent(), request.getHeaders().getContentType()); - return new StandardOperationRequest(request.getUri(), request.getMethod(), - modifiedContent, - getUpdatedHeaders(request.getHeaders(), modifiedContent), - request.getParameters(), request.getParts()); + return this.requestFactory.createFrom(request, modifiedContent); } @Override public OperationResponse preprocess(OperationResponse response) { byte[] modifiedContent = this.contentModifier.modifyContent( response.getContent(), response.getHeaders().getContentType()); - return new StandardOperationResponse(response.getStatus(), getUpdatedHeaders( - response.getHeaders(), modifiedContent), modifiedContent); - } - - private HttpHeaders getUpdatedHeaders(HttpHeaders headers, byte[] updatedContent) { - HttpHeaders updatedHeaders = new HttpHeaders(); - updatedHeaders.putAll(headers); - if (updatedContent.length > 0) { - updatedHeaders.setContentLength(updatedContent.length); - } - else { - updatedHeaders.remove(HttpHeaders.CONTENT_LENGTH); - } - return updatedHeaders; + return this.responseFactory.createFrom(response, modifiedContent); } } diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/HeaderRemovingOperationPreprocessor.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/HeaderRemovingOperationPreprocessor.java index 36eba207..7766af57 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/HeaderRemovingOperationPreprocessor.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/HeaderRemovingOperationPreprocessor.java @@ -22,9 +22,9 @@ import java.util.Set; import org.springframework.http.HttpHeaders; import org.springframework.restdocs.operation.OperationRequest; +import org.springframework.restdocs.operation.OperationRequestFactory; import org.springframework.restdocs.operation.OperationResponse; -import org.springframework.restdocs.operation.StandardOperationRequest; -import org.springframework.restdocs.operation.StandardOperationResponse; +import org.springframework.restdocs.operation.OperationResponseFactory; /** * An {@link OperationPreprocessor} that removes headers. @@ -33,6 +33,10 @@ import org.springframework.restdocs.operation.StandardOperationResponse; */ class HeaderRemovingOperationPreprocessor implements OperationPreprocessor { + private final OperationRequestFactory requestFactory = new OperationRequestFactory(); + + private final OperationResponseFactory responseFactory = new OperationResponseFactory(); + private final Set headersToRemove; HeaderRemovingOperationPreprocessor(String... headersToRemove) { @@ -41,15 +45,14 @@ class HeaderRemovingOperationPreprocessor implements OperationPreprocessor { @Override public OperationResponse preprocess(OperationResponse response) { - return new StandardOperationResponse(response.getStatus(), - removeHeaders(response.getHeaders()), response.getContent()); + return this.responseFactory.createFrom(response, + removeHeaders(response.getHeaders())); } @Override public OperationRequest preprocess(OperationRequest request) { - return new StandardOperationRequest(request.getUri(), request.getMethod(), - request.getContent(), removeHeaders(request.getHeaders()), - request.getParameters(), request.getParts()); + return this.requestFactory.createFrom(request, + removeHeaders(request.getHeaders())); } private HttpHeaders removeHeaders(HttpHeaders originalHeaders) { 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 9ccb89f1..f948fb10 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 @@ -54,8 +54,8 @@ public class HttpRequestSnippetTests { @Test public void getRequest() throws IOException { this.snippet.expectHttpRequest("get-request").withContents( - httpRequest(RequestMethod.GET, "/foo").header(HttpHeaders.HOST, - "localhost").header("Alpha", "a")); + httpRequest(RequestMethod.GET, "/foo").header("Alpha", "a").header( + HttpHeaders.HOST, "localhost")); new HttpRequestSnippet().document(new OperationBuilder("get-request", this.snippet.getOutputDirectory()).request("http://localhost/foo") @@ -92,8 +92,8 @@ public class HttpRequestSnippetTests { byte[] contentBytes = japaneseContent.getBytes("UTF-8"); this.snippet.expectHttpRequest("post-request-with-charset").withContents( httpRequest(RequestMethod.POST, "/foo") - .header(HttpHeaders.HOST, "localhost") .header("Content-Type", "text/plain;charset=UTF-8") + .header(HttpHeaders.HOST, "localhost") .header(HttpHeaders.CONTENT_LENGTH, contentBytes.length) .content(japaneseContent)); @@ -151,10 +151,9 @@ public class HttpRequestSnippetTests { + "form-data; " + "name=image%n%n<< data >>")); this.snippet.expectHttpRequest("multipart-post").withContents( httpRequest(RequestMethod.POST, "/upload") - .header(HttpHeaders.HOST, "localhost") .header("Content-Type", "multipart/form-data; boundary=" + BOUNDARY) - .content(expectedContent)); + .header(HttpHeaders.HOST, "localhost").content(expectedContent)); new HttpRequestSnippet().document(new OperationBuilder("multipart-post", this.snippet.getOutputDirectory()).request("http://localhost/upload") .method("POST") @@ -175,10 +174,9 @@ public class HttpRequestSnippetTests { String expectedContent = param1Part + param2Part + param3Part + filePart; this.snippet.expectHttpRequest("multipart-post-with-parameters").withContents( httpRequest(RequestMethod.POST, "/upload") - .header(HttpHeaders.HOST, "localhost") .header("Content-Type", "multipart/form-data; boundary=" + BOUNDARY) - .content(expectedContent)); + .header(HttpHeaders.HOST, "localhost").content(expectedContent)); new HttpRequestSnippet().document(new OperationBuilder( "multipart-post-with-parameters", this.snippet.getOutputDirectory()) .request("http://localhost/upload").method("POST") @@ -194,10 +192,9 @@ public class HttpRequestSnippetTests { + "image/png%n%n<< data >>")); this.snippet.expectHttpRequest("multipart-post-with-content-type").withContents( httpRequest(RequestMethod.POST, "/upload") - .header(HttpHeaders.HOST, "localhost") .header("Content-Type", "multipart/form-data; boundary=" + BOUNDARY) - .content(expectedContent)); + .header(HttpHeaders.HOST, "localhost").content(expectedContent)); new HttpRequestSnippet().document(new OperationBuilder( "multipart-post-with-content-type", this.snippet.getOutputDirectory()) .request("http://localhost/upload").method("POST") diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/hypermedia/ContentTypeLinkExtractorTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/hypermedia/ContentTypeLinkExtractorTests.java index 5157e07b..4ff3dbb4 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/hypermedia/ContentTypeLinkExtractorTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/hypermedia/ContentTypeLinkExtractorTests.java @@ -26,7 +26,8 @@ import org.junit.rules.ExpectedException; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -import org.springframework.restdocs.operation.StandardOperationResponse; +import org.springframework.restdocs.operation.OperationResponse; +import org.springframework.restdocs.operation.OperationResponseFactory; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -38,13 +39,15 @@ import static org.mockito.Mockito.verify; */ public class ContentTypeLinkExtractorTests { + private final OperationResponseFactory responseFactory = new OperationResponseFactory(); + @Rule public ExpectedException thrown = ExpectedException.none(); @Test public void extractionFailsWithNullContentType() throws IOException { this.thrown.expect(IllegalStateException.class); - new ContentTypeLinkExtractor().extractLinks(new StandardOperationResponse( + new ContentTypeLinkExtractor().extractLinks(this.responseFactory.create( HttpStatus.OK, new HttpHeaders(), null)); } @@ -55,7 +58,7 @@ public class ContentTypeLinkExtractorTests { extractors.put(MediaType.APPLICATION_JSON, extractor); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.APPLICATION_JSON); - StandardOperationResponse response = new StandardOperationResponse(HttpStatus.OK, + OperationResponse response = this.responseFactory.create(HttpStatus.OK, httpHeaders, null); new ContentTypeLinkExtractor(extractors).extractLinks(response); verify(extractor).extractLinks(response); @@ -68,7 +71,7 @@ public class ContentTypeLinkExtractorTests { extractors.put(MediaType.APPLICATION_JSON, extractor); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.parseMediaType("application/json;foo=bar")); - StandardOperationResponse response = new StandardOperationResponse(HttpStatus.OK, + OperationResponse response = this.responseFactory.create(HttpStatus.OK, httpHeaders, null); new ContentTypeLinkExtractor(extractors).extractLinks(response); verify(extractor).extractLinks(response); diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/hypermedia/LinkExtractorsPayloadTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/hypermedia/LinkExtractorsPayloadTests.java index 02adf5cb..47a05424 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/hypermedia/LinkExtractorsPayloadTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/hypermedia/LinkExtractorsPayloadTests.java @@ -30,7 +30,7 @@ import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; import org.springframework.http.HttpStatus; import org.springframework.restdocs.operation.OperationResponse; -import org.springframework.restdocs.operation.StandardOperationResponse; +import org.springframework.restdocs.operation.OperationResponseFactory; import org.springframework.util.FileCopyUtils; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; @@ -46,6 +46,8 @@ import static org.junit.Assert.assertEquals; @RunWith(Parameterized.class) public class LinkExtractorsPayloadTests { + private final OperationResponseFactory responseFactory = new OperationResponseFactory(); + private final LinkExtractor linkExtractor; private final String linkType; @@ -107,7 +109,7 @@ public class LinkExtractorsPayloadTests { } private OperationResponse createResponse(String contentName) throws IOException { - return new StandardOperationResponse(HttpStatus.OK, null, + return this.responseFactory.create(HttpStatus.OK, null, FileCopyUtils.copyToByteArray(getPayloadFile(contentName))); } 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 2f38bbb3..330381f6 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 @@ -25,11 +25,11 @@ 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.OperationRequestFactory; import org.springframework.restdocs.operation.OperationRequestPart; import org.springframework.restdocs.operation.OperationResponse; +import org.springframework.restdocs.operation.OperationResponseFactory; import org.springframework.restdocs.operation.Parameters; -import org.springframework.restdocs.operation.StandardOperationRequest; -import org.springframework.restdocs.operation.StandardOperationResponse; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; @@ -43,6 +43,10 @@ import static org.junit.Assert.assertThat; */ public class ContentModifyingOperationPreprocessorTests { + private final OperationRequestFactory requestFactory = new OperationRequestFactory(); + + private final OperationResponseFactory responseFactory = new OperationResponseFactory(); + private final ContentModifyingOperationPreprocessor preprocessor = new ContentModifyingOperationPreprocessor( new ContentModifier() { @@ -55,7 +59,7 @@ public class ContentModifyingOperationPreprocessorTests { @Test public void modifyRequestContent() { - StandardOperationRequest request = new StandardOperationRequest( + OperationRequest request = this.requestFactory.create( URI.create("http://localhost"), HttpMethod.GET, "content".getBytes(), new HttpHeaders(), new Parameters(), Collections.emptyList()); @@ -65,7 +69,7 @@ public class ContentModifyingOperationPreprocessorTests { @Test public void modifyResponseContent() { - StandardOperationResponse response = new StandardOperationResponse(HttpStatus.OK, + OperationResponse response = this.responseFactory.create(HttpStatus.OK, new HttpHeaders(), "content".getBytes()); OperationResponse preprocessed = this.preprocessor.preprocess(response); assertThat(preprocessed.getContent(), is(equalTo("modified".getBytes()))); @@ -75,7 +79,7 @@ public class ContentModifyingOperationPreprocessorTests { public void contentLengthIsUpdated() { HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentLength(7); - StandardOperationRequest request = new StandardOperationRequest( + OperationRequest request = this.requestFactory.create( URI.create("http://localhost"), HttpMethod.GET, "content".getBytes(), httpHeaders, new Parameters(), Collections.emptyList()); diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/HeaderRemovingOperationPreprocessorTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/HeaderRemovingOperationPreprocessorTests.java index 808b9ab9..634ef616 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/HeaderRemovingOperationPreprocessorTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/HeaderRemovingOperationPreprocessorTests.java @@ -25,11 +25,11 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.restdocs.operation.OperationRequest; +import org.springframework.restdocs.operation.OperationRequestFactory; import org.springframework.restdocs.operation.OperationRequestPart; import org.springframework.restdocs.operation.OperationResponse; +import org.springframework.restdocs.operation.OperationResponseFactory; import org.springframework.restdocs.operation.Parameters; -import org.springframework.restdocs.operation.StandardOperationRequest; -import org.springframework.restdocs.operation.StandardOperationResponse; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; @@ -44,23 +44,29 @@ import static org.junit.Assert.assertThat; */ public class HeaderRemovingOperationPreprocessorTests { + private final OperationRequestFactory requestFactory = new OperationRequestFactory(); + + private final OperationResponseFactory responseFactory = new OperationResponseFactory(); + private final HeaderRemovingOperationPreprocessor preprocessor = new HeaderRemovingOperationPreprocessor( "b"); @Test public void modifyRequestHeaders() { - StandardOperationRequest request = new StandardOperationRequest( + OperationRequest request = this.requestFactory.create( URI.create("http://localhost"), HttpMethod.GET, new byte[0], getHttpHeaders(), new Parameters(), Collections.emptyList()); OperationRequest preprocessed = this.preprocessor.preprocess(request); - assertThat(preprocessed.getHeaders().size(), is(equalTo(1))); + assertThat(preprocessed.getHeaders().size(), is(equalTo(2))); assertThat(preprocessed.getHeaders(), hasEntry("a", Arrays.asList("alpha"))); + assertThat(preprocessed.getHeaders(), + hasEntry("Host", Arrays.asList("localhost"))); } @Test public void modifyResponseHeaders() { - StandardOperationResponse response = new StandardOperationResponse(HttpStatus.OK, + OperationResponse response = this.responseFactory.create(HttpStatus.OK, getHttpHeaders(), new byte[0]); OperationResponse preprocessed = this.preprocessor.preprocess(response); assertThat(preprocessed.getHeaders().size(), is(equalTo(1))); diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/test/OperationBuilder.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/test/OperationBuilder.java index 51d66504..e5be8166 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/test/OperationBuilder.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/test/OperationBuilder.java @@ -29,13 +29,13 @@ import org.springframework.http.HttpStatus; import org.springframework.restdocs.RestDocumentationContext; import org.springframework.restdocs.operation.Operation; import org.springframework.restdocs.operation.OperationRequest; +import org.springframework.restdocs.operation.OperationRequestFactory; import org.springframework.restdocs.operation.OperationRequestPart; +import org.springframework.restdocs.operation.OperationRequestPartFactory; import org.springframework.restdocs.operation.OperationResponse; +import org.springframework.restdocs.operation.OperationResponseFactory; import org.springframework.restdocs.operation.Parameters; import org.springframework.restdocs.operation.StandardOperation; -import org.springframework.restdocs.operation.StandardOperationRequest; -import org.springframework.restdocs.operation.StandardOperationRequestPart; -import org.springframework.restdocs.operation.StandardOperationResponse; import org.springframework.restdocs.snippet.RestDocumentationContextPlaceholderResolver; import org.springframework.restdocs.snippet.StandardWriterResolver; import org.springframework.restdocs.snippet.WriterResolver; @@ -122,7 +122,7 @@ public class OperationBuilder { for (OperationRequestPartBuilder builder : this.partBuilders) { parts.add(builder.buildPart()); } - return new StandardOperationRequest(this.requestUri, this.method, + return new OperationRequestFactory().create(this.requestUri, this.method, this.content, this.headers, this.parameters, parts); } @@ -196,7 +196,7 @@ public class OperationBuilder { } private OperationRequestPart buildPart() { - return new StandardOperationRequestPart(this.name, + return new OperationRequestPartFactory().create(this.name, this.submittedFileName, this.content, this.headers); } @@ -219,7 +219,8 @@ public class OperationBuilder { private byte[] content = new byte[0]; private OperationResponse buildResponse() { - return new StandardOperationResponse(this.status, this.headers, this.content); + return new OperationResponseFactory().create(this.status, this.headers, + this.content); } public OperationResponseBuilder status(int status) { diff --git a/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcOperationRequestFactory.java b/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcOperationRequestFactory.java index 417f29e8..9449354a 100644 --- a/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcOperationRequestFactory.java +++ b/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcOperationRequestFactory.java @@ -33,10 +33,10 @@ import org.springframework.http.MediaType; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockMultipartHttpServletRequest; import org.springframework.restdocs.operation.OperationRequest; +import org.springframework.restdocs.operation.OperationRequestFactory; import org.springframework.restdocs.operation.OperationRequestPart; +import org.springframework.restdocs.operation.OperationRequestPartFactory; import org.springframework.restdocs.operation.Parameters; -import org.springframework.restdocs.operation.StandardOperationRequest; -import org.springframework.restdocs.operation.StandardOperationRequestPart; import org.springframework.util.FileCopyUtils; import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; @@ -67,7 +67,7 @@ class MockMvcOperationRequestFactory { * @return the {@code OperationRequest} * @throws Exception if the request could not be created */ - public OperationRequest createOperationRequest(MockHttpServletRequest mockRequest) + OperationRequest createOperationRequest(MockHttpServletRequest mockRequest) throws Exception { HttpHeaders headers = extractHeaders(mockRequest); Parameters parameters = extractParameters(mockRequest); @@ -76,8 +76,9 @@ class MockMvcOperationRequestFactory { if (!StringUtils.hasText(queryString) && "GET".equals(mockRequest.getMethod())) { queryString = parameters.toQueryString(); } - return new StandardOperationRequest(URI.create(getRequestUri(mockRequest) - + (StringUtils.hasText(queryString) ? "?" + queryString : "")), + return new OperationRequestFactory().create( + URI.create(getRequestUri(mockRequest) + + (StringUtils.hasText(queryString) ? "?" + queryString : "")), HttpMethod.valueOf(mockRequest.getMethod()), FileCopyUtils.copyToByteArray(mockRequest.getInputStream()), headers, parameters, parts); @@ -102,16 +103,17 @@ class MockMvcOperationRequestFactory { return parts; } - private StandardOperationRequestPart createOperationRequestPart(Part part) - throws IOException { + private OperationRequestPart createOperationRequestPart(Part part) throws IOException { HttpHeaders partHeaders = extractHeaders(part); List contentTypeHeader = partHeaders.get(HttpHeaders.CONTENT_TYPE); if (part.getContentType() != null && contentTypeHeader == null) { partHeaders.setContentType(MediaType.parseMediaType(part.getContentType())); } - return new StandardOperationRequestPart(part.getName(), StringUtils.hasText(part - .getSubmittedFileName()) ? part.getSubmittedFileName() : null, - FileCopyUtils.copyToByteArray(part.getInputStream()), partHeaders); + return new OperationRequestPartFactory() + .create(part.getName(), + StringUtils.hasText(part.getSubmittedFileName()) ? part + .getSubmittedFileName() : null, FileCopyUtils + .copyToByteArray(part.getInputStream()), partHeaders); } private List extractMultipartRequestParts( @@ -126,14 +128,14 @@ class MockMvcOperationRequestFactory { return parts; } - private StandardOperationRequestPart createOperationRequestPart(MultipartFile file) + private OperationRequestPart createOperationRequestPart(MultipartFile file) throws IOException { HttpHeaders partHeaders = new HttpHeaders(); if (StringUtils.hasText(file.getContentType())) { partHeaders.setContentType(MediaType.parseMediaType(file.getContentType())); } - return new StandardOperationRequestPart(file.getName(), StringUtils.hasText(file - .getOriginalFilename()) ? file.getOriginalFilename() : null, + return new OperationRequestPartFactory().create(file.getName(), StringUtils + .hasText(file.getOriginalFilename()) ? file.getOriginalFilename() : null, file.getBytes(), partHeaders); } diff --git a/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcOperationResponseFactory.java b/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcOperationResponseFactory.java index 54915697..4e4f765f 100644 --- a/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcOperationResponseFactory.java +++ b/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcOperationResponseFactory.java @@ -20,7 +20,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.restdocs.operation.OperationResponse; -import org.springframework.restdocs.operation.StandardOperationResponse; +import org.springframework.restdocs.operation.OperationResponseFactory; /** * A factory for creating an {@link OperationResponse} derived from a @@ -36,8 +36,8 @@ class MockMvcOperationResponseFactory { * @param mockResponse the response * @return the {@code OperationResponse} */ - public OperationResponse createOperationResponse(MockHttpServletResponse mockResponse) { - return new StandardOperationResponse( + OperationResponse createOperationResponse(MockHttpServletResponse mockResponse) { + return new OperationResponseFactory().create( HttpStatus.valueOf(mockResponse.getStatus()), extractHeaders(mockResponse), mockResponse.getContentAsByteArray()); } diff --git a/spring-restdocs-mockmvc/src/test/java/org/springframework/restdocs/mockmvc/MockMvcRestDocumentationIntegrationTests.java b/spring-restdocs-mockmvc/src/test/java/org/springframework/restdocs/mockmvc/MockMvcRestDocumentationIntegrationTests.java index ad6f3453..a7422f94 100644 --- a/spring-restdocs-mockmvc/src/test/java/org/springframework/restdocs/mockmvc/MockMvcRestDocumentationIntegrationTests.java +++ b/spring-restdocs-mockmvc/src/test/java/org/springframework/restdocs/mockmvc/MockMvcRestDocumentationIntegrationTests.java @@ -269,33 +269,31 @@ public class MockMvcRestDocumentationIntegrationTests { .andDo(document("original-request")) .andDo(document( "preprocessed-request", - preprocessRequest(prettyPrint(), removeHeaders("a"), + preprocessRequest( + prettyPrint(), + removeHeaders("a", HttpHeaders.HOST, + HttpHeaders.CONTENT_LENGTH), replacePattern(pattern, "\"<>\"")))); assertThat( new File("build/generated-snippets/original-request/http-request.adoc"), is(snippet().withContents( - httpRequest(RequestMethod.GET, "/").header("Host", "localhost") - .header("a", "alpha").header("b", "bravo") + httpRequest(RequestMethod.GET, "/").header("a", "alpha") + .header("b", "bravo") .header("Content-Type", "application/json") .header("Accept", MediaType.APPLICATION_JSON_VALUE) + .header("Host", "localhost") .header("Content-Length", "13") .content("{\"a\":\"alpha\"}")))); String prettyPrinted = String.format("{%n \"a\" : \"<>\"%n}"); assertThat( new File( "build/generated-snippets/preprocessed-request/http-request.adoc"), - is(snippet() - .withContents( - httpRequest(RequestMethod.GET, "/") - .header("Host", "localhost") - .header("b", "bravo") - .header("Content-Type", "application/json") - .header("Accept", - MediaType.APPLICATION_JSON_VALUE) - .header("Content-Length", - Integer.toString(prettyPrinted.getBytes().length)) - .content(prettyPrinted)))); + is(snippet().withContents( + httpRequest(RequestMethod.GET, "/").header("b", "bravo") + .header("Content-Type", "application/json") + .header("Accept", MediaType.APPLICATION_JSON_VALUE) + .content(prettyPrinted)))); } @Test