Bumped WireMock to 2.25.0
fixes gh-1230 fixes gh-1231
This commit is contained in:
3
pom.xml
3
pom.xml
@@ -57,7 +57,8 @@
|
||||
<groovy.version>2.5.8</groovy.version>
|
||||
<!-- We need to have compatibility with Boot -->
|
||||
<maven.version>3.5.4</maven.version>
|
||||
<maven.resolver.version>1.4.1</maven.resolver.version>
|
||||
<!-- Resolver has to be aligned with Maven (e.g resolver 1.4 and Maven 3.6 or resolver 1.3 and Maven 3.5) -->
|
||||
<maven.resolver.version>1.3.3</maven.resolver.version>
|
||||
<xpath2.processor.version>2.1.100</xpath2.processor.version>
|
||||
<xerces.version>2.11.0</xerces.version>
|
||||
<jacoco-maven-plugin.version>0.8.4</jacoco-maven-plugin.version>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<name>spring-cloud-contract-dependencies</name>
|
||||
<description>Spring Cloud Contract Dependencies</description>
|
||||
<properties>
|
||||
<wiremock.version>2.24.1</wiremock.version>
|
||||
<wiremock.version>2.25.0</wiremock.version>
|
||||
<jsonassert.version>0.4.13</jsonassert.version>
|
||||
<rest-assured.version>4.0.0</rest-assured.version>
|
||||
</properties>
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -30,7 +31,6 @@ import java.util.Set;
|
||||
import groovy.json.JsonOutput;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import wiremock.org.eclipse.jetty.util.ConcurrentHashSet;
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract;
|
||||
import org.springframework.cloud.contract.spec.internal.DslProperty;
|
||||
@@ -47,7 +47,8 @@ import org.springframework.cloud.contract.verifier.util.BodyExtractor;
|
||||
*/
|
||||
class StubRunnerExecutor implements StubFinder {
|
||||
|
||||
static final Set<StubServer> STUB_SERVERS = new ConcurrentHashSet<>();
|
||||
static final Set<StubServer> STUB_SERVERS = Collections
|
||||
.synchronizedSet(new HashSet<>());
|
||||
|
||||
private static final Log log = LogFactory.getLog(StubRunnerExecutor.class);
|
||||
|
||||
|
||||
@@ -22,6 +22,10 @@
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-contract-spec</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-contract-shade</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-contract-verifier</artifactId>
|
||||
|
||||
@@ -33,7 +33,6 @@ import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import wiremock.com.google.common.collect.ListMultimap;
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract;
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties;
|
||||
@@ -42,6 +41,7 @@ import org.springframework.cloud.contract.verifier.file.ContractFileScannerBuild
|
||||
import org.springframework.cloud.contract.verifier.file.ContractMetadata;
|
||||
import org.springframework.cloud.contract.verifier.util.NamesUtil;
|
||||
import org.springframework.cloud.contract.verifier.wiremock.DslToWireMockClientConverter;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -117,12 +117,12 @@ public class RecursiveFilesConverter {
|
||||
.baseDir(contractsDslDir).excluded(new HashSet<>(excludedFiles))
|
||||
.ignored(new HashSet<>()).included(new HashSet<>())
|
||||
.includeMatcher(includedContracts).build();
|
||||
ListMultimap<Path, ContractMetadata> contracts = scanner.findContracts();
|
||||
MultiValueMap<Path, ContractMetadata> contracts = scanner
|
||||
.findContractsRecursively();
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Found the following contracts " + contracts);
|
||||
}
|
||||
for (Map.Entry<Path, Collection<ContractMetadata>> entry : contracts.asMap()
|
||||
.entrySet()) {
|
||||
for (Map.Entry<Path, List<ContractMetadata>> entry : contracts.entrySet()) {
|
||||
for (ContractMetadata contract : entry.getValue()) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Will create a stub for contract [" + contract + "]");
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
wiremockVersion=2.24.1
|
||||
wiremockVersion=2.25.0
|
||||
jsonAssertVersion=0.4.13
|
||||
verifierVersion=2.2.0.BUILD-SNAPSHOT
|
||||
groovyVersion=2.4.17
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
wiremockVersion=2.24.1
|
||||
wiremockVersion=2.25.0
|
||||
jsonAssertVersion=0.4.13
|
||||
verifierVersion=2.2.0.BUILD-SNAPSHOT
|
||||
bootVersion=2.2.0.BUILD-SNAPSHOT
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
wiremockVersion=2.24.1
|
||||
wiremockVersion=2.25.0
|
||||
jsonAssertVersion=0.4.13
|
||||
verifierVersion=2.2.0.BUILD-SNAPSHOT
|
||||
bootVersion=2.2.0.BUILD-SNAPSHOT
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-contract-spec</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-contract-shade</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-test-autoconfigure</artifactId>
|
||||
|
||||
@@ -20,11 +20,11 @@ import java.nio.charset.StandardCharsets
|
||||
import java.nio.file.Path
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
import groovy.transform.CompileDynamic
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.PackageScope
|
||||
import org.apache.commons.logging.Log
|
||||
import org.apache.commons.logging.LogFactory
|
||||
import wiremock.com.google.common.collect.ListMultimap
|
||||
|
||||
import org.springframework.cloud.contract.spec.ContractVerifierException
|
||||
import org.springframework.cloud.contract.verifier.builder.JavaTestGenerator
|
||||
@@ -35,6 +35,7 @@ import org.springframework.cloud.contract.verifier.file.ContractFileScannerBuild
|
||||
import org.springframework.cloud.contract.verifier.file.ContractMetadata
|
||||
import org.springframework.cloud.contract.verifier.util.NamesUtil
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader
|
||||
import org.springframework.util.MultiValueMap
|
||||
import org.springframework.util.StringUtils
|
||||
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.afterLast
|
||||
@@ -121,31 +122,38 @@ class TestGenerator {
|
||||
|
||||
@PackageScope
|
||||
void generateTestClasses(final String basePackageName) {
|
||||
ListMultimap<Path, ContractMetadata> contracts = contractFileScanner.
|
||||
findContracts()
|
||||
MultiValueMap<Path, ContractMetadata> contracts = contractFileScanner.
|
||||
findContractsRecursively()
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Found the following contracts " + contracts.keySet())
|
||||
}
|
||||
Set<Map.Entry<Path,Collection<ContractMetadata>>> inProgress = contracts.asMap().entrySet()
|
||||
.findAll { Map.Entry<Path, Collection<ContractMetadata>> entry -> entry.value.any { it.anyInProgress() }}
|
||||
Set<Map.Entry<Path,List<ContractMetadata>>> inProgress = inProgress(contracts)
|
||||
if (!inProgress.isEmpty() && configProperties.failOnInProgress) {
|
||||
throw new IllegalStateException("In progress contracts found in paths [" + inProgress.collect { it.key.toString() }.join(",") + "] and the switch [failOnInProgress] is set to [true]. Either unmark those contracts as in progress, or set the switch to [false].")
|
||||
}
|
||||
processAllNotInProgress(contracts,basePackageName)
|
||||
}
|
||||
|
||||
@PackageScope Set<Map.Entry<Path,Collection<ContractMetadata>>> processAllNotInProgress(ListMultimap<Path,ContractMetadata> contracts, String basePackageName) {
|
||||
contracts.asMap().entrySet()
|
||||
.findAll { Map.Entry<Path, Collection<ContractMetadata>> entry -> !entry.value.any { it.anyInProgress() }}
|
||||
@CompileDynamic
|
||||
private Set<Map.Entry<Path,List<ContractMetadata>>> inProgress(MultiValueMap<Path,ContractMetadata> contracts) {
|
||||
return contracts.entrySet()
|
||||
.findAll { Map.Entry<Path, List<ContractMetadata>> entry -> entry.getValue().any { it.anyInProgress() }}
|
||||
}
|
||||
|
||||
@PackageScope
|
||||
@CompileDynamic
|
||||
Set<Map.Entry<Path,List<ContractMetadata>>> processAllNotInProgress(MultiValueMap<Path,ContractMetadata> contracts, String basePackageName) {
|
||||
contracts.entrySet()
|
||||
.findAll { Map.Entry<Path, List<ContractMetadata>> entry -> !entry.value.any { it.anyInProgress() }}
|
||||
.each {
|
||||
Map.Entry<Path, Collection<ContractMetadata>> entry ->
|
||||
Map.Entry<Path, List<ContractMetadata>> entry ->
|
||||
processIncludedDirectory(
|
||||
relativizeContractPath(entry), (Collection<ContractMetadata>) entry.
|
||||
getValue(), basePackageName)
|
||||
}
|
||||
}
|
||||
|
||||
private String relativizeContractPath(Map.Entry<Path, Collection<ContractMetadata>> entry) {
|
||||
private String relativizeContractPath(Map.Entry<Path, List<ContractMetadata>> entry) {
|
||||
Path relativePath = configProperties.contractsDslDir.toPath().
|
||||
relativize(entry.getKey())
|
||||
if (StringUtils.isEmpty(relativePath.toString())) {
|
||||
|
||||
@@ -40,6 +40,6 @@ public enum TestMode {
|
||||
/**
|
||||
* Uses Spring's reactive WebTestClient.
|
||||
*/
|
||||
WEBTESTCLIENT;
|
||||
WEBTESTCLIENT
|
||||
|
||||
}
|
||||
|
||||
@@ -24,15 +24,18 @@ import java.util.regex.Pattern
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.util.logging.Commons
|
||||
import wiremock.com.google.common.collect.ArrayListMultimap
|
||||
import wiremock.com.google.common.collect.HashMultiset
|
||||
import wiremock.com.google.common.collect.ListMultimap
|
||||
import wiremock.com.google.common.collect.Multimap
|
||||
import wiremock.com.google.common.collect.Multiset
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.spec.ContractConverter
|
||||
import org.springframework.cloud.contract.verifier.converter.YamlContractConverter
|
||||
import org.springframework.cloud.contract.verifier.util.ContractVerifierDslConverter
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader
|
||||
|
||||
import org.springframework.util.CollectionUtils
|
||||
import org.springframework.util.MultiValueMap
|
||||
/**
|
||||
* Scans the provided file path for the DSLs. There's a possibility to provide
|
||||
* inclusion and exclusion filters.
|
||||
@@ -85,9 +88,136 @@ class ContractFileScanner {
|
||||
|
||||
/**
|
||||
* @return for a map of paths for which a list of matching contracts has been found
|
||||
* @deprecated use the {@link ContractFileScanner#findContractsRecursively} version
|
||||
*/
|
||||
@Deprecated
|
||||
ListMultimap<Path, ContractMetadata> findContracts() {
|
||||
ListMultimap<Path, ContractMetadata> result = ArrayListMultimap.create()
|
||||
MultiValueMap<Path, ContractMetadata> contracts = findContractsRecursively();
|
||||
return new ListMultimap<Path, ContractMetadata>() {
|
||||
@Override
|
||||
List<ContractMetadata> get(Path key) {
|
||||
return contracts.get(key)
|
||||
}
|
||||
|
||||
@Override
|
||||
List<ContractMetadata> removeAll(Object key) {
|
||||
return contracts.remove(key)
|
||||
}
|
||||
|
||||
@Override
|
||||
List<ContractMetadata> replaceValues(Path key, Iterable<? extends ContractMetadata> values) {
|
||||
return contracts.put(key, asList(values))
|
||||
}
|
||||
|
||||
private static List<? extends ContractMetadata> asList(Iterable<? extends ContractMetadata> self) {
|
||||
if (self instanceof List) {
|
||||
return (List<? extends ContractMetadata>) self;
|
||||
} else {
|
||||
return toList(self.iterator());
|
||||
}
|
||||
}
|
||||
|
||||
private static List<? extends ContractMetadata> toList(Iterator<? extends ContractMetadata> self) {
|
||||
List<? extends ContractMetadata> answer = new ArrayList<>();
|
||||
while (self.hasNext()) {
|
||||
answer.add(self.next());
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
@Override
|
||||
Map<Path, Collection<ContractMetadata>> asMap() {
|
||||
return contracts.collectEntries {
|
||||
[(it.key): (Collection<ContractMetadata>) it.value]
|
||||
} as Map<Path, Collection<ContractMetadata>>
|
||||
}
|
||||
|
||||
@Override
|
||||
int size() {
|
||||
return contracts.size()
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isEmpty() {
|
||||
return contracts.isEmpty()
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean containsKey(Object key) {
|
||||
return contracts.containsKey(key)
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean containsValue(Object value) {
|
||||
return contracts.findResult { it.value.contains(value) }
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean containsEntry(Object key, Object value) {
|
||||
return contracts.findResult { it.key == key && it.value.contains(value) }
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean put(Path key, ContractMetadata value) {
|
||||
return contracts.add(key, value)
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean remove(Object key, Object value) {
|
||||
return contracts.getOrDefault(key, new ArrayList<ContractMetadata>()).remove(value)
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean putAll(Path key, Iterable<? extends ContractMetadata> values) {
|
||||
return contracts.getOrDefault(key, new ArrayList<ContractMetadata>()).addAll(values)
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean putAll(Multimap<? extends Path, ? extends ContractMetadata> multimap) {
|
||||
multimap.entries().each {
|
||||
contracts.add(it.key, it.value)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@Override
|
||||
void clear() {
|
||||
contracts.clear()
|
||||
}
|
||||
|
||||
@Override
|
||||
Set<Path> keySet() {
|
||||
return contracts.keySet()
|
||||
}
|
||||
|
||||
@Override
|
||||
Multiset<Path> keys() {
|
||||
return HashMultiset.create(contracts.keySet())
|
||||
}
|
||||
|
||||
@Override
|
||||
Collection<ContractMetadata> values() {
|
||||
return (Collection<ContractMetadata>) contracts.values().flatten()
|
||||
}
|
||||
|
||||
@Override
|
||||
Collection<Map.Entry<Path, ContractMetadata>> entries() {
|
||||
Collection<Map.Entry<Path, ContractMetadata>> entries = new LinkedList<>()
|
||||
contracts.each {
|
||||
Path path = it.key
|
||||
List<ContractMetadata> list = it.value
|
||||
list.each {
|
||||
entries.add(new AbstractMap.SimpleEntry<Path, ContractMetadata>(path, it))
|
||||
}
|
||||
}
|
||||
return entries
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MultiValueMap<Path, ContractMetadata> findContractsRecursively() {
|
||||
MultiValueMap<Path, ContractMetadata> result = CollectionUtils.toMultiValueMap(new LinkedHashMap<>());
|
||||
appendRecursively(baseDir, result)
|
||||
return result
|
||||
}
|
||||
@@ -96,7 +226,7 @@ class ContractFileScanner {
|
||||
* We iterate over found contracts, filter out those that should be excluded
|
||||
* and try to convert via pluggable Contract Converters any possible contracts
|
||||
*/
|
||||
private void appendRecursively(File baseDir, ListMultimap<Path, ContractMetadata> result) {
|
||||
private void appendRecursively(File baseDir, MultiValueMap<Path, ContractMetadata> result) {
|
||||
List<ContractConverter> converters = convertersWithYml()
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace("Found the following contract converters ${converters}")
|
||||
@@ -148,7 +278,7 @@ class ContractFileScanner {
|
||||
return SpringFactoriesLoader.loadFactories(ContractConverter, null)
|
||||
}
|
||||
|
||||
private void addContractToTestGeneration(List<ContractConverter> converters, ListMultimap<Path, ContractMetadata> result,
|
||||
private void addContractToTestGeneration(List<ContractConverter> converters, MultiValueMap<Path, ContractMetadata> result,
|
||||
File[] files, File file, int index) {
|
||||
boolean converted = false
|
||||
if (!file.isDirectory()) {
|
||||
@@ -182,7 +312,7 @@ class ContractFileScanner {
|
||||
}
|
||||
}
|
||||
|
||||
private void addContractToTestGeneration(ListMultimap<Path, ContractMetadata> result, File[] files, File file,
|
||||
private void addContractToTestGeneration(MultiValueMap<Path, ContractMetadata> result, File[] files, File file,
|
||||
int index, Collection<Contract> convertedContract) {
|
||||
Path path = file.toPath()
|
||||
Integer order = null
|
||||
@@ -196,7 +326,7 @@ class ContractFileScanner {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Creating a contract entry for path [" + path + "] and metadata [" + metadata + "]")
|
||||
}
|
||||
result.put(parent, metadata)
|
||||
result.add(parent, metadata)
|
||||
}
|
||||
|
||||
private boolean hasScenarioFilenamePattern(Path path) {
|
||||
|
||||
@@ -18,21 +18,22 @@ package org.springframework.cloud.contract.verifier;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.assertj.core.api.BDDAssertions;
|
||||
import org.junit.Test;
|
||||
import org.mockito.BDDMockito;
|
||||
import wiremock.com.google.common.collect.ArrayListMultimap;
|
||||
import wiremock.com.google.common.collect.ListMultimap;
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract;
|
||||
import org.springframework.cloud.contract.verifier.builder.SingleTestGenerator;
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties;
|
||||
import org.springframework.cloud.contract.verifier.file.ContractFileScanner;
|
||||
import org.springframework.cloud.contract.verifier.file.ContractMetadata;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
public class TestGeneratorTests {
|
||||
|
||||
@@ -46,9 +47,10 @@ public class TestGeneratorTests {
|
||||
.mock(SingleTestGenerator.class);
|
||||
FileSaver fileSaver = BDDMockito.mock(FileSaver.class);
|
||||
// and:
|
||||
ArrayListMultimap<Path, ContractMetadata> multimap = ArrayListMultimap.create();
|
||||
MultiValueMap<Path, ContractMetadata> multimap = CollectionUtils
|
||||
.toMultiValueMap(new LinkedHashMap<>());
|
||||
Path path = new File(".").toPath();
|
||||
multimap.put(path,
|
||||
multimap.add(path,
|
||||
new ContractMetadata(path, false, 0, null, Contract.make(it -> {
|
||||
it.inProgress();
|
||||
it.request(r -> {
|
||||
@@ -61,7 +63,7 @@ public class TestGeneratorTests {
|
||||
})));
|
||||
ContractFileScanner scanner = new ContractFileScanner(null, null, null) {
|
||||
@Override
|
||||
public ListMultimap<Path, ContractMetadata> findContracts() {
|
||||
public MultiValueMap<Path, ContractMetadata> findContractsRecursively() {
|
||||
return multimap;
|
||||
}
|
||||
};
|
||||
@@ -87,9 +89,10 @@ public class TestGeneratorTests {
|
||||
.mock(SingleTestGenerator.class);
|
||||
FileSaver fileSaver = BDDMockito.mock(FileSaver.class);
|
||||
// and:
|
||||
ArrayListMultimap<Path, ContractMetadata> multimap = ArrayListMultimap.create();
|
||||
MultiValueMap<Path, ContractMetadata> multimap = CollectionUtils
|
||||
.toMultiValueMap(new LinkedHashMap<>());
|
||||
Path path = new File(".").toPath();
|
||||
multimap.put(path,
|
||||
multimap.add(path,
|
||||
new ContractMetadata(path, false, 0, null, Contract.make(it -> {
|
||||
it.inProgress();
|
||||
it.request(r -> {
|
||||
@@ -102,7 +105,7 @@ public class TestGeneratorTests {
|
||||
})));
|
||||
ContractFileScanner scanner = new ContractFileScanner(null, null, null) {
|
||||
@Override
|
||||
public ListMultimap<Path, ContractMetadata> findContracts() {
|
||||
public MultiValueMap<Path, ContractMetadata> findContractsRecursively() {
|
||||
return multimap;
|
||||
}
|
||||
};
|
||||
@@ -110,8 +113,8 @@ public class TestGeneratorTests {
|
||||
TestGenerator testGenerator = new TestGenerator(properties, singleTestGenerator,
|
||||
fileSaver, scanner) {
|
||||
@Override
|
||||
Set<Map.Entry<Path, Collection<ContractMetadata>>> processAllNotInProgress(
|
||||
ListMultimap<Path, ContractMetadata> contracts,
|
||||
Set<Map.Entry<Path, List<ContractMetadata>>> processAllNotInProgress(
|
||||
MultiValueMap<Path, ContractMetadata> contracts,
|
||||
String basePackageName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright 2013-2019 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
|
||||
*
|
||||
* https://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.cloud.contract.verifier.file
|
||||
|
||||
|
||||
import java.nio.file.Path
|
||||
|
||||
import org.junit.Rule
|
||||
import org.junit.rules.TemporaryFolder
|
||||
import spock.lang.Specification
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.spec.ContractConverter
|
||||
import org.springframework.util.FileSystemUtils
|
||||
import org.springframework.util.MultiValueMap
|
||||
|
||||
/**
|
||||
* @author Jakub Kubrynski, codearte.io
|
||||
*/
|
||||
class ContractFileScannerNewApiSpec extends Specification {
|
||||
|
||||
@Rule
|
||||
TemporaryFolder tmp = new TemporaryFolder()
|
||||
File tmpFolder
|
||||
|
||||
def setup() {
|
||||
tmpFolder = new File(tmp.newFolder(), "contracts")
|
||||
}
|
||||
|
||||
def "should find contract files"() {
|
||||
given:
|
||||
FileSystemUtils.copyRecursively(
|
||||
new File(this.getClass().getResource("/directory/with/stubs").toURI()),
|
||||
tmpFolder)
|
||||
and:
|
||||
File baseDir = tmpFolder
|
||||
Set<String> excluded = ["package/**"] as Set
|
||||
Set<String> ignored = ["other/different/**"] as Set
|
||||
ContractFileScanner scanner = new ContractFileScanner(baseDir, excluded, ignored, [] as Set)
|
||||
when:
|
||||
MultiValueMap<Path, ContractMetadata> result = scanner.findContractsRecursively()
|
||||
then:
|
||||
result.keySet().size() == 3
|
||||
result.get(baseDir.toPath().resolve("different")).size() == 1
|
||||
result.get(baseDir.toPath().resolve("other")).size() == 2
|
||||
and:
|
||||
Collection<ContractMetadata> ignoredSet = result.get(baseDir.toPath().resolve("other").resolve("different"))
|
||||
ignoredSet.size() == 1
|
||||
ignoredSet.ignored == [true]
|
||||
}
|
||||
|
||||
def "should find contract files in strange directories"() {
|
||||
given:
|
||||
File baseDir = new File(this.getClass().getResource("/strange_[3.3.3]_directory").toURI())
|
||||
Set<String> excluded = ["foo/**"] as Set
|
||||
Set<String> ignored = ["bar/**"] as Set
|
||||
ContractFileScanner scanner = new ContractFileScanner(baseDir, excluded, ignored, [] as Set)
|
||||
when:
|
||||
MultiValueMap<Path, ContractMetadata> result = scanner.findContractsRecursively()
|
||||
then:
|
||||
result.entrySet().size() == 2
|
||||
and:
|
||||
Collection<ContractMetadata> ignoredSet = result.get(baseDir.toPath().resolve("bar"))
|
||||
ignoredSet.size() == 1
|
||||
ignoredSet.ignored == [true]
|
||||
}
|
||||
|
||||
def "should find contracts group in scenario"() {
|
||||
given:
|
||||
File baseDir = new File(this.getClass().getResource("/directory/with/scenario").toURI())
|
||||
ContractFileScanner scanner = new ContractFileScanner(baseDir, [] as Set, [] as Set, [] as Set)
|
||||
when:
|
||||
MultiValueMap<Path, ContractMetadata> contracts = scanner.findContractsRecursively()
|
||||
then:
|
||||
contracts.values().size() == 1
|
||||
def firstEntry = contracts.values().first()
|
||||
firstEntry.size() == 3
|
||||
firstEntry.find {
|
||||
it.path.fileName.toString().startsWith('01')
|
||||
}.groupSize == 3
|
||||
firstEntry.find {
|
||||
it.path.fileName.toString().startsWith('01')
|
||||
}.order == 0
|
||||
firstEntry.find {
|
||||
it.path.fileName.toString().startsWith('02')
|
||||
}.order == 1
|
||||
firstEntry.find {
|
||||
it.path.fileName.toString().startsWith('03')
|
||||
}.order == 2
|
||||
}
|
||||
|
||||
def "should find contract files with converters"() {
|
||||
given:
|
||||
File baseDir = new File(this.getClass().getResource("/directory/with/mixed").toURI())
|
||||
ContractFileScanner scanner = new ContractFileScanner(baseDir, null, null, null) {
|
||||
@Override
|
||||
protected List<ContractConverter> converters() {
|
||||
return [new ContractConverter() {
|
||||
@Override
|
||||
boolean isAccepted(File file) {
|
||||
return file.name.endsWith(".json")
|
||||
}
|
||||
|
||||
@Override
|
||||
Collection<Contract> convertFrom(File file) {
|
||||
throw new RuntimeException("boom")
|
||||
}
|
||||
|
||||
@Override
|
||||
Object convertTo(Collection contract) {
|
||||
throw new RuntimeException("boom")
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
when:
|
||||
scanner.findContractsRecursively()
|
||||
then:
|
||||
IllegalStateException e = thrown(IllegalStateException)
|
||||
e.cause.message == "boom"
|
||||
e.message.matches(".*Failed to convert file .*invalid.json.*")
|
||||
}
|
||||
|
||||
def "should prefer custom yaml converter over standard yaml converter"() {
|
||||
given:
|
||||
File baseDir = new File(this.getClass().getResource("/directory/with/custom/yml").toURI())
|
||||
ContractFileScanner scanner = new ContractFileScanner(baseDir, null, null) {
|
||||
@Override
|
||||
protected List<ContractConverter> converters() {
|
||||
return [new ContractConverter() {
|
||||
@Override
|
||||
boolean isAccepted(File file) {
|
||||
if (!file.name.endsWith(".yml") && !file.name.endsWith(".yaml")) {
|
||||
return false
|
||||
}
|
||||
String line
|
||||
file.withReader {
|
||||
line = it.readLine()
|
||||
}
|
||||
return line != null && line.startsWith("custom_format: 1.0")
|
||||
}
|
||||
|
||||
@Override
|
||||
Collection<Contract> convertFrom(File file) {
|
||||
return Collections.singleton(Contract.newInstance())
|
||||
}
|
||||
|
||||
@Override
|
||||
Object convertTo(Collection contract) {
|
||||
return new Object()
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
when:
|
||||
MultiValueMap<Path, ContractMetadata> result = scanner.findContractsRecursively()
|
||||
then:
|
||||
result.keySet().size() == 1
|
||||
result.entrySet().every { it.value.convertedContract }
|
||||
}
|
||||
|
||||
def "should find contracts for include pattern"() {
|
||||
given:
|
||||
FileSystemUtils.copyRecursively(
|
||||
new File(this.getClass().getResource("/directory/with/common-messaging").toURI()),
|
||||
tmpFolder)
|
||||
and:
|
||||
File baseDir = tmpFolder
|
||||
Set<String> included = ["social-service/**", "**/coupon-collected/**/*V1*"] as Set
|
||||
ContractFileScanner scanner = new ContractFileScanner(baseDir, [] as Set, [] as Set, included)
|
||||
when:
|
||||
MultiValueMap<Path, ContractMetadata> result = scanner.findContractsRecursively()
|
||||
then:
|
||||
result.keySet().size() == 3
|
||||
result.values().flatten().find {
|
||||
(it.path.fileName.toString() == 'couponCollectedEventV1.groovy')
|
||||
}.groupSize == 2
|
||||
result.values().flatten().find {
|
||||
(it.convertedContract.first().label == 'couponCollectedV1')
|
||||
}
|
||||
result.values().flatten().findAll {
|
||||
(it.path.fileName.toString() == 'couponCollectedEventV2.groovy')
|
||||
}.isEmpty()
|
||||
result.values().flatten().find {
|
||||
(it.path.fileName.toString() == 'shouldUpdateUserInfo.groovy')
|
||||
}.groupSize == 1
|
||||
result.values().flatten().find {
|
||||
(it.path.fileName.toString() == 'shouldReturnEmptyFriendsWhenGetFriends.groovy')
|
||||
}.groupSize == 1
|
||||
result.get(baseDir.toPath().resolve("coupon-sent")) == null
|
||||
result.get(baseDir.toPath().resolve("reward-rules")) == null
|
||||
}
|
||||
}
|
||||
@@ -199,7 +199,7 @@ class ContractFileScannerSpec extends Specification {
|
||||
result.values().find {
|
||||
(it.path.fileName.toString() == 'shouldReturnEmptyFriendsWhenGetFriends.groovy')
|
||||
}.groupSize == 1
|
||||
result.get(baseDir.toPath().resolve("coupon-sent")).size() == 0
|
||||
result.get(baseDir.toPath().resolve("reward-rules")).size() == 0
|
||||
result.get(baseDir.toPath().resolve("coupon-sent")) == null
|
||||
result.get(baseDir.toPath().resolve("reward-rules")) == null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ package org.springframework.cloud.contract.verifier.messaging.amqp
|
||||
|
||||
import com.rabbitmq.client.Channel
|
||||
import org.mockito.exceptions.verification.WantedButNotInvoked
|
||||
import shaded.com.google.common.collect.ImmutableMap
|
||||
import spock.lang.Specification
|
||||
import wiremock.com.google.common.collect.ImmutableMap
|
||||
|
||||
import org.springframework.amqp.core.Binding
|
||||
import org.springframework.amqp.core.BindingBuilder
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
<logger name="com.github.jknack.handlebars.internal" level="INFO"/>
|
||||
|
||||
<!-- <logger name="org.springframework.cloud.function" level="INFO"/>-->
|
||||
<logger name="org.springframework.cloud.function" level="INFO"/>
|
||||
|
||||
<root level="DEBUG">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
|
||||
@@ -81,6 +81,10 @@
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
|
||||
@@ -38,7 +38,6 @@ import com.github.tomakehurst.wiremock.http.Request;
|
||||
import com.github.tomakehurst.wiremock.http.RequestMethod;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import wiremock.com.google.common.base.Optional;
|
||||
import wiremock.org.eclipse.jetty.server.handler.ContextHandler;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
@@ -51,6 +50,8 @@ import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;
|
||||
|
||||
import static org.eclipse.jetty.server.handler.ContextHandler.StaticContext;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
@@ -263,7 +264,7 @@ class WireMockHttpRequestAdapter implements Request {
|
||||
.request(this.result.getMethod(), this.result.getUriTemplate())
|
||||
.contentType(this.result.getRequestHeaders().getContentType())
|
||||
.content(this.result.getRequestBodyContent())
|
||||
.buildRequest(new ContextHandler.StaticContext());
|
||||
.buildRequest(new StaticContext());
|
||||
try {
|
||||
return new StandardMultipartHttpServletRequest(request).getParts().stream()
|
||||
.map(part -> partFromServletPart(part)).collect(Collectors.toList());
|
||||
|
||||
@@ -18,21 +18,18 @@ package org.springframework.cloud.contract.wiremock.restdocs;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder;
|
||||
import com.github.tomakehurst.wiremock.common.Gzip;
|
||||
import com.github.tomakehurst.wiremock.http.Body;
|
||||
import com.github.tomakehurst.wiremock.http.ContentTypeHeader;
|
||||
import com.github.tomakehurst.wiremock.http.Cookie;
|
||||
import com.github.tomakehurst.wiremock.http.HttpHeader;
|
||||
@@ -40,30 +37,15 @@ import com.github.tomakehurst.wiremock.http.HttpHeaders;
|
||||
import com.github.tomakehurst.wiremock.http.QueryParameter;
|
||||
import com.github.tomakehurst.wiremock.http.Request;
|
||||
import com.github.tomakehurst.wiremock.http.RequestMethod;
|
||||
import com.github.tomakehurst.wiremock.servlet.WireMockHttpServletMultipartAdapter;
|
||||
import wiremock.com.google.common.base.Function;
|
||||
import wiremock.com.google.common.base.Optional;
|
||||
import wiremock.com.google.common.collect.ImmutableList;
|
||||
import wiremock.com.google.common.collect.ImmutableMultimap;
|
||||
import wiremock.com.google.common.collect.Maps;
|
||||
import wiremock.org.apache.commons.io.IOUtils;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.ResultHandler;
|
||||
|
||||
import static com.github.tomakehurst.wiremock.common.Encoding.encodeBase64;
|
||||
import static com.github.tomakehurst.wiremock.common.Exceptions.throwUnchecked;
|
||||
import static com.github.tomakehurst.wiremock.common.Strings.stringFromBytes;
|
||||
import static com.github.tomakehurst.wiremock.common.Urls.splitQuery;
|
||||
import static java.util.Collections.list;
|
||||
import static wiremock.com.google.common.base.Charsets.UTF_8;
|
||||
import static wiremock.com.google.common.base.MoreObjects.firstNonNull;
|
||||
import static wiremock.com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static wiremock.com.google.common.collect.FluentIterable.from;
|
||||
import static wiremock.com.google.common.collect.Lists.newArrayList;
|
||||
import static wiremock.com.google.common.io.ByteStreams.toByteArray;
|
||||
import org.springframework.util.Base64Utils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Converts a {@link MvcResult} to a WireMock response.
|
||||
@@ -117,7 +99,191 @@ public class ContractResultHandler extends
|
||||
|
||||
@Override
|
||||
protected Request getWireMockRequest(MvcResult result) {
|
||||
return new WireMockHttpServletRequestAdapter(result.getRequest());
|
||||
return new Request() {
|
||||
@Override
|
||||
public String getUrl() {
|
||||
return result.getRequest().getRequestURI();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAbsoluteUrl() {
|
||||
return result.getRequest().getRequestURI();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestMethod getMethod() {
|
||||
return RequestMethod.fromString(result.getRequest().getMethod());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getScheme() {
|
||||
return result.getRequest().getScheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHost() {
|
||||
return result.getRequest().getRemoteHost();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPort() {
|
||||
return result.getRequest().getServerPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getClientIp() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHeader(String key) {
|
||||
return result.getRequest().getHeader(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeader header(String key) {
|
||||
return new HttpHeader(key, getHeader(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentTypeHeader contentTypeHeader() {
|
||||
return new ContentTypeHeader(result.getRequest().getContentType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders getHeaders() {
|
||||
List<HttpHeader> headers = new ArrayList<>();
|
||||
Enumeration<String> headerNames = result.getRequest().getHeaderNames();
|
||||
while (headerNames.hasMoreElements()) {
|
||||
String key = headerNames.nextElement();
|
||||
String value = getHeader(key);
|
||||
headers.add(new HttpHeader(key, value));
|
||||
}
|
||||
return new HttpHeaders(headers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsHeader(String key) {
|
||||
Enumeration<String> headerNames = result.getRequest().getHeaderNames();
|
||||
while (headerNames.hasMoreElements()) {
|
||||
String name = headerNames.nextElement();
|
||||
if (name.equals(key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAllHeaderKeys() {
|
||||
return getHeaders().keys();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Cookie> getCookies() {
|
||||
Map<String, Cookie> nameToCookie = new HashMap<>();
|
||||
if (result.getRequest().getCookies() == null) {
|
||||
return nameToCookie;
|
||||
}
|
||||
for (javax.servlet.http.Cookie cookie : result.getRequest()
|
||||
.getCookies()) {
|
||||
nameToCookie.put(cookie.getName(), new Cookie(cookie.getValue()));
|
||||
}
|
||||
return nameToCookie;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryParameter queryParameter(String key) {
|
||||
return new QueryParameter(key,
|
||||
Collections.singletonList(result.getRequest().getParameter(key)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBody() {
|
||||
return result.getRequest().getContentAsByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBodyAsString() {
|
||||
try {
|
||||
return result.getRequest().getContentAsString();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
return new String(result.getRequest().getContentAsByteArray());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBodyAsBase64() {
|
||||
return Base64Utils
|
||||
.encodeToString(result.getRequest().getContentAsByteArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMultipart() {
|
||||
return StringUtils
|
||||
.hasText(result.getRequest().getHeader("multipart/form-data"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Part> getParts() {
|
||||
try {
|
||||
return result.getRequest().getParts().stream()
|
||||
.map(part -> new Part() {
|
||||
@Override
|
||||
public String getName() {
|
||||
return part.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeader getHeader(String name) {
|
||||
String header = part.getHeader(name);
|
||||
return new HttpHeader(name, header);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders getHeaders() {
|
||||
List<HttpHeader> headers = new ArrayList<>();
|
||||
for (String headerName : part.getHeaderNames()) {
|
||||
headers.add(new HttpHeader(headerName,
|
||||
getHeader(headerName).values()));
|
||||
}
|
||||
return new HttpHeaders(headers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Body getBody() {
|
||||
try {
|
||||
return new Body(IOUtils
|
||||
.toByteArray(part.getInputStream()));
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Part getPart(String name) {
|
||||
return getParts().stream().filter(part -> part.getName().equals(name))
|
||||
.findFirst().orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBrowserProxyRequest() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Request> getOriginalRequest() {
|
||||
return Optional.absent();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -127,289 +293,8 @@ public class ContractResultHandler extends
|
||||
|
||||
@Override
|
||||
protected byte[] getRequestBodyContent(MvcResult result) {
|
||||
byte[] body = new WireMockHttpServletRequestAdapter(result.getRequest())
|
||||
.getBody();
|
||||
byte[] body = getWireMockRequest(result).getBody();
|
||||
return body != null ? body : new byte[0];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// COPIED FROM WIREMOCK
|
||||
class WireMockHttpServletRequestAdapter implements Request {
|
||||
|
||||
private static final String ORIGINAL_REQUEST_KEY = "wiremock.ORIGINAL_REQUEST";
|
||||
|
||||
private final HttpServletRequest request;
|
||||
|
||||
private byte[] cachedBody;
|
||||
|
||||
private Collection<Part> cachedMultiparts;
|
||||
|
||||
WireMockHttpServletRequestAdapter(HttpServletRequest request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUrl() {
|
||||
String url = this.request.getRequestURI();
|
||||
String contextPath = this.request.getContextPath();
|
||||
if (!isNullOrEmpty(contextPath) && url.startsWith(contextPath)) {
|
||||
url = url.substring(contextPath.length());
|
||||
}
|
||||
return withQueryStringIfPresent(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAbsoluteUrl() {
|
||||
return withQueryStringIfPresent(this.request.getRequestURL().toString());
|
||||
}
|
||||
|
||||
private String withQueryStringIfPresent(String url) {
|
||||
return url + (isNullOrEmpty(this.request.getQueryString()) ? ""
|
||||
: "?" + this.request.getQueryString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestMethod getMethod() {
|
||||
return RequestMethod.fromString(this.request.getMethod().toUpperCase());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getScheme() {
|
||||
return this.request.getScheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHost() {
|
||||
return this.request.getServerName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPort() {
|
||||
return this.request.getServerPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getClientIp() {
|
||||
String forwardedForHeader = this.getHeader("X-Forwarded-For");
|
||||
|
||||
if (forwardedForHeader != null && forwardedForHeader.length() > 0) {
|
||||
return forwardedForHeader;
|
||||
}
|
||||
|
||||
return this.request.getRemoteAddr();
|
||||
}
|
||||
|
||||
// Something's wrong with reading the body from request
|
||||
@Override
|
||||
public byte[] getBody() {
|
||||
if (this.cachedBody == null || this.cachedBody.length == 0) {
|
||||
try {
|
||||
if (this.request instanceof MockHttpServletRequest) {
|
||||
this.cachedBody = ((MockHttpServletRequest) this.request)
|
||||
.getContentAsByteArray();
|
||||
return this.cachedBody;
|
||||
}
|
||||
byte[] body = toByteArray(this.request.getInputStream());
|
||||
boolean isGzipped = hasGzipEncoding() || Gzip.isGzipped(body);
|
||||
this.cachedBody = isGzipped ? Gzip.unGzip(body) : body;
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
throw new RuntimeException(ioe);
|
||||
}
|
||||
}
|
||||
return this.cachedBody;
|
||||
}
|
||||
|
||||
private Charset encodingFromContentTypeHeaderOrUtf8() {
|
||||
ContentTypeHeader contentTypeHeader = contentTypeHeader();
|
||||
if (contentTypeHeader != null) {
|
||||
return contentTypeHeader.charset();
|
||||
}
|
||||
return UTF_8;
|
||||
}
|
||||
|
||||
private boolean hasGzipEncoding() {
|
||||
String encodingHeader = this.request.getHeader("Content-Encoding");
|
||||
return encodingHeader != null && encodingHeader.contains("gzip");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBodyAsString() {
|
||||
return stringFromBytes(getBody(), encodingFromContentTypeHeaderOrUtf8());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBodyAsBase64() {
|
||||
return encodeBase64(getBody());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHeader(String key) {
|
||||
List<String> headerNames = list(this.request.getHeaderNames());
|
||||
for (String currentKey : headerNames) {
|
||||
if (currentKey.toLowerCase().equals(key.toLowerCase())) {
|
||||
return this.request.getHeader(currentKey);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeader header(String key) {
|
||||
List<String> headerNames = list(this.request.getHeaderNames());
|
||||
for (String currentKey : headerNames) {
|
||||
if (currentKey.toLowerCase().equals(key.toLowerCase())) {
|
||||
List<String> valueList = list(this.request.getHeaders(currentKey));
|
||||
if (valueList.isEmpty()) {
|
||||
return HttpHeader.empty(key);
|
||||
}
|
||||
return new HttpHeader(key, valueList);
|
||||
}
|
||||
}
|
||||
|
||||
return HttpHeader.absent(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentTypeHeader contentTypeHeader() {
|
||||
return getHeaders().getContentTypeHeader();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsHeader(String key) {
|
||||
return header(key).isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders getHeaders() {
|
||||
List<HttpHeader> headerList = newArrayList();
|
||||
for (String key : getAllHeaderKeys()) {
|
||||
headerList.add(header(key));
|
||||
}
|
||||
|
||||
return new HttpHeaders(headerList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAllHeaderKeys() {
|
||||
LinkedHashSet<String> headerKeys = new LinkedHashSet<>();
|
||||
for (Enumeration<String> headerNames = this.request.getHeaderNames(); headerNames
|
||||
.hasMoreElements();) {
|
||||
headerKeys.add(headerNames.nextElement());
|
||||
}
|
||||
|
||||
return headerKeys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Cookie> getCookies() {
|
||||
ImmutableMultimap.Builder<String, String> builder = ImmutableMultimap.builder();
|
||||
javax.servlet.http.Cookie[] cookies = firstNonNull(this.request.getCookies(),
|
||||
new javax.servlet.http.Cookie[0]);
|
||||
for (javax.servlet.http.Cookie cookie : cookies) {
|
||||
builder.put(cookie.getName(), cookie.getValue());
|
||||
}
|
||||
return Maps.transformValues(builder.build().asMap(),
|
||||
input -> new Cookie(null, ImmutableList.copyOf(input)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryParameter queryParameter(String key) {
|
||||
return firstNonNull((splitQuery(this.request.getQueryString()).get(key)),
|
||||
QueryParameter.absent(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBrowserProxyRequest() {
|
||||
if (!isJetty()) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Collection<Part> getParts() {
|
||||
if (!isMultipart()) {
|
||||
return null;
|
||||
}
|
||||
if (this.cachedMultiparts == null) {
|
||||
try {
|
||||
this.cachedMultiparts = from(safelyGetRequestParts()).transform(
|
||||
(Function<javax.servlet.http.Part, Part>) WireMockHttpServletMultipartAdapter::from)
|
||||
.toList();
|
||||
}
|
||||
catch (IOException | ServletException exception) {
|
||||
return throwUnchecked(exception, Collection.class);
|
||||
}
|
||||
}
|
||||
return (this.cachedMultiparts.size() > 0) ? this.cachedMultiparts : null;
|
||||
}
|
||||
|
||||
private Collection<javax.servlet.http.Part> safelyGetRequestParts()
|
||||
throws IOException, ServletException {
|
||||
try {
|
||||
return this.request.getParts();
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
if (ioe.getMessage().contains("Missing content for multipart")) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
throw ioe;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMultipart() {
|
||||
String header = getHeader("Content-Type");
|
||||
return (header != null && header.contains("multipart"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Part getPart(final String name) {
|
||||
if (name == null || name.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
if (this.cachedMultiparts == null) {
|
||||
if (getParts() == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return from(this.cachedMultiparts)
|
||||
.firstMatch(input -> name.equals(input.getName())).get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Request> getOriginalRequest() {
|
||||
Request originalRequest = (Request) this.request
|
||||
.getAttribute(ORIGINAL_REQUEST_KEY);
|
||||
return Optional.fromNullable(originalRequest);
|
||||
}
|
||||
|
||||
private boolean isJetty() {
|
||||
try {
|
||||
getClass("org.eclipse.jetty.server.Request");
|
||||
return true;
|
||||
}
|
||||
catch (Exception e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void getClass(String type) throws ClassNotFoundException {
|
||||
ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
|
||||
ClassLoader loader = contextCL == null
|
||||
? com.github.tomakehurst.wiremock.servlet.WireMockHttpServletRequestAdapter.class
|
||||
.getClassLoader()
|
||||
: contextCL;
|
||||
Class.forName(type, false, loader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.request.toString() + getBodyAsString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
package com.example.loan;
|
||||
|
||||
import org.junit.Test;
|
||||
import wiremock.com.google.common.collect.ImmutableMap;
|
||||
import shaded.com.google.common.collect.ImmutableMap;
|
||||
|
||||
import org.springframework.beans.BeanInstantiationException;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
|
||||
Reference in New Issue
Block a user