diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/UriModifyingOperationPreprocessor.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/UriModifyingOperationPreprocessor.java
new file mode 100644
index 00000000..f2980721
--- /dev/null
+++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/UriModifyingOperationPreprocessor.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2014-2017 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.preprocess;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.springframework.http.HttpHeaders;
+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.OperationRequestPartFactory;
+import org.springframework.restdocs.operation.OperationResponse;
+import org.springframework.restdocs.operation.OperationResponseFactory;
+import org.springframework.util.StringUtils;
+import org.springframework.web.util.UriComponentsBuilder;
+
+/**
+ * An {@link OperationPreprocessor} that modifies URIs in the request and in the response
+ * by changing one or more of their host, scheme, and port. URIs in the following
+ * locations are modified:
+ *
+ * - {@link OperationRequest#getUri() Request URI}
+ *
- {@link OperationRequest#getHeaders() Request headers}
+ *
- {@link OperationRequest#getContent() Request content}
+ *
- {@link OperationRequestPart#getHeaders() Request part headers}
+ *
- {@link OperationRequestPart#getContent() Request part content}
+ *
- {@link OperationResponse#getHeaders() Response headers}
+ *
- {@link OperationResponse#getContent() Response content}
+ *
+ *
+ * @author Andy Wilkinson
+ * @since 1.2.0
+ */
+public class UriModifyingOperationPreprocessor implements OperationPreprocessor {
+
+ private final UriModifyingContentModifier contentModifier = new UriModifyingContentModifier();
+
+ private final OperationPreprocessor contentModifyingDelegate = new ContentModifyingOperationPreprocessor(
+ this.contentModifier);
+
+ private String scheme;
+
+ private String host;
+
+ private String port;
+
+ /**
+ * Modifies the URI to use the given {@code scheme}. {@code null}, the default, will
+ * leave the scheme unchanged.
+ *
+ * @param scheme the scheme
+ * @return {@code this}
+ */
+ public UriModifyingOperationPreprocessor scheme(String scheme) {
+ this.scheme = scheme;
+ this.contentModifier.setScheme(scheme);
+ return this;
+ }
+
+ /**
+ * Modifies the URI to use the given {@code host}. {@code null}, the default, will
+ * leave the host unchanged.
+ *
+ * @param host the host
+ * @return {@code this}
+ */
+ public UriModifyingOperationPreprocessor host(String host) {
+ this.host = host;
+ this.contentModifier.setHost(host);
+ return this;
+ }
+
+ /**
+ * Modifies the URI to use the given {@code port}.
+ *
+ * @param port the port
+ * @return {@code this}
+ */
+ public UriModifyingOperationPreprocessor port(int port) {
+ return port(Integer.toString(port));
+ }
+
+ /**
+ * Removes the port from the URI.
+ *
+ * @return {@code this}
+ */
+ public UriModifyingOperationPreprocessor removePort() {
+ return port("");
+ }
+
+ private UriModifyingOperationPreprocessor port(String port) {
+ this.port = port;
+ this.contentModifier.setPort(port);
+ return this;
+ }
+
+ @Override
+ public OperationRequest preprocess(OperationRequest request) {
+ UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUri(request.getUri());
+ if (this.scheme != null) {
+ uriBuilder.scheme(this.scheme);
+ }
+ if (this.host != null) {
+ uriBuilder.host(this.host);
+ }
+ if (this.port != null) {
+ if (StringUtils.hasText(this.port)) {
+ uriBuilder.port(this.port);
+ }
+ else {
+ uriBuilder.port(null);
+ }
+ }
+ URI modifiedUri = uriBuilder.build(true).toUri();
+ HttpHeaders modifiedHeaders = modify(request.getHeaders());
+ modifiedHeaders.set(HttpHeaders.HOST, modifiedUri.getHost()
+ + (modifiedUri.getPort() == -1 ? "" : ":" + modifiedUri.getPort()));
+ return this.contentModifyingDelegate.preprocess(
+ new OperationRequestFactory().create(uriBuilder.build(true).toUri(),
+ request.getMethod(), request.getContent(), modifiedHeaders,
+ request.getParameters(), modify(request.getParts())));
+ }
+
+ @Override
+ public OperationResponse preprocess(OperationResponse response) {
+ return this.contentModifyingDelegate
+ .preprocess(new OperationResponseFactory().create(response.getStatus(),
+ modify(response.getHeaders()), response.getContent()));
+ }
+
+ private HttpHeaders modify(HttpHeaders headers) {
+ HttpHeaders modified = new HttpHeaders();
+ for (Entry> header : headers.entrySet()) {
+ for (String value : header.getValue()) {
+ modified.add(header.getKey(), this.contentModifier.modify(value));
+ }
+ }
+ return modified;
+ }
+
+ private Collection modify(
+ Collection parts) {
+ List modifiedParts = new ArrayList<>();
+ OperationRequestPartFactory factory = new OperationRequestPartFactory();
+ for (OperationRequestPart part : parts) {
+ modifiedParts.add(factory.create(part.getName(), part.getSubmittedFileName(),
+ this.contentModifier.modifyContent(part.getContent(),
+ part.getHeaders().getContentType()),
+ modify(part.getHeaders())));
+ }
+ return modifiedParts;
+ }
+
+ private static final class UriModifyingContentModifier implements ContentModifier {
+
+ private static final Pattern SCHEME_HOST_PORT_PATTERN = Pattern
+ .compile("(http[s]?)://([^/:#?]+)(:[0-9]+)?");
+
+ private String scheme;
+
+ private String host;
+
+ private String port;
+
+ private void setScheme(String scheme) {
+ this.scheme = scheme;
+ }
+
+ private void setHost(String host) {
+ this.host = host;
+ }
+
+ private void setPort(String port) {
+ this.port = port;
+ }
+
+ @Override
+ public byte[] modifyContent(byte[] content, MediaType contentType) {
+ String input;
+ if (contentType != null && contentType.getCharset() != null) {
+ input = new String(content, contentType.getCharset());
+ }
+ else {
+ input = new String(content);
+ }
+
+ return modify(input).getBytes();
+ }
+
+ private String modify(String input) {
+ List replacements = Arrays.asList(this.scheme, this.host,
+ StringUtils.hasText(this.port) ? ":" + this.port : this.port);
+
+ int previous = 0;
+
+ Matcher matcher = SCHEME_HOST_PORT_PATTERN.matcher(input);
+ StringBuilder builder = new StringBuilder();
+ while (matcher.find()) {
+ for (int i = 1; i <= matcher.groupCount(); i++) {
+ if (matcher.start(i) >= 0) {
+ builder.append(input.substring(previous, matcher.start(i)));
+ }
+ if (matcher.start(i) >= 0) {
+ previous = matcher.end(i);
+ }
+ builder.append(
+ getReplacement(matcher.group(i), replacements.get(i - 1)));
+ }
+ }
+
+ if (previous < input.length()) {
+ builder.append(input.substring(previous));
+ }
+ return builder.toString();
+ }
+
+ private String getReplacement(String original, String candidate) {
+ if (candidate != null) {
+ return candidate;
+ }
+ if (original != null) {
+ return original;
+ }
+ return "";
+ }
+
+ }
+
+}
diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/UriModifyingOperationPreprocessorTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/UriModifyingOperationPreprocessorTests.java
new file mode 100644
index 00000000..f861c1f7
--- /dev/null
+++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/UriModifyingOperationPreprocessorTests.java
@@ -0,0 +1,373 @@
+/*
+ * Copyright 2014-2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.restdocs.operation.preprocess;
+
+import java.net.URI;
+import java.util.Arrays;
+import java.util.Collections;
+
+import org.junit.Test;
+
+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.OperationRequestPartFactory;
+import org.springframework.restdocs.operation.OperationResponse;
+import org.springframework.restdocs.operation.OperationResponseFactory;
+import org.springframework.restdocs.operation.Parameters;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Tests for {@link UriModifyingOperationPreprocessor}.
+ *
+ * @author Andy Wilkinson
+ */
+public class UriModifyingOperationPreprocessorTests {
+
+ private final OperationRequestFactory requestFactory = new OperationRequestFactory();
+
+ private final OperationResponseFactory responseFactory = new OperationResponseFactory();
+
+ private final UriModifyingOperationPreprocessor preprocessor = new UriModifyingOperationPreprocessor();
+
+ @Test
+ public void requestUriSchemeCanBeModified() {
+ this.preprocessor.scheme("https");
+ OperationRequest processed = this.preprocessor
+ .preprocess(createRequestWithUri("http://localhost:12345"));
+ assertThat(processed.getUri(),
+ is(equalTo(URI.create("https://localhost:12345"))));
+ }
+
+ @Test
+ public void requestUriHostCanBeModified() {
+ this.preprocessor.host("api.example.com");
+ OperationRequest processed = this.preprocessor
+ .preprocess(createRequestWithUri("http://api.foo.com:12345"));
+ assertThat(processed.getUri(),
+ is(equalTo(URI.create("http://api.example.com:12345"))));
+ assertThat(processed.getHeaders().getFirst(HttpHeaders.HOST),
+ is(equalTo("api.example.com:12345")));
+ }
+
+ @Test
+ public void requestUriPortCanBeModified() {
+ this.preprocessor.port(23456);
+ OperationRequest processed = this.preprocessor
+ .preprocess(createRequestWithUri("http://api.example.com:12345"));
+ assertThat(processed.getUri(),
+ is(equalTo(URI.create("http://api.example.com:23456"))));
+ assertThat(processed.getHeaders().getFirst(HttpHeaders.HOST),
+ is(equalTo("api.example.com:23456")));
+ }
+
+ @Test
+ public void requestUriPortCanBeRemoved() {
+ this.preprocessor.removePort();
+ OperationRequest processed = this.preprocessor
+ .preprocess(createRequestWithUri("http://api.example.com:12345"));
+ assertThat(processed.getUri(), is(equalTo(URI.create("http://api.example.com"))));
+ assertThat(processed.getHeaders().getFirst(HttpHeaders.HOST),
+ is(equalTo("api.example.com")));
+ }
+
+ @Test
+ public void requestUriPathIsPreserved() {
+ this.preprocessor.removePort();
+ OperationRequest processed = this.preprocessor
+ .preprocess(createRequestWithUri("http://api.example.com:12345/foo/bar"));
+ assertThat(processed.getUri(),
+ is(equalTo(URI.create("http://api.example.com/foo/bar"))));
+ }
+
+ @Test
+ public void requestUriQueryIsPreserved() {
+ this.preprocessor.removePort();
+ OperationRequest processed = this.preprocessor
+ .preprocess(createRequestWithUri("http://api.example.com:12345?foo=bar"));
+ assertThat(processed.getUri(),
+ is(equalTo(URI.create("http://api.example.com?foo=bar"))));
+ }
+
+ @Test
+ public void requestUriAnchorIsPreserved() {
+ this.preprocessor.removePort();
+ OperationRequest processed = this.preprocessor
+ .preprocess(createRequestWithUri("http://api.example.com:12345#foo"));
+ assertThat(processed.getUri(),
+ is(equalTo(URI.create("http://api.example.com#foo"))));
+ }
+
+ @Test
+ public void requestContentUriSchemeCanBeModified() {
+ this.preprocessor.scheme("https");
+ OperationRequest processed = this.preprocessor
+ .preprocess(createRequestWithContent(
+ "The uri 'http://localhost:12345' should be used"));
+ assertThat(new String(processed.getContent()),
+ is(equalTo("The uri 'https://localhost:12345' should be used")));
+ }
+
+ @Test
+ public void requestContentUriHostCanBeModified() {
+ this.preprocessor.host("api.example.com");
+ OperationRequest processed = this.preprocessor
+ .preprocess(createRequestWithContent(
+ "The uri 'http://localhost:12345' should be used"));
+ assertThat(new String(processed.getContent()),
+ is(equalTo("The uri 'http://api.example.com:12345' should be used")));
+ }
+
+ @Test
+ public void requestContentUriPortCanBeModified() {
+ this.preprocessor.port(23456);
+ OperationRequest processed = this.preprocessor
+ .preprocess(createRequestWithContent(
+ "The uri 'http://localhost:12345' should be used"));
+ assertThat(new String(processed.getContent()),
+ is(equalTo("The uri 'http://localhost:23456' should be used")));
+ }
+
+ @Test
+ public void requestContentUriPortCanBeRemoved() {
+ this.preprocessor.removePort();
+ OperationRequest processed = this.preprocessor
+ .preprocess(createRequestWithContent(
+ "The uri 'http://localhost:12345' should be used"));
+ assertThat(new String(processed.getContent()),
+ is(equalTo("The uri 'http://localhost' should be used")));
+ }
+
+ @Test
+ public void multipleRequestContentUrisCanBeModified() {
+ this.preprocessor.removePort();
+ OperationRequest processed = this.preprocessor
+ .preprocess(createRequestWithContent(
+ "Use 'http://localhost:12345' or 'https://localhost:23456' to access the service"));
+ assertThat(new String(processed.getContent()), is(equalTo(
+ "Use 'http://localhost' or 'https://localhost' to access the service")));
+ }
+
+ @Test
+ public void requestContentUriPathIsPreserved() {
+ this.preprocessor.removePort();
+ OperationRequest processed = this.preprocessor
+ .preprocess(createRequestWithContent(
+ "The uri 'http://localhost:12345/foo/bar' should be used"));
+ assertThat(new String(processed.getContent()),
+ is(equalTo("The uri 'http://localhost/foo/bar' should be used")));
+ }
+
+ @Test
+ public void requestContentUriQueryIsPreserved() {
+ this.preprocessor.removePort();
+ OperationRequest processed = this.preprocessor
+ .preprocess(createRequestWithContent(
+ "The uri 'http://localhost:12345?foo=bar' should be used"));
+ assertThat(new String(processed.getContent()),
+ is(equalTo("The uri 'http://localhost?foo=bar' should be used")));
+ }
+
+ @Test
+ public void requestContentUriAnchorIsPreserved() {
+ this.preprocessor.removePort();
+ OperationRequest processed = this.preprocessor
+ .preprocess(createRequestWithContent(
+ "The uri 'http://localhost:12345#foo' should be used"));
+ assertThat(new String(processed.getContent()),
+ is(equalTo("The uri 'http://localhost#foo' should be used")));
+ }
+
+ @Test
+ public void responseContentUriSchemeCanBeModified() {
+ this.preprocessor.scheme("https");
+ OperationResponse processed = this.preprocessor
+ .preprocess(createResponseWithContent(
+ "The uri 'http://localhost:12345' should be used"));
+ assertThat(new String(processed.getContent()),
+ is(equalTo("The uri 'https://localhost:12345' should be used")));
+ }
+
+ @Test
+ public void responseContentUriHostCanBeModified() {
+ this.preprocessor.host("api.example.com");
+ OperationResponse processed = this.preprocessor
+ .preprocess(createResponseWithContent(
+ "The uri 'http://localhost:12345' should be used"));
+ assertThat(new String(processed.getContent()),
+ is(equalTo("The uri 'http://api.example.com:12345' should be used")));
+ }
+
+ @Test
+ public void responseContentUriPortCanBeModified() {
+ this.preprocessor.port(23456);
+ OperationResponse processed = this.preprocessor
+ .preprocess(createResponseWithContent(
+ "The uri 'http://localhost:12345' should be used"));
+ assertThat(new String(processed.getContent()),
+ is(equalTo("The uri 'http://localhost:23456' should be used")));
+ }
+
+ @Test
+ public void responseContentUriPortCanBeRemoved() {
+ this.preprocessor.removePort();
+ OperationResponse processed = this.preprocessor
+ .preprocess(createResponseWithContent(
+ "The uri 'http://localhost:12345' should be used"));
+ assertThat(new String(processed.getContent()),
+ is(equalTo("The uri 'http://localhost' should be used")));
+ }
+
+ @Test
+ public void multipleResponseContentUrisCanBeModified() {
+ this.preprocessor.removePort();
+ OperationResponse processed = this.preprocessor
+ .preprocess(createResponseWithContent(
+ "Use 'http://localhost:12345' or 'https://localhost:23456' to access the service"));
+ assertThat(new String(processed.getContent()), is(equalTo(
+ "Use 'http://localhost' or 'https://localhost' to access the service")));
+ }
+
+ @Test
+ public void responseContentUriPathIsPreserved() {
+ this.preprocessor.removePort();
+ OperationResponse processed = this.preprocessor
+ .preprocess(createResponseWithContent(
+ "The uri 'http://localhost:12345/foo/bar' should be used"));
+ assertThat(new String(processed.getContent()),
+ is(equalTo("The uri 'http://localhost/foo/bar' should be used")));
+ }
+
+ @Test
+ public void responseContentUriQueryIsPreserved() {
+ this.preprocessor.removePort();
+ OperationResponse processed = this.preprocessor
+ .preprocess(createResponseWithContent(
+ "The uri 'http://localhost:12345?foo=bar' should be used"));
+ assertThat(new String(processed.getContent()),
+ is(equalTo("The uri 'http://localhost?foo=bar' should be used")));
+ }
+
+ @Test
+ public void responseContentUriAnchorIsPreserved() {
+ this.preprocessor.removePort();
+ OperationResponse processed = this.preprocessor
+ .preprocess(createResponseWithContent(
+ "The uri 'http://localhost:12345#foo' should be used"));
+ assertThat(new String(processed.getContent()),
+ is(equalTo("The uri 'http://localhost#foo' should be used")));
+ }
+
+ @Test
+ public void urisInRequestHeadersCanBeModified() {
+ OperationRequest processed = this.preprocessor.host("api.example.com")
+ .preprocess(createRequestWithHeader("Foo", "http://locahost:12345"));
+ assertThat(processed.getHeaders().getFirst("Foo"),
+ is(equalTo("http://api.example.com:12345")));
+ assertThat(processed.getHeaders().getFirst("Host"),
+ is(equalTo("api.example.com")));
+ }
+
+ @Test
+ public void urisInResponseHeadersCanBeModified() {
+ OperationResponse processed = this.preprocessor.host("api.example.com")
+ .preprocess(createResponseWithHeader("Foo", "http://locahost:12345"));
+ assertThat(processed.getHeaders().getFirst("Foo"),
+ is(equalTo("http://api.example.com:12345")));
+ }
+
+ @Test
+ public void urisInRequestPartHeadersCanBeModified() {
+ OperationRequest processed = this.preprocessor.host("api.example.com").preprocess(
+ createRequestWithPartWithHeader("Foo", "http://locahost:12345"));
+ assertThat(processed.getParts().iterator().next().getHeaders().getFirst("Foo"),
+ is(equalTo("http://api.example.com:12345")));
+ }
+
+ @Test
+ public void urisInRequestPartContentCanBeModified() {
+ OperationRequest processed = this.preprocessor.host("api.example.com")
+ .preprocess(createRequestWithPartWithContent(
+ "The uri 'http://localhost:12345' should be used"));
+ assertThat(new String(processed.getParts().iterator().next().getContent()),
+ is(equalTo("The uri 'http://api.example.com:12345' should be used")));
+ }
+
+ @Test
+ public void modifiedUriDoesNotGetDoubleEncoded() {
+ this.preprocessor.scheme("https");
+ OperationRequest processed = this.preprocessor
+ .preprocess(createRequestWithUri("http://localhost:12345?foo=%7B%7D"));
+ assertThat(processed.getUri(),
+ is(equalTo(URI.create("https://localhost:12345?foo=%7B%7D"))));
+
+ }
+
+ private OperationRequest createRequestWithUri(String uri) {
+ return this.requestFactory.create(URI.create(uri), HttpMethod.GET, new byte[0],
+ new HttpHeaders(), new Parameters(),
+ Collections.emptyList());
+ }
+
+ private OperationRequest createRequestWithContent(String content) {
+ return this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET,
+ content.getBytes(), new HttpHeaders(), new Parameters(),
+ Collections.emptyList());
+ }
+
+ private OperationRequest createRequestWithHeader(String name, String value) {
+ HttpHeaders headers = new HttpHeaders();
+ headers.add(name, value);
+ return this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET,
+ new byte[0], headers, new Parameters(),
+ Collections.emptyList());
+ }
+
+ private OperationRequest createRequestWithPartWithHeader(String name, String value) {
+ HttpHeaders headers = new HttpHeaders();
+ headers.add(name, value);
+ return this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET,
+ new byte[0], new HttpHeaders(), new Parameters(),
+ Arrays.asList(new OperationRequestPartFactory().create("part", "fileName",
+ new byte[0], headers)));
+ }
+
+ private OperationRequest createRequestWithPartWithContent(String content) {
+ return this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET,
+ new byte[0], new HttpHeaders(), new Parameters(),
+ Arrays.asList(new OperationRequestPartFactory().create("part", "fileName",
+ content.getBytes(), new HttpHeaders())));
+ }
+
+ private OperationResponse createResponseWithContent(String content) {
+ return this.responseFactory.create(HttpStatus.OK, new HttpHeaders(),
+ content.getBytes());
+ }
+
+ private OperationResponse createResponseWithHeader(String name, String value) {
+ HttpHeaders headers = new HttpHeaders();
+ headers.add(name, value);
+ return this.responseFactory.create(HttpStatus.OK, headers, new byte[0]);
+ }
+
+}
diff --git a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/operation/preprocess/RestAssuredPreprocessors.java b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/operation/preprocess/RestAssuredPreprocessors.java
index 2deb20cc..8d94649f 100644
--- a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/operation/preprocess/RestAssuredPreprocessors.java
+++ b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/operation/preprocess/RestAssuredPreprocessors.java
@@ -19,6 +19,7 @@ package org.springframework.restdocs.restassured3.operation.preprocess;
import org.springframework.restdocs.operation.Operation;
import org.springframework.restdocs.operation.OperationRequest;
import org.springframework.restdocs.operation.OperationResponse;
+import org.springframework.restdocs.operation.preprocess.UriModifyingOperationPreprocessor;
/**
* Static factory methods for creating
diff --git a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/operation/preprocess/UriModifyingOperationPreprocessor.java b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/operation/preprocess/UriModifyingOperationPreprocessor.java
index 6d3d510d..25c69714 100644
--- a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/operation/preprocess/UriModifyingOperationPreprocessor.java
+++ b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/operation/preprocess/UriModifyingOperationPreprocessor.java
@@ -16,28 +16,10 @@
package org.springframework.restdocs.restassured3.operation.preprocess;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map.Entry;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.springframework.http.HttpHeaders;
-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.OperationRequestPartFactory;
import org.springframework.restdocs.operation.OperationResponse;
-import org.springframework.restdocs.operation.OperationResponseFactory;
-import org.springframework.restdocs.operation.preprocess.ContentModifier;
-import org.springframework.restdocs.operation.preprocess.ContentModifyingOperationPreprocessor;
import org.springframework.restdocs.operation.preprocess.OperationPreprocessor;
-import org.springframework.util.StringUtils;
-import org.springframework.web.util.UriComponentsBuilder;
/**
* An {@link OperationPreprocessor} that modifies URIs in the request and in the response
@@ -55,201 +37,9 @@ import org.springframework.web.util.UriComponentsBuilder;
*
* @author Andy Wilkinson
* @since 1.2.0
+ * @deprecated use {@link org.springframework.restdocs.operation.preprocess.UriModifyingOperationPreprocessor} instead
*/
-public final class UriModifyingOperationPreprocessor implements OperationPreprocessor {
-
- private final UriModifyingContentModifier contentModifier = new UriModifyingContentModifier();
-
- private final OperationPreprocessor contentModifyingDelegate = new ContentModifyingOperationPreprocessor(
- this.contentModifier);
-
- private String scheme;
-
- private String host;
-
- private String port;
-
- /**
- * Modifies the URI to use the given {@code scheme}. {@code null}, the default, will
- * leave the scheme unchanged.
- *
- * @param scheme the scheme
- * @return {@code this}
- */
- public UriModifyingOperationPreprocessor scheme(String scheme) {
- this.scheme = scheme;
- this.contentModifier.setScheme(scheme);
- return this;
- }
-
- /**
- * Modifies the URI to use the given {@code host}. {@code null}, the default, will
- * leave the host unchanged.
- *
- * @param host the host
- * @return {@code this}
- */
- public UriModifyingOperationPreprocessor host(String host) {
- this.host = host;
- this.contentModifier.setHost(host);
- return this;
- }
-
- /**
- * Modifies the URI to use the given {@code port}.
- *
- * @param port the port
- * @return {@code this}
- */
- public UriModifyingOperationPreprocessor port(int port) {
- return port(Integer.toString(port));
- }
-
- /**
- * Removes the port from the URI.
- *
- * @return {@code this}
- */
- public UriModifyingOperationPreprocessor removePort() {
- return port("");
- }
-
- private UriModifyingOperationPreprocessor port(String port) {
- this.port = port;
- this.contentModifier.setPort(port);
- return this;
- }
-
- @Override
- public OperationRequest preprocess(OperationRequest request) {
- UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUri(request.getUri());
- if (this.scheme != null) {
- uriBuilder.scheme(this.scheme);
- }
- if (this.host != null) {
- uriBuilder.host(this.host);
- }
- if (this.port != null) {
- if (StringUtils.hasText(this.port)) {
- uriBuilder.port(this.port);
- }
- else {
- uriBuilder.port(null);
- }
- }
- URI modifiedUri = uriBuilder.build(true).toUri();
- HttpHeaders modifiedHeaders = modify(request.getHeaders());
- modifiedHeaders.set(HttpHeaders.HOST, modifiedUri.getHost()
- + (modifiedUri.getPort() == -1 ? "" : ":" + modifiedUri.getPort()));
- return this.contentModifyingDelegate.preprocess(
- new OperationRequestFactory().create(uriBuilder.build(true).toUri(),
- request.getMethod(), request.getContent(), modifiedHeaders,
- request.getParameters(), modify(request.getParts())));
- }
-
- @Override
- public OperationResponse preprocess(OperationResponse response) {
- return this.contentModifyingDelegate
- .preprocess(new OperationResponseFactory().create(response.getStatus(),
- modify(response.getHeaders()), response.getContent()));
- }
-
- private HttpHeaders modify(HttpHeaders headers) {
- HttpHeaders modified = new HttpHeaders();
- for (Entry> header : headers.entrySet()) {
- for (String value : header.getValue()) {
- modified.add(header.getKey(), this.contentModifier.modify(value));
- }
- }
- return modified;
- }
-
- private Collection modify(
- Collection parts) {
- List modifiedParts = new ArrayList<>();
- OperationRequestPartFactory factory = new OperationRequestPartFactory();
- for (OperationRequestPart part : parts) {
- modifiedParts.add(factory.create(part.getName(), part.getSubmittedFileName(),
- this.contentModifier.modifyContent(part.getContent(),
- part.getHeaders().getContentType()),
- modify(part.getHeaders())));
- }
- return modifiedParts;
- }
-
- private static final class UriModifyingContentModifier implements ContentModifier {
-
- private static final Pattern SCHEME_HOST_PORT_PATTERN = Pattern
- .compile("(http[s]?)://([^/:#?]+)(:[0-9]+)?");
-
- private String scheme;
-
- private String host;
-
- private String port;
-
- private void setScheme(String scheme) {
- this.scheme = scheme;
- }
-
- private void setHost(String host) {
- this.host = host;
- }
-
- private void setPort(String port) {
- this.port = port;
- }
-
- @Override
- public byte[] modifyContent(byte[] content, MediaType contentType) {
- String input;
- if (contentType != null && contentType.getCharset() != null) {
- input = new String(content, contentType.getCharset());
- }
- else {
- input = new String(content);
- }
-
- return modify(input).getBytes();
- }
-
- private String modify(String input) {
- List replacements = Arrays.asList(this.scheme, this.host,
- StringUtils.hasText(this.port) ? ":" + this.port : this.port);
-
- int previous = 0;
-
- Matcher matcher = SCHEME_HOST_PORT_PATTERN.matcher(input);
- StringBuilder builder = new StringBuilder();
- while (matcher.find()) {
- for (int i = 1; i <= matcher.groupCount(); i++) {
- if (matcher.start(i) >= 0) {
- builder.append(input.substring(previous, matcher.start(i)));
- }
- if (matcher.start(i) >= 0) {
- previous = matcher.end(i);
- }
- builder.append(
- getReplacement(matcher.group(i), replacements.get(i - 1)));
- }
- }
-
- if (previous < input.length()) {
- builder.append(input.substring(previous));
- }
- return builder.toString();
- }
-
- private String getReplacement(String original, String candidate) {
- if (candidate != null) {
- return candidate;
- }
- if (original != null) {
- return original;
- }
- return "";
- }
-
- }
+@Deprecated
+public class UriModifyingOperationPreprocessor extends org.springframework.restdocs.operation.preprocess.UriModifyingOperationPreprocessor {
}
diff --git a/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/operation/preprocess/UriModifyingOperationPreprocessorTests.java b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/operation/preprocess/UriModifyingOperationPreprocessorTests.java
index 7f262e9f..e55a98a6 100644
--- a/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/operation/preprocess/UriModifyingOperationPreprocessorTests.java
+++ b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/operation/preprocess/UriModifyingOperationPreprocessorTests.java
@@ -41,7 +41,9 @@ import static org.junit.Assert.assertThat;
* Tests for {@link UriModifyingOperationPreprocessor}.
*
* @author Andy Wilkinson
+ * @deprecated use {@link org.springframework.restdocs.operation.preprocess.UriModifyingOperationPreprocessorTests} instead
*/
+@Deprecated
public class UriModifyingOperationPreprocessorTests {
private final OperationRequestFactory requestFactory = new OperationRequestFactory();