Merge pull request #493 from Joe McCall
* gh-493: Polish "Move UriModifyingOperationPreprocessor to core project" Move UriModifyingOperationPreprocessor to core project
This commit is contained in:
@@ -143,12 +143,13 @@ parameters.
|
||||
[[customizing-requests-and-responses-preprocessors-modify-uris]]
|
||||
==== Modifying URIs
|
||||
|
||||
TIP: If you are using MockMvc or WebTestclient, URIs should be customized by
|
||||
<<configuration-uris, changing the configuration>>.
|
||||
TIP: If you are using MockMvc or a WebTestClient that is not bound to a server,
|
||||
URIs should be customized by <<configuration-uris, changing the configuration>>.
|
||||
|
||||
`modifyUris` on `RestAssuredPreprocessors` can be used to modify any URIs in a request
|
||||
or a response. When using REST Assured, this allows you to customize the URIs that appear
|
||||
in the documentation while testing a local instance of the service.
|
||||
`modifyUris` on `Preprocessors` can be used to modify any URIs in a request
|
||||
or a response. When using REST Assured or WebTestClient bound to a server, this
|
||||
allows you to customize the URIs that appear in the documentation while testing a
|
||||
local instance of the service.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2018 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.
|
||||
@@ -151,4 +151,15 @@ public final class Preprocessors {
|
||||
return new ParametersModifyingOperationPreprocessor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@code UriModifyingOperationPreprocessor} that will modify URIs in the
|
||||
* request or response by changing one or more of their host, scheme, and port.
|
||||
*
|
||||
* @return the preprocessor
|
||||
* @since 2.0.1
|
||||
*/
|
||||
public static UriModifyingOperationPreprocessor modifyUris() {
|
||||
return new UriModifyingOperationPreprocessor();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,252 @@
|
||||
/*
|
||||
* Copyright 2014-2018 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:
|
||||
* <ul>
|
||||
* <li>{@link OperationRequest#getUri() Request URI}
|
||||
* <li>{@link OperationRequest#getHeaders() Request headers}
|
||||
* <li>{@link OperationRequest#getContent() Request content}
|
||||
* <li>{@link OperationRequestPart#getHeaders() Request part headers}
|
||||
* <li>{@link OperationRequestPart#getContent() Request part content}
|
||||
* <li>{@link OperationResponse#getHeaders() Response headers}
|
||||
* <li>{@link OperationResponse#getContent() Response content}
|
||||
* </ul>
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @since 2.0.1
|
||||
*/
|
||||
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<String, List<String>> header : headers.entrySet()) {
|
||||
for (String value : header.getValue()) {
|
||||
modified.add(header.getKey(), this.contentModifier.modify(value));
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
private Collection<OperationRequestPart> modify(
|
||||
Collection<OperationRequestPart> parts) {
|
||||
List<OperationRequestPart> 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<String> 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 "";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,373 @@
|
||||
/*
|
||||
* Copyright 2014-2018 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.<OperationRequestPart>emptyList());
|
||||
}
|
||||
|
||||
private OperationRequest createRequestWithContent(String content) {
|
||||
return this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET,
|
||||
content.getBytes(), new HttpHeaders(), new Parameters(),
|
||||
Collections.<OperationRequestPart>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.<OperationRequestPart>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]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 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.
|
||||
@@ -19,6 +19,8 @@ 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.Preprocessors;
|
||||
import org.springframework.restdocs.operation.preprocess.UriModifyingOperationPreprocessor;
|
||||
|
||||
/**
|
||||
* Static factory methods for creating
|
||||
@@ -29,7 +31,10 @@ import org.springframework.restdocs.operation.OperationResponse;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @since 1.1.0
|
||||
* @deprecated since 2.0.1 in favor of {@link Preprocessors} and, specifically,
|
||||
* {@link Preprocessors#modifyUris()}
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class RestAssuredPreprocessors {
|
||||
|
||||
private RestAssuredPreprocessors() {
|
||||
@@ -41,7 +46,9 @@ public abstract class RestAssuredPreprocessors {
|
||||
* request or response by changing one or more of their host, scheme, and port.
|
||||
*
|
||||
* @return the preprocessor
|
||||
* @deprecated since 2.0.1 in favor of {@link Preprocessors#modifyUris()}
|
||||
*/
|
||||
@Deprecated
|
||||
public static UriModifyingOperationPreprocessor modifyUris() {
|
||||
return new UriModifyingOperationPreprocessor();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 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.
|
||||
@@ -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,11 @@ import org.springframework.web.util.UriComponentsBuilder;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @since 1.2.0
|
||||
* @deprecated since 2.0.1 in favor of
|
||||
* {@link org.springframework.restdocs.operation.preprocess.UriModifyingOperationPreprocessor}
|
||||
*/
|
||||
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<String, List<String>> header : headers.entrySet()) {
|
||||
for (String value : header.getValue()) {
|
||||
modified.add(header.getKey(), this.contentModifier.modify(value));
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
private Collection<OperationRequestPart> modify(
|
||||
Collection<OperationRequestPart> parts) {
|
||||
List<OperationRequestPart> 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<String> 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 {
|
||||
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ import static org.springframework.restdocs.headers.HeaderDocumentation.responseH
|
||||
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
|
||||
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.links;
|
||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.maskLinks;
|
||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.modifyUris;
|
||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest;
|
||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse;
|
||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
|
||||
@@ -59,7 +60,6 @@ import static org.springframework.restdocs.request.RequestDocumentation.requestP
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.requestParts;
|
||||
import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document;
|
||||
import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.documentationConfiguration;
|
||||
import static org.springframework.restdocs.restassured3.operation.preprocess.RestAssuredPreprocessors.modifyUris;
|
||||
import static org.springframework.restdocs.templates.TemplateFormats.asciidoctor;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.codeBlock;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.httpRequest;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2018 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.
|
||||
@@ -42,6 +42,7 @@ import static org.junit.Assert.assertThat;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@Deprecated
|
||||
public class UriModifyingOperationPreprocessorTests {
|
||||
|
||||
private final OperationRequestFactory requestFactory = new OperationRequestFactory();
|
||||
|
||||
Reference in New Issue
Block a user