Merge branch 'master' into 2.0.x
This commit is contained in:
@@ -4,16 +4,10 @@
|
||||
|
||||
|
||||
Modules giving you the possibility to use
|
||||
http://wiremock.org[WireMock] with different servers by using the
|
||||
"ambient" server embedded in a Spring Boot application. Check out the
|
||||
http://wiremock.org[WireMock] in a Spring Boot application. Check out the
|
||||
https://github.com/spring-cloud/spring-cloud-contract/tree/{branch}/samples[samples]
|
||||
for more details.
|
||||
|
||||
IMPORTANT: The Spring Cloud Release Train BOM imports `spring-cloud-contract-dependencies`
|
||||
which in turn has exclusions for the dependencies needed by WireMock. This might lead to a situation that
|
||||
even if you're not using Spring Cloud Contract then your dependencies will be influenced
|
||||
anyways.
|
||||
|
||||
If you have a Spring Boot application that uses Tomcat as an embedded
|
||||
server, for example (the default with `spring-boot-starter-web`), then
|
||||
you can simply add `spring-cloud-contract-wiremock` to your classpath
|
||||
|
||||
@@ -76,7 +76,6 @@
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<version>2.8.2</version>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<jetty.version>9.2.13.v20150730</jetty.version>
|
||||
<spring-cloud-contract.version>2.0.0.BUILD-SNAPSHOT</spring-cloud-contract.version>
|
||||
</properties>
|
||||
|
||||
@@ -51,7 +50,7 @@
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.tomakehurst</groupId>
|
||||
<artifactId>wiremock</artifactId>
|
||||
<artifactId>wiremock-standalone</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
@@ -66,7 +66,6 @@
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<version>2.8.2</version>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
|
||||
@@ -76,7 +76,6 @@
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<version>2.8.2</version>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
|
||||
@@ -76,7 +76,6 @@
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<version>2.8.2</version>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
|
||||
@@ -82,42 +82,8 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.tomakehurst</groupId>
|
||||
<artifactId>wiremock</artifactId>
|
||||
<artifactId>wiremock-standalone</artifactId>
|
||||
<version>${wiremock.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.mortbay.jetty</groupId>
|
||||
<artifactId>jetty</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.jayway.jsonpath</groupId>
|
||||
<artifactId>json-path</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>net.sf.jopt-simple</groupId>
|
||||
<artifactId>jopt-simple</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jetty-servlet</artifactId>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jetty-servlets</artifactId>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jetty-webapp</artifactId>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.toomuchcoding.jsonassert</groupId>
|
||||
|
||||
@@ -10,15 +10,16 @@ import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.github.jknack.handlebars.Helper;
|
||||
import com.github.tomakehurst.wiremock.WireMockServer;
|
||||
import com.github.tomakehurst.wiremock.client.WireMock;
|
||||
import com.github.tomakehurst.wiremock.common.Slf4jNotifier;
|
||||
import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
|
||||
import com.github.tomakehurst.wiremock.extension.responsetemplating.ResponseTemplateTransformer;
|
||||
import com.github.tomakehurst.wiremock.stubbing.StubMapping;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.cloud.contract.stubrunner.HttpServerStub;
|
||||
import org.springframework.cloud.contract.verifier.builder.handlebars.HandlebarsEscapeHelper;
|
||||
import org.springframework.cloud.contract.verifier.builder.handlebars.HandlebarsJsonPathHelper;
|
||||
@@ -28,6 +29,8 @@ import org.springframework.util.SocketUtils;
|
||||
import org.springframework.util.StreamUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import wiremock.com.github.jknack.handlebars.Helper;
|
||||
|
||||
/**
|
||||
* Abstraction over WireMock as a HTTP Server Stub
|
||||
*
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.tomakehurst</groupId>
|
||||
<artifactId>wiremock</artifactId>
|
||||
<artifactId>wiremock-standalone</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spockframework</groupId>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.springframework.cloud.contract.verifier.converter
|
||||
|
||||
import com.google.common.collect.ListMultimap
|
||||
import wiremock.com.google.common.collect.ListMultimap
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.util.logging.Slf4j
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
|
||||
@@ -35,7 +35,7 @@ import org.springframework.cloud.contract.stubrunner.StubRunner;
|
||||
import org.springframework.cloud.contract.stubrunner.StubRunnerOptions;
|
||||
import org.springframework.cloud.contract.stubrunner.StubRunnerOptionsBuilder;
|
||||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static wiremock.com.google.common.base.Strings.isNullOrEmpty;
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.tomakehurst</groupId>
|
||||
<artifactId>wiremock</artifactId>
|
||||
<artifactId>wiremock-standalone</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.toomuchcoding.jsonassert</groupId>
|
||||
|
||||
@@ -20,7 +20,7 @@ import java.nio.charset.StandardCharsets
|
||||
import java.nio.file.Path
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
import com.google.common.collect.ListMultimap
|
||||
import wiremock.com.google.common.collect.ListMultimap
|
||||
import groovy.transform.PackageScope
|
||||
import org.apache.commons.lang3.StringUtils
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.springframework.cloud.contract.verifier.builder.handlebars
|
||||
|
||||
import com.github.jknack.handlebars.Helper
|
||||
import com.github.jknack.handlebars.Options
|
||||
import wiremock.com.github.jknack.handlebars.Helper
|
||||
import wiremock.com.github.jknack.handlebars.Options
|
||||
import com.github.tomakehurst.wiremock.extension.responsetemplating.RequestTemplateModel
|
||||
import groovy.transform.CompileStatic
|
||||
import org.apache.commons.lang3.StringEscapeUtils
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.springframework.cloud.contract.verifier.builder.handlebars
|
||||
|
||||
import com.github.jknack.handlebars.Helper
|
||||
import com.github.jknack.handlebars.Options
|
||||
import wiremock.com.github.jknack.handlebars.Helper
|
||||
import wiremock.com.github.jknack.handlebars.Options
|
||||
import com.github.tomakehurst.wiremock.extension.responsetemplating.RequestTemplateModel
|
||||
import com.jayway.jsonpath.DocumentContext
|
||||
import com.jayway.jsonpath.JsonPath
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
package org.springframework.cloud.contract.verifier.file
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap
|
||||
import com.google.common.collect.ListMultimap
|
||||
import wiremock.com.google.common.collect.ArrayListMultimap
|
||||
import wiremock.com.google.common.collect.ListMultimap
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.util.logging.Slf4j
|
||||
import org.apache.commons.lang3.SystemUtils
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.springframework.cloud.contract.verifier.template
|
||||
|
||||
import com.github.jknack.handlebars.Handlebars
|
||||
import com.github.jknack.handlebars.Template
|
||||
import wiremock.com.github.jknack.handlebars.Handlebars
|
||||
import wiremock.com.github.jknack.handlebars.Template
|
||||
import groovy.transform.CompileStatic
|
||||
import org.springframework.cloud.contract.spec.ContractTemplate
|
||||
import org.springframework.cloud.contract.spec.internal.HandlebarsContractTemplate
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.springframework.cloud.contract.verifier.file
|
||||
|
||||
import com.google.common.collect.ListMultimap
|
||||
import wiremock.com.google.common.collect.ListMultimap
|
||||
import spock.lang.Specification
|
||||
|
||||
import java.nio.file.Path
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package org.springframework.cloud.contract.verifier.messaging.amqp
|
||||
|
||||
import com.google.common.collect.ImmutableMap
|
||||
import wiremock.com.google.common.collect.ImmutableMap
|
||||
import org.springframework.amqp.core.Binding
|
||||
import org.springframework.amqp.core.BindingBuilder
|
||||
import org.springframework.amqp.core.DirectExchange
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.github.tomakehurst</groupId>
|
||||
<artifactId>wiremock</artifactId>
|
||||
<artifactId>wiremock-standalone</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
@@ -28,17 +28,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-undertow</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jetty</artifactId>
|
||||
<optional>true</optional>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,515 +0,0 @@
|
||||
/*
|
||||
* Copyright 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 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;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.boot.Banner.Mode;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.DefaultServletWebServerFactoryCustomizer;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.context.event.ApplicationPreparedEvent;
|
||||
import org.springframework.boot.web.context.WebServerInitializedEvent;
|
||||
import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer;
|
||||
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
|
||||
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
|
||||
import org.springframework.boot.web.embedded.undertow.UndertowBuilderCustomizer;
|
||||
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
|
||||
import org.springframework.boot.web.server.Ssl;
|
||||
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
|
||||
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||
import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext;
|
||||
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
|
||||
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
|
||||
import org.springframework.cloud.contract.wiremock.ContainerConfiguration.JettyContainerConfiguration;
|
||||
import org.springframework.cloud.contract.wiremock.ContainerConfiguration.TomcatContainerConfiguration;
|
||||
import org.springframework.cloud.contract.wiremock.ContainerConfiguration.UndertowContainerConfiguration;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.ServletContextAware;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
class SpringBootHttpServerFactory implements HttpServerFactory {
|
||||
|
||||
@Override
|
||||
public HttpServer buildHttpServer(Options options,
|
||||
AdminRequestHandler adminRequestHandler,
|
||||
StubRequestHandler stubRequestHandler) {
|
||||
return new SpringBootHttpServer(options, adminRequestHandler, stubRequestHandler);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class SpringBootHttpServer
|
||||
implements HttpServer, ApplicationListener<ApplicationPreparedEvent> {
|
||||
|
||||
private volatile boolean running;
|
||||
private Options options;
|
||||
private AdminRequestHandler adminRequestHandler;
|
||||
private StubRequestHandler stubRequestHandler;
|
||||
private ConfigurableApplicationContext context;
|
||||
|
||||
public SpringBootHttpServer(Options options, AdminRequestHandler adminRequestHandler,
|
||||
StubRequestHandler stubRequestHandler) {
|
||||
this.options = options;
|
||||
this.adminRequestHandler = adminRequestHandler;
|
||||
this.stubRequestHandler = stubRequestHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
this.context = new SpringApplicationBuilder(WiremockServerConfiguration.class)
|
||||
.logStartupInfo(false).bannerMode(Mode.OFF)
|
||||
.properties("spring.cloud.bootstrap.enabled=false").listeners(this).run();
|
||||
this.running = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
this.running = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
return this.running;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int port() {
|
||||
return container().port();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int httpsPort() {
|
||||
return container().httpsPort();
|
||||
}
|
||||
|
||||
private ContainerProperties container() {
|
||||
if (this.context != null) {
|
||||
return this.context.getBean(ContainerProperties.class);
|
||||
}
|
||||
return new ContainerProperties(this.options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationPreparedEvent event) {
|
||||
GenericApplicationContext context = (GenericApplicationContext) event
|
||||
.getApplicationContext();
|
||||
DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();
|
||||
if (beanFactory.containsBean("wireMockOptions")) {
|
||||
// Be idempotent (the event might be emitted more than once)
|
||||
return;
|
||||
}
|
||||
beanFactory.registerSingleton("wireMockOptions", this.options);
|
||||
beanFactory.registerSingleton("adminRequestHandler", this.adminRequestHandler);
|
||||
beanFactory.registerSingleton("stubRequestHandler", this.stubRequestHandler);
|
||||
beanFactory.addBeanPostProcessor(new ServerPropertiesPostProcessor());
|
||||
}
|
||||
|
||||
class ServerPropertiesPostProcessor implements BeanPostProcessor {
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
if (bean instanceof WiremockServerProperties) {
|
||||
WiremockServerProperties server = (WiremockServerProperties) bean;
|
||||
server.setPort(getPort());
|
||||
setupHttps(server, SpringBootHttpServer.this.options.httpsSettings());
|
||||
// TODO: other options
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
private void setupHttps(WiremockServerProperties server,
|
||||
HttpsSettings httpsSettings) {
|
||||
if (httpsSettings.port() < 0 || !httpsSettings.enabled()) {
|
||||
return;
|
||||
}
|
||||
Ssl ssl = server.getSsl();
|
||||
if (ssl == null) {
|
||||
ssl = new Ssl();
|
||||
server.setSsl(ssl);
|
||||
}
|
||||
ssl.setKeyStore(httpsSettings.keyStorePath());
|
||||
ssl.setKeyPassword(httpsSettings.keyStorePassword());
|
||||
if (httpsSettings.hasTrustStore()) {
|
||||
ssl.setTrustStore(httpsSettings.trustStorePath());
|
||||
ssl.setTrustStorePassword(httpsSettings.trustStorePassword());
|
||||
}
|
||||
}
|
||||
|
||||
private int getPort() {
|
||||
if (SpringBootHttpServer.this.options.httpsSettings().port() >= 0) {
|
||||
return SpringBootHttpServer.this.options.httpsSettings().port();
|
||||
}
|
||||
return SpringBootHttpServer.this.options.portNumber();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class WiremockServerProperties implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
|
||||
|
||||
private ServerProperties delegate = new ServerProperties();
|
||||
|
||||
public Integer getPort() {
|
||||
return this.delegate.getPort();
|
||||
}
|
||||
|
||||
public void setPort(Integer port) {
|
||||
this.delegate.setPort(port);
|
||||
}
|
||||
|
||||
public Ssl getSsl() {
|
||||
return this.delegate.getSsl();
|
||||
}
|
||||
|
||||
public void setSsl(Ssl ssl) {
|
||||
this.delegate.setSsl(ssl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customize(ConfigurableServletWebServerFactory server) {
|
||||
new DefaultServletWebServerFactoryCustomizer(this.delegate).customize(server);
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
class ServerPropertiesConfiguration {
|
||||
@Bean
|
||||
public WiremockServerProperties serverProperties() {
|
||||
// Needs to be something that doesn't bind to "server.*"
|
||||
return new WiremockServerProperties();
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import({ TomcatContainerConfiguration.class, JettyContainerConfiguration.class,
|
||||
UndertowContainerConfiguration.class, ServerPropertiesConfiguration.class,
|
||||
BeanPostProcessorsRegistrar.class, ConfigurationPropertiesAutoConfiguration.class,
|
||||
JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class, ContainerProperties.class })
|
||||
class WiremockServerConfiguration {
|
||||
|
||||
@Autowired
|
||||
private AdminRequestHandler adminRequestHandler;
|
||||
@Autowired
|
||||
private StubRequestHandler stubRequestHandler;
|
||||
@Autowired
|
||||
private FaultInjectorFactory faultInjectorFactory;
|
||||
@Autowired
|
||||
private Options options;
|
||||
|
||||
@Bean(name = DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
|
||||
public ServletRegistrationBean<WireMockHandlerDispatchingServlet> stubServletRegistration() {
|
||||
ServletRegistrationBean<WireMockHandlerDispatchingServlet> 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("/");
|
||||
return reg;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ServletRegistrationBean<WireMockHandlerDispatchingServlet> adminServletRegistration() {
|
||||
ServletRegistrationBean<WireMockHandlerDispatchingServlet> reg = new ServletRegistrationBean<>();
|
||||
reg.addInitParameter(RequestHandler.HANDLER_CLASS_KEY,
|
||||
AdminRequestHandler.class.getName());
|
||||
reg.setServlet(new WireMockHandlerDispatchingServlet());
|
||||
reg.setName("admin");
|
||||
reg.addUrlMappings(WireMockApp.ADMIN_CONTEXT_ROOT + "/*");
|
||||
return reg;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ServletContextAware servletContextSetUp() {
|
||||
return new ServletContextAware() {
|
||||
@Override
|
||||
public void setServletContext(ServletContext servletContext) {
|
||||
servletContext.setAttribute(AdminRequestHandler.class.getName(),
|
||||
WiremockServerConfiguration.this.adminRequestHandler);
|
||||
servletContext.setAttribute(StubRequestHandler.class.getName(),
|
||||
WiremockServerConfiguration.this.stubRequestHandler);
|
||||
servletContext.setAttribute(Notifier.KEY,
|
||||
WiremockServerConfiguration.this.options.notifier());
|
||||
if (WiremockServerConfiguration.this.faultInjectorFactory != null) {
|
||||
servletContext.setAttribute(FaultInjectorFactory.class.getName(),
|
||||
WiremockServerConfiguration.this.faultInjectorFactory);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Component
|
||||
class ContainerProperties {
|
||||
|
||||
private Options options;
|
||||
|
||||
private Integer localPort;
|
||||
|
||||
private Integer localHttpsPort;
|
||||
|
||||
@Autowired
|
||||
private ConfigurableApplicationContext context;
|
||||
|
||||
@Autowired
|
||||
public ContainerProperties(Options options) {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
public int port() {
|
||||
if (this.options.httpsSettings().enabled()) {
|
||||
return this.options.portNumber();
|
||||
}
|
||||
if (this.localPort != null) {
|
||||
return this.localPort;
|
||||
}
|
||||
ServletWebServerApplicationContext embedded = (ServletWebServerApplicationContext) this.context;
|
||||
return embedded.getWebServer().getPort();
|
||||
}
|
||||
|
||||
public int httpsPort() {
|
||||
if (this.localHttpsPort != null) {
|
||||
return this.localHttpsPort;
|
||||
}
|
||||
return this.options.httpsSettings().port();
|
||||
}
|
||||
|
||||
public void setLocalPort(int localPort) {
|
||||
this.localPort = localPort;
|
||||
}
|
||||
|
||||
public void setLocalHttpsPort(int localHttpsPort) {
|
||||
this.localHttpsPort = localHttpsPort;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ContainerConfiguration {
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(ServletWebServerFactory.class)
|
||||
@ConditionalOnClass({ TomcatServletWebServerFactory.class, Connector.class })
|
||||
static class TomcatContainerConfiguration {
|
||||
@Autowired
|
||||
private Options options;
|
||||
|
||||
@Autowired
|
||||
private ContainerProperties container;
|
||||
|
||||
private Connector connector;
|
||||
|
||||
@Bean
|
||||
public ServletWebServerFactory servletContainer() {
|
||||
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
|
||||
if (this.options.httpsSettings().enabled()) {
|
||||
tomcat.addAdditionalTomcatConnectors(createStandardConnector());
|
||||
}
|
||||
return tomcat;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FaultInjectorFactory faultInjectorFactory() {
|
||||
return new TomcatFaultInjectorFactory();
|
||||
}
|
||||
|
||||
@EventListener
|
||||
public void serverUp(WebServerInitializedEvent event) {
|
||||
if (this.connector != null) {
|
||||
this.container.setLocalPort(this.connector.getLocalPort());
|
||||
this.container
|
||||
.setLocalHttpsPort(event.getWebServer().getPort());
|
||||
}
|
||||
}
|
||||
|
||||
private Connector createStandardConnector() {
|
||||
Connector connector = new Connector(
|
||||
"org.apache.coyote.http11.Http11NioProtocol");
|
||||
connector.setPort(this.options.portNumber());
|
||||
this.connector = connector;
|
||||
return connector;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(ServletWebServerFactory.class)
|
||||
@ConditionalOnClass({ UndertowServletWebServerFactory.class, Builder.class })
|
||||
static class UndertowContainerConfiguration {
|
||||
|
||||
@Autowired
|
||||
private Options options;
|
||||
|
||||
@Autowired
|
||||
private ContainerProperties container;
|
||||
|
||||
private Integer port;
|
||||
|
||||
@Bean
|
||||
public ServletWebServerFactory servletContainer() {
|
||||
UndertowServletWebServerFactory undertow = new UndertowServletWebServerFactory();
|
||||
if (this.options.httpsSettings().enabled()) {
|
||||
undertow.addBuilderCustomizers(new UndertowBuilderCustomizer() {
|
||||
@Override
|
||||
public void customize(Builder builder) {
|
||||
builder.addHttpListener(
|
||||
UndertowContainerConfiguration.this.options.portNumber(),
|
||||
"localhost");
|
||||
UndertowContainerConfiguration.this.port = UndertowContainerConfiguration.this.options
|
||||
.portNumber();
|
||||
}
|
||||
});
|
||||
}
|
||||
return undertow;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FaultInjectorFactory faultInjectorFactory() {
|
||||
return new NoFaultInjectorFactory();
|
||||
}
|
||||
|
||||
@EventListener
|
||||
public void serverUp(WebServerInitializedEvent event) {
|
||||
if (this.port != null) {
|
||||
// TODO: make it dynamic as well
|
||||
this.container.setLocalPort(this.port);
|
||||
this.container
|
||||
.setLocalHttpsPort(event.getWebServer().getPort());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(ServletWebServerFactory.class)
|
||||
@ConditionalOnClass({ JettyServletWebServerFactory.class,
|
||||
ServerConnector.class })
|
||||
static class JettyContainerConfiguration {
|
||||
|
||||
@Autowired
|
||||
private ContainerProperties container;
|
||||
|
||||
@Autowired
|
||||
private Options options;
|
||||
|
||||
private ServerConnector connector;
|
||||
|
||||
@Bean
|
||||
public ServletWebServerFactory servletContainer() {
|
||||
final JettyServletWebServerFactory jetty = new JettyServletWebServerFactory();
|
||||
if (this.options.httpsSettings().enabled()) {
|
||||
jetty.addServerCustomizers(new JettyServerCustomizer() {
|
||||
@Override
|
||||
public void customize(Server server) {
|
||||
server.addConnector(createStandardConnector(server));
|
||||
}
|
||||
});
|
||||
}
|
||||
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);
|
||||
connector.setHost("localhost");
|
||||
connector.setPort(this.options.portNumber());
|
||||
for (ConnectionFactory connectionFactory : connector
|
||||
.getConnectionFactories()) {
|
||||
if (connectionFactory instanceof HttpConfiguration.ConnectionFactory) {
|
||||
((HttpConfiguration.ConnectionFactory) connectionFactory)
|
||||
.getHttpConfiguration().setSendServerVersion(false);
|
||||
}
|
||||
}
|
||||
this.connector = connector;
|
||||
return connector;
|
||||
}
|
||||
|
||||
@EventListener
|
||||
public void serverUp(WebServerInitializedEvent event) {
|
||||
if (this.connector != null) {
|
||||
this.container.setLocalPort(this.connector.getLocalPort());
|
||||
this.container
|
||||
.setLocalHttpsPort(event.getWebServer().getPort());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -67,7 +67,6 @@ public abstract class WireMockSpring {
|
||||
initialized = true;
|
||||
}
|
||||
WireMockConfiguration config = new WireMockConfiguration();
|
||||
config.httpServerFactory(new SpringBootHttpServerFactory());
|
||||
return config;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package org.springframework.cloud.contract.wiremock;
|
||||
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
@@ -21,6 +21,8 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
|
||||
|
||||
import wiremock.org.eclipse.jetty.http.HttpStatus;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = TestConfiguration.class)
|
||||
@AutoConfigureRestDocs(outputDir = "target/snippets")
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package com.example.loan;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import wiremock.com.google.common.collect.ImmutableMap;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.BeanInstantiationException;
|
||||
|
||||
Reference in New Issue
Block a user