diff --git a/docs/src/main/asciidoc/spring-cloud-wiremock.adoc b/docs/src/main/asciidoc/spring-cloud-wiremock.adoc
index 087d19afe2..8e80571029 100644
--- a/docs/src/main/asciidoc/spring-cloud-wiremock.adoc
+++ b/docs/src/main/asciidoc/spring-cloud-wiremock.adoc
@@ -94,6 +94,49 @@ include::{doc_samples}/src/test/java/com/example/WiremockForDocsClassRuleTests.j
The use `@ClassRule` means that the server will shut down after all the methods in this class.
+== Relaxed SSL Validation for Rest Template
+
+WireMock allows you to stub a "secure" server with an "https" URL protocol. If your application wants to
+contact that stub server in an integration test, then it will find that the SSL certificates are not
+valid (it's the usual problem with self-installed certificates). The best option is often to just
+re-configure the client to use "http", but if that's not open to you then you can ask Spring to configure
+an HTTP client that ignores SSL validation errors (just for tests).
+
+To make this work with minimum fuss you need to be using the Spring Boot `RestTemplateBuilder` in your app,
+e.g.
+
+[source,java,indent=0]
+----
+ @Bean
+ public RestTemplate restTemplate(RestTemplateBuilder builder) {
+ return builder.build();
+ }
+----
+
+This is because the builder is passed through callbacks to initalize it, so the SSL validation can be set up
+in the client at that point. This will happen automatically in your test if you are using the
+`@AutoConfigureWireMock` annotation (or the stub runner). If you are using the JUnit `@Rule` approach you need
+to add the `@AutoConfigureHttpClient` annotation as well:
+
+[source,java,indent=0]
+----
+@RunWith(SpringRunner.class)
+@SpringBootTest("app.baseUrl=https://localhost:6443")
+@AutoConfigureHttpClient
+public class WiremockHttpsServerApplicationTests {
+
+ @ClassRule
+ public static WireMockClassRule wiremock = new WireMockClassRule(
+ WireMockSpring.options().httpsPort(6443));
+...
+}
+----
+
+If you are using `spring-boot-starter-test` then you will have the Apache HTTP client on the classpath and it will
+be selected by the `RestTemplateBuilder` and configured to ignore SSL errors. If you are using the default `java.net`
+client you don't need the annotation (but it won't do any harm). There is no support currently for other clients, but
+it may be added in future releases.
+
== WireMock and Spring MVC Mocks
Spring Cloud Contract provides a convenience class that can load JSON WireMock stubs into a
diff --git a/pom.xml b/pom.xml
index 67b3b4604e..f5165f2022 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,7 +7,7 @@
org.springframework.cloud
spring-cloud-build
- 1.3.1.BUILD-SNAPSHOT
+ 1.3.2.BUILD-SNAPSHOT
@@ -27,12 +27,12 @@
2.17.0
1.5.3.BUILD-SNAPSHOT
2.17
- 1.3.1.BUILD-SNAPSHOT
- 1.1.0.BUILD-SNAPSHOT
+ 1.3.2.BUILD-SNAPSHOT
+ 1.1.1.BUILD-SNAPSHOT
Chelsea.BUILD-SNAPSHOT
- 1.3.0.BUILD-SNAPSHOT
- 1.2.0.BUILD-SNAPSHOT
- 1.2.0.BUILD-SNAPSHOT
+ 1.3.1.BUILD-SNAPSHOT
+ 1.2.1.BUILD-SNAPSHOT
+ 1.2.1.BUILD-SNAPSHOT
diff --git a/samples/standalone/dsl/http-client/src/main/java/com/example/loan/LoanApplicationService.java b/samples/standalone/dsl/http-client/src/main/java/com/example/loan/LoanApplicationService.java
index c91df67aea..cf26b27f35 100644
--- a/samples/standalone/dsl/http-client/src/main/java/com/example/loan/LoanApplicationService.java
+++ b/samples/standalone/dsl/http-client/src/main/java/com/example/loan/LoanApplicationService.java
@@ -5,6 +5,7 @@ import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
+import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@@ -20,9 +21,6 @@ import com.example.loan.model.Response;
@Service
public class LoanApplicationService {
- private static final String FRAUD_SERVICE_JSON_VERSION_1 =
- "application/vnd.fraud.v1+json";
-
private final RestTemplate restTemplate;
private int port = 6565;
@@ -45,7 +43,7 @@ public class LoanApplicationService {
private FraudServiceResponse sendRequestToFraudDetectionService(
FraudServiceRequest request) {
HttpHeaders httpHeaders = new HttpHeaders();
- httpHeaders.add(HttpHeaders.CONTENT_TYPE, FRAUD_SERVICE_JSON_VERSION_1);
+ httpHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
// tag::client_call_server[]
ResponseEntity response =
@@ -70,7 +68,7 @@ public class LoanApplicationService {
public int countAllFrauds() {
HttpHeaders httpHeaders = new HttpHeaders();
- httpHeaders.add(HttpHeaders.CONTENT_TYPE, FRAUD_SERVICE_JSON_VERSION_1);
+ httpHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
ResponseEntity response =
restTemplate.exchange("http://localhost:" + port + "/frauds", HttpMethod.GET,
new HttpEntity<>(httpHeaders),
@@ -80,7 +78,7 @@ public class LoanApplicationService {
public int countDrunks() {
HttpHeaders httpHeaders = new HttpHeaders();
- httpHeaders.add(HttpHeaders.CONTENT_TYPE, FRAUD_SERVICE_JSON_VERSION_1);
+ httpHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
ResponseEntity response =
restTemplate.exchange("http://localhost:" + port + "/drunks", HttpMethod.GET,
new HttpEntity<>(httpHeaders),
diff --git a/samples/standalone/dsl/http-server/pom.xml b/samples/standalone/dsl/http-server/pom.xml
index e0a6490c58..772176997a 100644
--- a/samples/standalone/dsl/http-server/pom.xml
+++ b/samples/standalone/dsl/http-server/pom.xml
@@ -117,7 +117,7 @@
org.springframework.cloud
spring-cloud-contract-maven-plugin
- [1.1.0.BUILD-SNAPSHOT,)
+ [1.1.1.BUILD-SNAPSHOT,)
convert
generateTests
diff --git a/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudDetectionController.java b/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudDetectionController.java
index d172969868..764f8a6e96 100644
--- a/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudDetectionController.java
+++ b/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudDetectionController.java
@@ -15,17 +15,12 @@ import static org.springframework.web.bind.annotation.RequestMethod.PUT;
@RestController
public class FraudDetectionController {
- private static final String FRAUD_SERVICE_JSON_VERSION_1 = "application/vnd.fraud.v1+json";
private static final String NO_REASON = null;
private static final String AMOUNT_TOO_HIGH = "Amount too high";
private static final BigDecimal MAX_AMOUNT = new BigDecimal("5000");
// tag::server_api[]
- @RequestMapping(
- value = "/fraudcheck",
- method = PUT,
- consumes = FRAUD_SERVICE_JSON_VERSION_1,
- produces = FRAUD_SERVICE_JSON_VERSION_1)
+ @RequestMapping(value = "/fraudcheck", method = PUT)
public FraudCheckResult fraudCheck(@RequestBody FraudCheck fraudCheck) {
// end::server_api[]
// tag::new_impl[]
diff --git a/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudNameController.java b/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudNameController.java
index ea6ff8f2c0..4ba6881594 100644
--- a/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudNameController.java
+++ b/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudNameController.java
@@ -10,17 +10,13 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
class FraudNameController {
- private static final String FRAUD_SERVICE_JSON_VERSION_1 = "application/vnd.fraud.v1+json";
-
private final FraudVerifier fraudVerifier;
FraudNameController(FraudVerifier fraudVerifier) {
this.fraudVerifier = fraudVerifier;
}
- @PutMapping(
- value = "/frauds/name",
- produces = FRAUD_SERVICE_JSON_VERSION_1)
+ @PutMapping(value = "/frauds/name")
public NameResponse checkByName(@RequestBody NameRequest request) {
boolean fraud = this.fraudVerifier.isFraudByName(request.getName());
if (fraud) {
diff --git a/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudStatsController.java b/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudStatsController.java
index ab8d933814..ac9340611c 100644
--- a/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudStatsController.java
+++ b/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudStatsController.java
@@ -6,24 +6,18 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
public class FraudStatsController {
- private static final String FRAUD_SERVICE_JSON_VERSION_1 = "application/vnd.fraud.v1+json";
-
private final StatsProvider statsProvider;
public FraudStatsController(StatsProvider statsProvider) {
this.statsProvider = statsProvider;
}
- @GetMapping(
- value = "/frauds",
- produces = FRAUD_SERVICE_JSON_VERSION_1)
+ @GetMapping(value = "/frauds")
public Response countAllFrauds() {
return new Response(this.statsProvider.count(FraudType.ALL));
}
- @GetMapping(
- value = "/drunks",
- produces = FRAUD_SERVICE_JSON_VERSION_1)
+ @GetMapping(value = "/drunks")
public Response countAllDrunks() {
return new Response(this.statsProvider.count(FraudType.DRUNKS));
}
diff --git a/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.groovy b/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.groovy
index 02614d1555..64dcdc139c 100644
--- a/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.groovy
+++ b/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.groovy
@@ -9,7 +9,7 @@ org.springframework.cloud.contract.spec.Contract.make {
loanAmount: 99999
])
headers { // (5)
- contentType('application/vnd.fraud.v1+json')
+ contentType('application/json')
}
}
response { // (6)
@@ -19,7 +19,7 @@ org.springframework.cloud.contract.spec.Contract.make {
rejectionReason: "Amount too high"
])
headers { // (9)
- contentType('application/vnd.fraud.v1+json')
+ contentType('application/json')
}
}
}
@@ -33,12 +33,12 @@ From the Consumer perspective, when shooting a request in the integration test:
(4) - with the JSON body that
* has a field `clientId` that matches a regular expression `[0-9]{10}`
* has a field `loanAmount` that is equal to `99999`
-(5) - with header `Content-Type` equal to `application/vnd.fraud.v1+json`
+(5) - with header `Content-Type` equal to `application/json`
(6) - then the response will be sent with
(7) - status equal `200`
(8) - and JSON body equal to
{ "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
-(9) - with header `Content-Type` equal to `application/vnd.fraud.v1+json`
+(9) - with header `Content-Type` equal to `application/json`
From the Producer perspective, in the autogenerated producer-side test:
@@ -48,10 +48,10 @@ From the Producer perspective, in the autogenerated producer-side test:
(4) - with the JSON body that
* has a field `clientId` that will have a generated value that matches a regular expression `[0-9]{10}`
* has a field `loanAmount` that is equal to `99999`
-(5) - with header `Content-Type` equal to `application/vnd.fraud.v1+json`
+(5) - with header `Content-Type` equal to `application/json`
(6) - then the test will assert if the response has been sent with
(7) - status equal `200`
(8) - and JSON body equal to
{ "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
-(9) - with header `Content-Type` matching `application/vnd.fraud.v1+json.*`
+(9) - with header `Content-Type` matching `application/json.*`
*/
\ No newline at end of file
diff --git a/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsNotFraud.groovy b/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsNotFraud.groovy
index c3dce3f32d..a04fe8447f 100644
--- a/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsNotFraud.groovy
+++ b/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsNotFraud.groovy
@@ -12,7 +12,7 @@ org.springframework.cloud.contract.spec.Contract.make {
"""
)
headers {
- contentType("application/vnd.fraud.v1+json")
+ contentType("application/json")
}
}
@@ -23,7 +23,7 @@ org.springframework.cloud.contract.spec.Contract.make {
rejectionReason: $(consumer(null), producer(execute('assertThatRejectionReasonIsNull($it)')))
)
headers {
- contentType("application/vnd.fraud.v1+json")
+ contentType("application/json")
}
}
diff --git a/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldReturnFraudStats.groovy b/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldReturnFraudStats.groovy
index a6ed5a97d7..1b95f5e19f 100644
--- a/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldReturnFraudStats.groovy
+++ b/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldReturnFraudStats.groovy
@@ -15,7 +15,7 @@ import org.springframework.cloud.contract.spec.Contract
count: 200
])
headers {
- contentType("application/vnd.fraud.v1+json")
+ contentType("application/json")
}
}
},
@@ -30,7 +30,7 @@ import org.springframework.cloud.contract.spec.Contract
count: 100
])
headers {
- contentType("application/vnd.fraud.v1+json")
+ contentType("application/json")
}
}
}
diff --git a/samples/standalone/dsl/http-server/src/test/resources/contracts/fraudname/shouldReturnAFraudForTheName.groovy b/samples/standalone/dsl/http-server/src/test/resources/contracts/fraudname/shouldReturnAFraudForTheName.groovy
index f2f96c2676..31c3d0e215 100644
--- a/samples/standalone/dsl/http-server/src/test/resources/contracts/fraudname/shouldReturnAFraudForTheName.groovy
+++ b/samples/standalone/dsl/http-server/src/test/resources/contracts/fraudname/shouldReturnAFraudForTheName.groovy
@@ -10,7 +10,7 @@ org.springframework.cloud.contract.spec.Contract.make {
name: "fraud"
])
headers {
- contentType("application/vnd.fraud.v1+json")
+ contentType("application/json")
}
}
response {
diff --git a/samples/standalone/dsl/http-server/src/test/resources/contracts/fraudname/shouldReturnNonFraudForTheName.groovy b/samples/standalone/dsl/http-server/src/test/resources/contracts/fraudname/shouldReturnNonFraudForTheName.groovy
index eddea317a7..ce9a92a533 100644
--- a/samples/standalone/dsl/http-server/src/test/resources/contracts/fraudname/shouldReturnNonFraudForTheName.groovy
+++ b/samples/standalone/dsl/http-server/src/test/resources/contracts/fraudname/shouldReturnNonFraudForTheName.groovy
@@ -8,7 +8,7 @@ org.springframework.cloud.contract.spec.Contract.make {
name: $(anyAlphaUnicode())
])
headers {
- contentType("application/vnd.fraud.v1+json")
+ contentType("application/json")
}
}
response {
diff --git a/samples/standalone/dsl/pom.xml b/samples/standalone/dsl/pom.xml
index 13c73b511d..1246a5d6d3 100644
--- a/samples/standalone/dsl/pom.xml
+++ b/samples/standalone/dsl/pom.xml
@@ -6,7 +6,7 @@
org.springframework.cloud
spring-cloud-contract-samples-standalone
- 1.1.0.BUILD-SNAPSHOT
+ 1.1.1.BUILD-SNAPSHOT
..
diff --git a/samples/standalone/messaging/pom.xml b/samples/standalone/messaging/pom.xml
index 8893959be8..05616bbc2c 100644
--- a/samples/standalone/messaging/pom.xml
+++ b/samples/standalone/messaging/pom.xml
@@ -6,7 +6,7 @@
org.springframework.cloud
spring-cloud-contract-samples-standalone
- 1.1.0.BUILD-SNAPSHOT
+ 1.1.1.BUILD-SNAPSHOT
..
diff --git a/samples/standalone/messaging/stream-source/pom.xml b/samples/standalone/messaging/stream-source/pom.xml
index f11d74d600..e11c1616e0 100644
--- a/samples/standalone/messaging/stream-source/pom.xml
+++ b/samples/standalone/messaging/stream-source/pom.xml
@@ -156,7 +156,7 @@
org.springframework.cloud
spring-cloud-contract-maven-plugin
- [1.1.0.BUILD-SNAPSHOT,)
+ [1.1.1.BUILD-SNAPSHOT,)
convert
generateTests
diff --git a/samples/standalone/pact/pact-http-server/pom.xml b/samples/standalone/pact/pact-http-server/pom.xml
index 310125e090..13eb8c236a 100644
--- a/samples/standalone/pact/pact-http-server/pom.xml
+++ b/samples/standalone/pact/pact-http-server/pom.xml
@@ -125,7 +125,7 @@
org.springframework.cloud
spring-cloud-contract-maven-plugin
- [1.1.0.BUILD-SNAPSHOT,)
+ [1.1.1.BUILD-SNAPSHOT,)
convert
generateTests
diff --git a/samples/standalone/pact/pom.xml b/samples/standalone/pact/pom.xml
index 3b582cc2b7..56469b3a2b 100644
--- a/samples/standalone/pact/pom.xml
+++ b/samples/standalone/pact/pom.xml
@@ -6,7 +6,7 @@
org.springframework.cloud
spring-cloud-contract-samples-standalone
- 1.1.0.BUILD-SNAPSHOT
+ 1.1.1.BUILD-SNAPSHOT
..
diff --git a/samples/standalone/pom.xml b/samples/standalone/pom.xml
index 56f1211331..85fb0941cc 100644
--- a/samples/standalone/pom.xml
+++ b/samples/standalone/pom.xml
@@ -6,7 +6,7 @@
org.springframework.cloud
spring-cloud-contract-samples
- 1.1.0.BUILD-SNAPSHOT
+ 1.1.1.BUILD-SNAPSHOT
..
diff --git a/samples/standalone/restdocs/pom.xml b/samples/standalone/restdocs/pom.xml
index 45d64b19f8..bf1aad247f 100644
--- a/samples/standalone/restdocs/pom.xml
+++ b/samples/standalone/restdocs/pom.xml
@@ -6,7 +6,7 @@
org.springframework.cloud
spring-cloud-contract-samples-standalone
- 1.1.0.BUILD-SNAPSHOT
+ 1.1.1.BUILD-SNAPSHOT
..
diff --git a/samples/wiremock-jetty/src/main/java/com/example/WiremockTestsApplication.java b/samples/wiremock-jetty/src/main/java/com/example/WiremockTestsApplication.java
index dbf42f24cc..0608f2f338 100644
--- a/samples/wiremock-jetty/src/main/java/com/example/WiremockTestsApplication.java
+++ b/samples/wiremock-jetty/src/main/java/com/example/WiremockTestsApplication.java
@@ -3,6 +3,7 @@ package com.example;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -13,8 +14,8 @@ import org.springframework.web.client.RestTemplate;
public class WiremockTestsApplication {
@Bean
- public RestTemplate restTemplate() {
- return new RestTemplate();
+ public RestTemplate restTemplate(RestTemplateBuilder builder) {
+ return builder.build();
}
public static void main(String[] args) {
diff --git a/samples/wiremock-jetty/src/test/java/com/example/WiremockHttpsServerApplicationTests.java b/samples/wiremock-jetty/src/test/java/com/example/WiremockHttpsServerApplicationTests.java
index e700ce0211..93b83c12d5 100644
--- a/samples/wiremock-jetty/src/test/java/com/example/WiremockHttpsServerApplicationTests.java
+++ b/samples/wiremock-jetty/src/test/java/com/example/WiremockHttpsServerApplicationTests.java
@@ -1,26 +1,28 @@
package com.example;
+import com.github.tomakehurst.wiremock.junit.WireMockClassRule;
+
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cloud.contract.wiremock.AutoConfigureHttpClient;
+import org.springframework.cloud.contract.wiremock.WireMockSpring;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.junit4.SpringRunner;
+
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
import static org.assertj.core.api.Assertions.assertThat;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.cloud.contract.wiremock.WireMockSpring;
-import org.springframework.test.annotation.DirtiesContext;
-import org.springframework.test.context.junit4.SpringRunner;
-
-import com.github.tomakehurst.wiremock.junit.WireMockClassRule;
-
-
@RunWith(SpringRunner.class)
@SpringBootTest("app.baseUrl=https://localhost:8443")
@DirtiesContext
+@AutoConfigureHttpClient
public class WiremockHttpsServerApplicationTests {
@ClassRule
@@ -32,8 +34,8 @@ public class WiremockHttpsServerApplicationTests {
@Test
public void contextLoads() throws Exception {
- stubFor(get(urlEqualTo("/resource"))
- .willReturn(aResponse().withHeader("Content-Type", "text/plain").withBody("Hello World!")));
+ stubFor(get(urlEqualTo("/resource")).willReturn(aResponse()
+ .withHeader("Content-Type", "text/plain").withBody("Hello World!")));
assertThat(this.service.go()).isEqualTo("Hello World!");
}
diff --git a/samples/wiremock-jetty/src/test/java/com/example/WiremockServerApplicationTests.java b/samples/wiremock-jetty/src/test/java/com/example/WiremockServerApplicationTests.java
index 6c6f1e6da9..9bbb1671d6 100644
--- a/samples/wiremock-jetty/src/test/java/com/example/WiremockServerApplicationTests.java
+++ b/samples/wiremock-jetty/src/test/java/com/example/WiremockServerApplicationTests.java
@@ -1,14 +1,17 @@
package com.example;
-import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
-import static com.github.tomakehurst.wiremock.client.WireMock.get;
-import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
-import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
-import static org.assertj.core.api.Assertions.assertThat;
+import com.github.tomakehurst.wiremock.http.Fault;
+import com.github.tomakehurst.wiremock.junit.WireMockClassRule;
+import org.apache.http.MalformedChunkCodingException;
+import org.apache.http.NoHttpResponseException;
+import org.apache.http.client.ClientProtocolException;
import org.junit.ClassRule;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
+
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
@@ -16,7 +19,12 @@ import org.springframework.cloud.contract.wiremock.WireMockSpring;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
-import com.github.tomakehurst.wiremock.junit.WireMockClassRule;
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.CoreMatchers.instanceOf;
@RunWith(SpringRunner.class)
@SpringBootTest(properties="app.baseUrl=http://localhost:6061", webEnvironment=WebEnvironment.NONE)
@@ -26,14 +34,41 @@ public class WiremockServerApplicationTests {
@ClassRule
public static WireMockClassRule wiremock = new WireMockClassRule(WireMockSpring.options().port(6061));
+ @Rule
+ public ExpectedException expected = ExpectedException.none();
+
@Autowired
private Service service;
@Test
- public void contextLoads() throws Exception {
+ public void hello() throws Exception {
stubFor(get(urlEqualTo("/resource"))
.willReturn(aResponse().withHeader("Content-Type", "text/plain").withBody("Hello World!")));
assertThat(this.service.go()).isEqualTo("Hello World!");
}
+ @Test
+ public void randomData() throws Exception {
+ stubFor(get(urlEqualTo("/resource"))
+ .willReturn(aResponse().withFault(Fault.RANDOM_DATA_THEN_CLOSE)));
+ expected.expectCause(instanceOf(ClientProtocolException.class));
+ assertThat(this.service.go()).isEqualTo("Oops!");
+ }
+
+ @Test
+ public void emptyResponse() throws Exception {
+ stubFor(get(urlEqualTo("/resource"))
+ .willReturn(aResponse().withFault(Fault.EMPTY_RESPONSE)));
+ expected.expectCause(instanceOf(NoHttpResponseException.class));
+ assertThat(this.service.go()).isEqualTo("Oops!");
+ }
+
+ @Test
+ public void malformed() throws Exception {
+ stubFor(get(urlEqualTo("/resource"))
+ .willReturn(aResponse().withFault(Fault.MALFORMED_RESPONSE_CHUNK)));
+ expected.expectCause(instanceOf(MalformedChunkCodingException.class));
+ assertThat(this.service.go()).isEqualTo("Oops!");
+ }
+
}
diff --git a/samples/wiremock-tomcat/src/main/java/com/example/WiremockTestsApplication.java b/samples/wiremock-tomcat/src/main/java/com/example/WiremockTestsApplication.java
index fa59698f17..926417a038 100644
--- a/samples/wiremock-tomcat/src/main/java/com/example/WiremockTestsApplication.java
+++ b/samples/wiremock-tomcat/src/main/java/com/example/WiremockTestsApplication.java
@@ -3,6 +3,7 @@ package com.example;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -13,8 +14,8 @@ import org.springframework.web.client.RestTemplate;
public class WiremockTestsApplication {
@Bean
- public RestTemplate restTemplate() {
- return new RestTemplate();
+ public RestTemplate restTemplate(RestTemplateBuilder builder) {
+ return builder.build();
}
public static void main(String[] args) {
diff --git a/samples/wiremock-tomcat/src/test/java/com/example/WiremockHttpsServerApplicationTests.java b/samples/wiremock-tomcat/src/test/java/com/example/WiremockHttpsServerApplicationTests.java
index add1d311fe..9e30002fdf 100644
--- a/samples/wiremock-tomcat/src/test/java/com/example/WiremockHttpsServerApplicationTests.java
+++ b/samples/wiremock-tomcat/src/test/java/com/example/WiremockHttpsServerApplicationTests.java
@@ -11,6 +11,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cloud.contract.wiremock.AutoConfigureHttpClient;
import org.springframework.cloud.contract.wiremock.WireMockSpring;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
@@ -21,6 +22,7 @@ import com.github.tomakehurst.wiremock.junit.WireMockClassRule;
@RunWith(SpringRunner.class)
@SpringBootTest("app.baseUrl=https://localhost:6443")
@DirtiesContext
+@AutoConfigureHttpClient
public class WiremockHttpsServerApplicationTests {
@ClassRule
diff --git a/samples/wiremock-tomcat/src/test/java/com/example/WiremockServerApplicationTests.java b/samples/wiremock-tomcat/src/test/java/com/example/WiremockServerApplicationTests.java
index d7f2980b6f..d4c5656527 100644
--- a/samples/wiremock-tomcat/src/test/java/com/example/WiremockServerApplicationTests.java
+++ b/samples/wiremock-tomcat/src/test/java/com/example/WiremockServerApplicationTests.java
@@ -1,14 +1,18 @@
package com.example;
-import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
-import static com.github.tomakehurst.wiremock.client.WireMock.get;
-import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
-import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
-import static org.assertj.core.api.Assertions.assertThat;
+import java.io.IOException;
+import com.github.tomakehurst.wiremock.http.Fault;
+import com.github.tomakehurst.wiremock.junit.WireMockClassRule;
+
+import org.apache.http.NoHttpResponseException;
+import org.apache.http.client.ClientProtocolException;
import org.junit.ClassRule;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
+
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
@@ -16,7 +20,12 @@ import org.springframework.cloud.contract.wiremock.WireMockSpring;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
-import com.github.tomakehurst.wiremock.junit.WireMockClassRule;
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.CoreMatchers.instanceOf;
@RunWith(SpringRunner.class)
@SpringBootTest(properties="app.baseUrl=http://localhost:6067", webEnvironment=WebEnvironment.NONE)
@@ -26,6 +35,9 @@ public class WiremockServerApplicationTests {
@ClassRule
public static WireMockClassRule wiremock = new WireMockClassRule(WireMockSpring.options().port(6067));
+ @Rule
+ public ExpectedException expected = ExpectedException.none();
+
@Autowired
private Service service;
@@ -36,4 +48,30 @@ public class WiremockServerApplicationTests {
assertThat(this.service.go()).isEqualTo("Hello World!");
}
+ @Test
+ public void randomData() throws Exception {
+ stubFor(get(urlEqualTo("/resource"))
+ .willReturn(aResponse().withFault(Fault.RANDOM_DATA_THEN_CLOSE)));
+ expected.expectCause(instanceOf(ClientProtocolException.class));
+ assertThat(this.service.go()).isEqualTo("Oops!");
+ }
+
+ @Test
+ public void emptyResponse() throws Exception {
+ stubFor(get(urlEqualTo("/resource"))
+ .willReturn(aResponse().withFault(Fault.EMPTY_RESPONSE)));
+ expected.expectCause(instanceOf(NoHttpResponseException.class));
+ assertThat(this.service.go()).isEqualTo("Oops!");
+ }
+
+ @Test
+ public void malformed() throws Exception {
+ stubFor(get(urlEqualTo("/resource"))
+ .willReturn(aResponse().withFault(Fault.MALFORMED_RESPONSE_CHUNK)));
+ // It's a different exception type than Jetty, but it's in the right ballpark
+ expected.expectCause(instanceOf(IOException.class));
+ expected.expectMessage("chunk");
+ assertThat(this.service.go()).isEqualTo("Oops!");
+ }
+
}
diff --git a/spring-cloud-contract-dependencies/pom.xml b/spring-cloud-contract-dependencies/pom.xml
index ea304b54f1..393d99b475 100644
--- a/spring-cloud-contract-dependencies/pom.xml
+++ b/spring-cloud-contract-dependencies/pom.xml
@@ -5,7 +5,7 @@
spring-cloud-dependencies-parent
org.springframework.cloud
- 1.3.1.BUILD-SNAPSHOT
+ 1.3.2.BUILD-SNAPSHOT
spring-cloud-contract-dependencies
diff --git a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/build.gradle b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/build.gradle
index 1c4613a77b..dc8a6bca6f 100644
--- a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/build.gradle
+++ b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/build.gradle
@@ -23,7 +23,7 @@ ext {
]
}
-project.version = findProperty('verifierVersion') ?: '1.1.0.BUILD-SNAPSHOT'
+project.version = findProperty('verifierVersion') ?: '1.1.1.BUILD-SNAPSHOT'
apply plugin: 'groovy'
apply from: "$rootDir/gradle/release.gradle"
apply plugin: 'eclipse'
diff --git a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/gradle.properties b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/gradle.properties
index dc488d8fa7..1c3fb93350 100644
--- a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/gradle.properties
+++ b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/gradle.properties
@@ -16,5 +16,5 @@
nexusUsername =
nexusPassword =
-verifierVersion=1.1.0.BUILD-SNAPSHOT
+verifierVersion=1.1.1.BUILD-SNAPSHOT
org.gradle.daemon=false
\ No newline at end of file
diff --git a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/bootSimple/gradle.properties b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/bootSimple/gradle.properties
index 5b12dfc27a..ef921a31eb 100644
--- a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/bootSimple/gradle.properties
+++ b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/bootSimple/gradle.properties
@@ -15,5 +15,5 @@
#
wiremockVersion=2.5.1
jsonAssertVersion=0.4.8
-verifierVersion=1.1.0.BUILD-SNAPSHOT
+verifierVersion=1.1.1.BUILD-SNAPSHOT
diff --git a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/gradle.properties b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/gradle.properties
index 71b597b876..6f9a459444 100644
--- a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/gradle.properties
+++ b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/gradle.properties
@@ -15,4 +15,4 @@
#
wiremockVersion=2.5.1
jsonAssertVersion=0.4.8
-verifierVersion=1.1.0.BUILD-SNAPSHOT
+verifierVersion=1.1.1.BUILD-SNAPSHOT
diff --git a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/sampleProject/gradle.properties b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/sampleProject/gradle.properties
index c6339b65ea..33ab5a5b1c 100644
--- a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/sampleProject/gradle.properties
+++ b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/sampleProject/gradle.properties
@@ -15,4 +15,4 @@
#
wiremockVersion=2.5.1
jsonAssertVersion=0.4.8
-verifierVersion=1.1.0.BUILD-SNAPSHOT
\ No newline at end of file
+verifierVersion=1.1.1.BUILD-SNAPSHOT
\ No newline at end of file
diff --git a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/scenarioProject/gradle.properties b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/scenarioProject/gradle.properties
index 5b12dfc27a..ef921a31eb 100644
--- a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/scenarioProject/gradle.properties
+++ b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/scenarioProject/gradle.properties
@@ -15,5 +15,5 @@
#
wiremockVersion=2.5.1
jsonAssertVersion=0.4.8
-verifierVersion=1.1.0.BUILD-SNAPSHOT
+verifierVersion=1.1.1.BUILD-SNAPSHOT
diff --git a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/complex-remote-contracts/pom.xml b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/complex-remote-contracts/pom.xml
index 5f68ede9cf..50f3621a39 100644
--- a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/complex-remote-contracts/pom.xml
+++ b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/complex-remote-contracts/pom.xml
@@ -30,7 +30,7 @@
org.springframework.cloud
spring-cloud-contract-maven-plugin
- 1.1.0.BUILD-SNAPSHOT
+ 1.1.1.BUILD-SNAPSHOT
com/example/server
diff --git a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/pact/pom.xml b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/pact/pom.xml
index 297e4e005e..b4e5c89df7 100644
--- a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/pact/pom.xml
+++ b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/pact/pom.xml
@@ -26,7 +26,7 @@
0.1
- 1.1.0.BUILD-SNAPSHOT
+ 1.1.1.BUILD-SNAPSHOT
diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BlockBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BlockBuilder.groovy
index de3f392561..2f2ef6da5c 100644
--- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BlockBuilder.groovy
+++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BlockBuilder.groovy
@@ -27,7 +27,6 @@ import groovy.transform.PackageScope
*
* @since 1.0.0
*/
-@PackageScope
@CompileStatic
class BlockBuilder {
@@ -43,21 +42,33 @@ class BlockBuilder {
builder = new StringBuilder()
}
+ /**
+ * Adds indents to start a new block
+ */
BlockBuilder startBlock() {
indents++
return this
}
+ /**
+ * Ends block by removing indents
+ */
BlockBuilder endBlock() {
indents--
return this
}
+ /**
+ * Creates a block and adds indents
+ */
BlockBuilder indent() {
startBlock().startBlock()
return this
}
+ /**
+ * Removes indents and closes the block
+ */
BlockBuilder unindent() {
endBlock().endBlock()
return this
@@ -81,6 +92,7 @@ class BlockBuilder {
}
}
+ @PackageScope
BlockBuilder addBlock(MethodBuilder methodBuilder) {
startBlock()
methodBuilder.appendTo(this)
@@ -89,6 +101,11 @@ class BlockBuilder {
return this
}
+ /**
+ * Adds the given text at the end of the line
+ *
+ * @return updated BlockBuilder
+ */
BlockBuilder addAtTheEnd(String toAdd) {
String lastChar = builder.charAt(builder.length() - 1) as String
String secondLastChar = builder.length() >= 2 ? builder.charAt(builder.length() - 2) as String : ""
@@ -114,6 +131,12 @@ class BlockBuilder {
return character == "{" || character == toAdd
}
+ /**
+ * Updates the current text with the provided one
+ *
+ * @param contents - text to replace the current content with
+ * @return updated Block Builder
+ */
BlockBuilder updateContents(String contents) {
this.builder.replace(0, this.builder.length(), contents)
return this
diff --git a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/AutoConfigureHttpClient.java b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/AutoConfigureHttpClient.java
new file mode 100644
index 0000000000..48f3e9d60b
--- /dev/null
+++ b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/AutoConfigureHttpClient.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2012-2015 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.contract.wiremock;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.springframework.boot.test.autoconfigure.properties.PropertyMapping;
+import org.springframework.context.annotation.Import;
+
+/**
+ * Annotation for test classes that want to install a RestTemplateCustomizer that sets up
+ * a Spring Boot app to ignore SSL errors. Use only in tests!
+ *
+ * @author Dave Syer
+ *
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Import(WireMockRestTemplateConfiguration.class)
+@PropertyMapping("wiremock.server")
+public @interface AutoConfigureHttpClient {
+}
diff --git a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/AutoConfigureWireMock.java b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/AutoConfigureWireMock.java
index fb8db93eb1..b1337ba0c3 100644
--- a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/AutoConfigureWireMock.java
+++ b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/AutoConfigureWireMock.java
@@ -39,6 +39,7 @@ import org.springframework.context.annotation.Import;
@Documented
@Import(WireMockConfiguration.class)
@PropertyMapping("wiremock.server")
+@AutoConfigureHttpClient
public @interface AutoConfigureWireMock {
int port() default 8080;
diff --git a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/JettyFaultInjector.java b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/JettyFaultInjector.java
new file mode 100644
index 0000000000..ab3e2822b8
--- /dev/null
+++ b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/JettyFaultInjector.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2016-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.cloud.contract.wiremock;
+
+import java.io.IOException;
+import java.nio.channels.ByteChannel;
+
+import javax.servlet.http.HttpServletResponse;
+
+import com.github.tomakehurst.wiremock.core.FaultInjector;
+import com.google.common.base.Charsets;
+
+import org.eclipse.jetty.io.ChannelEndPoint;
+import org.eclipse.jetty.server.HttpChannel;
+import org.eclipse.jetty.server.Response;
+import org.eclipse.jetty.util.BufferUtil;
+
+import static com.github.tomakehurst.wiremock.common.Exceptions.throwUnchecked;
+import static com.github.tomakehurst.wiremock.jetty9.JettyUtils.unwrapResponse;
+
+/**
+ * @author Dave Syer
+ *
+ */
+public class JettyFaultInjector implements FaultInjector {
+
+ private static final byte[] GARBAGE = "lskdu018973t09sylgasjkfg1][]'./.sdlv"
+ .getBytes(Charsets.UTF_8);
+
+ private final Response response;
+ private final ByteChannel socket;
+
+ public JettyFaultInjector(HttpServletResponse response) {
+ this.response = unwrapResponse(response);
+ this.socket = socket();
+ }
+
+ @Override
+ public void emptyResponseAndCloseConnection() {
+ try {
+ this.socket.close();
+ }
+ catch (IOException e) {
+ throwUnchecked(e);
+ }
+ }
+
+ @Override
+ public void malformedResponseChunk() {
+ try {
+ this.response.setStatus(200);
+ this.response.flushBuffer();
+ this.socket.write(BufferUtil.toBuffer(GARBAGE));
+ this.socket.close();
+ }
+ catch (IOException e) {
+ throwUnchecked(e);
+ }
+
+ }
+
+ @Override
+ public void randomDataAndCloseConnection() {
+ try {
+ this.socket.write(BufferUtil.toBuffer(GARBAGE));
+ this.socket.close();
+ }
+ catch (IOException e) {
+ throwUnchecked(e);
+ }
+ }
+
+ private ByteChannel socket() {
+ HttpChannel httpChannel = this.response.getHttpOutput().getHttpChannel();
+ ChannelEndPoint ep = (ChannelEndPoint) httpChannel.getEndPoint();
+ return ep.getChannel();
+ }
+
+}
diff --git a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/JettyFaultInjectorFactory.java b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/JettyFaultInjectorFactory.java
new file mode 100644
index 0000000000..00ebaa6c3b
--- /dev/null
+++ b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/JettyFaultInjectorFactory.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2016-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.cloud.contract.wiremock;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.github.tomakehurst.wiremock.core.FaultInjector;
+import com.github.tomakehurst.wiremock.servlet.FaultInjectorFactory;
+
+/**
+ * @author Dave Syer
+ *
+ */
+public class JettyFaultInjectorFactory implements FaultInjectorFactory {
+
+ @Override
+ public FaultInjector buildFaultInjector(HttpServletRequest httpServletRequest,
+ HttpServletResponse httpServletResponse) {
+ return new JettyFaultInjector(httpServletResponse);
+ }
+
+}
diff --git a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/SpringBootHttpServerFactory.java b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/SpringBootHttpServerFactory.java
index ecf36be8cb..03d655b972 100644
--- a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/SpringBootHttpServerFactory.java
+++ b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/SpringBootHttpServerFactory.java
@@ -18,11 +18,27 @@ package org.springframework.cloud.contract.wiremock;
import javax.servlet.ServletContext;
+import io.undertow.Undertow.Builder;
+
+import com.github.tomakehurst.wiremock.common.HttpsSettings;
+import com.github.tomakehurst.wiremock.common.Notifier;
+import com.github.tomakehurst.wiremock.core.Options;
+import com.github.tomakehurst.wiremock.core.WireMockApp;
+import com.github.tomakehurst.wiremock.http.AdminRequestHandler;
+import com.github.tomakehurst.wiremock.http.HttpServer;
+import com.github.tomakehurst.wiremock.http.HttpServerFactory;
+import com.github.tomakehurst.wiremock.http.RequestHandler;
+import com.github.tomakehurst.wiremock.http.StubRequestHandler;
+import com.github.tomakehurst.wiremock.servlet.FaultInjectorFactory;
+import com.github.tomakehurst.wiremock.servlet.NoFaultInjectorFactory;
+import com.github.tomakehurst.wiremock.servlet.WireMockHandlerDispatchingServlet;
+
import org.apache.catalina.connector.Connector;
import org.eclipse.jetty.server.ConnectionFactory;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
+
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
@@ -64,19 +80,6 @@ import org.springframework.context.support.GenericApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.web.context.ServletContextAware;
-import com.github.tomakehurst.wiremock.common.HttpsSettings;
-import com.github.tomakehurst.wiremock.common.Notifier;
-import com.github.tomakehurst.wiremock.core.Options;
-import com.github.tomakehurst.wiremock.core.WireMockApp;
-import com.github.tomakehurst.wiremock.http.AdminRequestHandler;
-import com.github.tomakehurst.wiremock.http.HttpServer;
-import com.github.tomakehurst.wiremock.http.HttpServerFactory;
-import com.github.tomakehurst.wiremock.http.RequestHandler;
-import com.github.tomakehurst.wiremock.http.StubRequestHandler;
-import com.github.tomakehurst.wiremock.servlet.WireMockHandlerDispatchingServlet;
-
-import io.undertow.Undertow.Builder;
-
/**
* @author Dave Syer
*
@@ -258,6 +261,8 @@ class WiremockServerConfiguration {
@Autowired
private StubRequestHandler stubRequestHandler;
@Autowired
+ private FaultInjectorFactory faultInjectorFactory;
+ @Autowired
private Options options;
@Bean(name = DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
@@ -265,6 +270,10 @@ class WiremockServerConfiguration {
ServletRegistrationBean reg = new ServletRegistrationBean();
reg.addInitParameter(RequestHandler.HANDLER_CLASS_KEY,
StubRequestHandler.class.getName());
+ if (WiremockServerConfiguration.this.faultInjectorFactory != null) {
+ reg.addInitParameter(FaultInjectorFactory.INJECTOR_CLASS_KEY,
+ FaultInjectorFactory.class.getName());
+ }
reg.setServlet(new WireMockHandlerDispatchingServlet());
reg.setName("stub");
reg.addUrlMappings("/");
@@ -293,6 +302,10 @@ class WiremockServerConfiguration {
WiremockServerConfiguration.this.stubRequestHandler);
servletContext.setAttribute(Notifier.KEY,
WiremockServerConfiguration.this.options.notifier());
+ if (WiremockServerConfiguration.this.faultInjectorFactory != null) {
+ servletContext.setAttribute(FaultInjectorFactory.class.getName(),
+ WiremockServerConfiguration.this.faultInjectorFactory);
+ }
}
};
}
@@ -367,6 +380,11 @@ class ContainerConfiguration {
return tomcat;
}
+ @Bean
+ public FaultInjectorFactory faultInjectorFactory() {
+ return new TomcatFaultInjectorFactory();
+ }
+
@EventListener
public void serverUp(EmbeddedServletContainerInitializedEvent event) {
if (this.connector != null) {
@@ -417,6 +435,11 @@ class ContainerConfiguration {
return undertow;
}
+ @Bean
+ public FaultInjectorFactory faultInjectorFactory() {
+ return new NoFaultInjectorFactory();
+ }
+
@EventListener
public void serverUp(EmbeddedServletContainerInitializedEvent event) {
if (this.port != null) {
@@ -457,6 +480,11 @@ class ContainerConfiguration {
return jetty;
}
+ @Bean
+ public JettyFaultInjectorFactory faultInjectorFactory() {
+ return new JettyFaultInjectorFactory();
+ }
+
private org.eclipse.jetty.server.Connector createStandardConnector(
Server server) {
ServerConnector connector = new ServerConnector(server, -1, -1);
diff --git a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/TomcatFaultInjector.java b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/TomcatFaultInjector.java
new file mode 100644
index 0000000000..0abf792f85
--- /dev/null
+++ b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/TomcatFaultInjector.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2016-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.cloud.contract.wiremock;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.nio.ByteBuffer;
+
+import javax.servlet.http.HttpServletResponse;
+
+import com.github.tomakehurst.wiremock.common.Exceptions;
+import com.github.tomakehurst.wiremock.core.FaultInjector;
+import com.google.common.base.Charsets;
+
+import org.apache.coyote.Response;
+import org.apache.tomcat.util.net.SocketWrapperBase;
+
+import org.springframework.util.ReflectionUtils;
+
+import static com.github.tomakehurst.wiremock.common.Exceptions.throwUnchecked;
+
+/**
+ * @author Dave Syer
+ *
+ */
+public class TomcatFaultInjector implements FaultInjector {
+
+ private static final byte[] GARBAGE = "lskdu018973t09sylgasjkfg1][]'./.sdlv"
+ .getBytes(Charsets.UTF_8);
+ private final Response response;
+ private SocketWrapperBase> socket;
+
+ public TomcatFaultInjector(HttpServletResponse response) {
+ this.response = ((org.apache.catalina.connector.Response) getField(response,
+ "response")).getCoyoteResponse();
+ this.socket = (SocketWrapperBase>) getField(
+ getField(this.response, "outputBuffer"), "socketWrapper");
+ }
+
+ private Object getField(Object target, String string) {
+ Field field = ReflectionUtils.findField(target.getClass(), string);
+ ReflectionUtils.makeAccessible(field);
+ return ReflectionUtils.getField(field, target);
+ }
+
+ @Override
+ public void emptyResponseAndCloseConnection() {
+ try {
+ this.socket.close();
+ }
+ catch (IOException e) {
+ Exceptions.throwUnchecked(e);
+ }
+ }
+
+ @Override
+ public void malformedResponseChunk() {
+ try {
+ this.response.sendHeaders();
+ this.response.doWrite(ByteBuffer.wrap(GARBAGE));
+ this.socket.flush(true);
+ this.socket.close();
+ }
+ catch (IOException e) {
+ throwUnchecked(e);
+ }
+ }
+
+ @Override
+ public void randomDataAndCloseConnection() {
+ try {
+ this.socket.write(true, GARBAGE, 0, GARBAGE.length);
+ this.socket.flush(true);
+ this.socket.close();
+ }
+ catch (IOException e) {
+ throwUnchecked(e);
+ }
+ }
+
+}
diff --git a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/TomcatFaultInjectorFactory.java b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/TomcatFaultInjectorFactory.java
new file mode 100644
index 0000000000..17cbcaea2d
--- /dev/null
+++ b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/TomcatFaultInjectorFactory.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2016-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.cloud.contract.wiremock;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.github.tomakehurst.wiremock.core.FaultInjector;
+import com.github.tomakehurst.wiremock.servlet.FaultInjectorFactory;
+
+/**
+ * @author Dave Syer
+ *
+ */
+public class TomcatFaultInjectorFactory implements FaultInjectorFactory {
+
+ @Override
+ public FaultInjector buildFaultInjector(HttpServletRequest httpServletRequest,
+ HttpServletResponse httpServletResponse) {
+ return new TomcatFaultInjector(httpServletResponse);
+ }
+
+}
diff --git a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/WireMockRestTemplateConfiguration.java b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/WireMockRestTemplateConfiguration.java
new file mode 100644
index 0000000000..c543b1a556
--- /dev/null
+++ b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/WireMockRestTemplateConfiguration.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2016-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.cloud.contract.wiremock;
+
+import org.apache.http.client.HttpClient;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.ssl.SSLContextBuilder;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.web.client.RestTemplateCustomizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * @author Dave Syer
+ *
+ */
+@Configuration
+public class WireMockRestTemplateConfiguration {
+
+ @Bean
+ @ConditionalOnClass(SSLContextBuilder.class)
+ public RestTemplateCustomizer restTemplateCustomizer() {
+ return new RestTemplateCustomizer() {
+ @Override
+ public void customize(RestTemplate restTemplate) {
+ HttpComponentsClientHttpRequestFactory factory = (HttpComponentsClientHttpRequestFactory) restTemplate
+ .getRequestFactory();
+ factory.setHttpClient(createSslHttpClient());
+ }
+
+ private HttpClient createSslHttpClient() {
+ try {
+ SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
+ new SSLContextBuilder().loadTrustMaterial(null,
+ TrustSelfSignedStrategy.INSTANCE).build(),
+ NoopHostnameVerifier.INSTANCE);
+ return HttpClients.custom().setSSLSocketFactory(socketFactory)
+ .build();
+ }
+ catch (Exception ex) {
+ throw new IllegalStateException("Unable to create SSL HttpClient",
+ ex);
+ }
+ }
+ };
+ }
+
+}
diff --git a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/WireMockSpring.java b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/WireMockSpring.java
index e23dc40879..632ccc7b3d 100644
--- a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/WireMockSpring.java
+++ b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/WireMockSpring.java
@@ -18,13 +18,14 @@ package org.springframework.cloud.contract.wiremock;
import javax.net.ssl.HttpsURLConnection;
+import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
+
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.ssl.SSLContexts;
import org.junit.Assert;
-import org.springframework.util.ClassUtils;
-import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
+import org.springframework.util.ClassUtils;
/**
* Convenience factory class for a {@link WireMockConfiguration} that knows how to use
diff --git a/spring-cloud-contract-wiremock/src/main/resources/META-INF/spring.factories b/spring-cloud-contract-wiremock/src/main/resources/META-INF/spring.factories
index 6c450975aa..9ac5aa6677 100644
--- a/spring-cloud-contract-wiremock/src/main/resources/META-INF/spring.factories
+++ b/spring-cloud-contract-wiremock/src/main/resources/META-INF/spring.factories
@@ -4,4 +4,4 @@ org.springframework.cloud.contract.wiremock.WireMockApplicationListener
# RestDocs Auto Configuration
org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs=\
-org.springframework.cloud.contract.wiremock.restdocs.WireMockRestDocsConfiguration
\ No newline at end of file
+org.springframework.cloud.contract.wiremock.restdocs.WireMockRestDocsConfiguration
diff --git a/spring-cloud-contract-wiremock/src/test/java/org/springframework/cloud/contract/wiremock/WiremockServerApplicationTests.java b/spring-cloud-contract-wiremock/src/test/java/org/springframework/cloud/contract/wiremock/WiremockServerApplicationTests.java
index 34d7f57f9e..dd6a002d33 100644
--- a/spring-cloud-contract-wiremock/src/test/java/org/springframework/cloud/contract/wiremock/WiremockServerApplicationTests.java
+++ b/spring-cloud-contract-wiremock/src/test/java/org/springframework/cloud/contract/wiremock/WiremockServerApplicationTests.java
@@ -1,21 +1,22 @@
package org.springframework.cloud.contract.wiremock;
-import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
-import static com.github.tomakehurst.wiremock.client.WireMock.get;
-import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
-import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
-import static org.assertj.core.api.Assertions.assertThat;
+import com.github.tomakehurst.wiremock.junit.WireMockClassRule;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
+
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
-import com.github.tomakehurst.wiremock.junit.WireMockClassRule;
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
+import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringRunner.class)
@SpringBootTest(classes=WiremockTestsApplication.class, properties="app.baseUrl=http://localhost:8080", webEnvironment=WebEnvironment.NONE)
@@ -29,7 +30,7 @@ public class WiremockServerApplicationTests {
private Service service;
@Test
- public void contextLoads() throws Exception {
+ public void hello() throws Exception {
stubFor(get(urlEqualTo("/test"))
.willReturn(aResponse().withHeader("Content-Type", "text/plain").withBody("Hello World!")));
assertThat(this.service.go()).isEqualTo("Hello World!");