Add support for random port with https as well

This commit is contained in:
Dave Syer
2016-07-21 22:06:33 +01:00
parent b47ea3b0cd
commit cc1d20c91b
6 changed files with 202 additions and 18 deletions

View File

@@ -38,4 +38,6 @@ public @interface AutoConfigureWireMock {
int port() default 8080;
int httpsPort() default -1;
}

View File

@@ -40,6 +40,7 @@ import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent;
import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext;
import org.springframework.boot.context.embedded.Ssl;
import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory;
@@ -57,7 +58,9 @@ 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;
import com.github.tomakehurst.wiremock.common.HttpsSettings;
@@ -126,17 +129,19 @@ class SpringBootHttpServer
@Override
public int port() {
if (options.httpsSettings().enabled()) {
return options.portNumber();
}
EmbeddedWebApplicationContext embedded = (EmbeddedWebApplicationContext) context;
return embedded.getEmbeddedServletContainer().getPort();
return container().port();
}
@Override
public int httpsPort() {
// TODO HTTPS on random port
return this.options.httpsSettings().port();
return container().httpsPort();
}
private ContainerProperties container() {
if (this.context != null) {
return context.getBean(ContainerProperties.class);
}
return new ContainerProperties(options);
}
@Override
@@ -207,7 +212,7 @@ class SpringBootHttpServer
UndertowContainerConfiguration.class, ServerPropertiesAutoConfiguration.class,
BeanPostProcessorsRegistrar.class, ConfigurationPropertiesAutoConfiguration.class,
JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class })
PropertyPlaceholderAutoConfiguration.class, ContainerProperties.class })
class WiremockServerConfiguration {
@Autowired
@@ -255,6 +260,51 @@ class WiremockServerConfiguration {
}
@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 (options.httpsSettings().enabled()) {
return options.portNumber();
}
if (this.localPort != null) {
return this.localPort;
}
EmbeddedWebApplicationContext embedded = (EmbeddedWebApplicationContext) context;
return embedded.getEmbeddedServletContainer().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
@@ -264,6 +314,11 @@ class ContainerConfiguration {
@Autowired
private Options options;
@Autowired
private ContainerProperties container;
private Connector connector;
@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
@@ -273,10 +328,20 @@ class ContainerConfiguration {
return tomcat;
}
@EventListener
public void serverUp(EmbeddedServletContainerInitializedEvent event) {
if (connector != null) {
container.setLocalPort(connector.getLocalPort());
container
.setLocalHttpsPort(event.getEmbeddedServletContainer().getPort());
}
}
private Connector createStandardConnector() {
Connector connector = new Connector(
"org.apache.coyote.http11.Http11NioProtocol");
connector.setPort(this.options.portNumber());
this.connector = connector;
return connector;
}
@@ -286,9 +351,15 @@ class ContainerConfiguration {
@ConditionalOnMissingBean(EmbeddedServletContainerFactory.class)
@ConditionalOnClass({ UndertowEmbeddedServletContainerFactory.class, Builder.class })
static class UndertowContainerConfiguration {
@Autowired
private Options options;
@Autowired
private ContainerProperties container;
private Integer port;
@Bean
public EmbeddedServletContainerFactory servletContainer() {
UndertowEmbeddedServletContainerFactory undertow = new UndertowEmbeddedServletContainerFactory();
@@ -297,11 +368,23 @@ class ContainerConfiguration {
@Override
public void customize(Builder builder) {
builder.addHttpListener(options.portNumber(), "localhost");
UndertowContainerConfiguration.this.port = options.portNumber();
}
});
}
return undertow;
}
@EventListener
public void serverUp(EmbeddedServletContainerInitializedEvent event) {
if (port != null) {
// TODO: make it dynamic as well
container.setLocalPort(port);
container
.setLocalHttpsPort(event.getEmbeddedServletContainer().getPort());
}
}
}
@Configuration
@@ -309,9 +392,15 @@ class ContainerConfiguration {
@ConditionalOnClass({ JettyEmbeddedServletContainerFactory.class,
ServerConnector.class })
static class JettyContainerConfiguration {
@Autowired
private ContainerProperties container;
@Autowired
private Options options;
private ServerConnector connector;
@Bean
public EmbeddedServletContainerFactory servletContainer() {
final JettyEmbeddedServletContainerFactory jetty = new JettyEmbeddedServletContainerFactory();
@@ -338,8 +427,18 @@ class ContainerConfiguration {
.getHttpConfiguration().setSendServerVersion(false);
}
}
this.connector = connector;
return connector;
}
@EventListener
public void serverUp(EmbeddedServletContainerInitializedEvent event) {
if (connector != null) {
container.setLocalPort(connector.getLocalPort());
container
.setLocalHttpsPort(event.getEmbeddedServletContainer().getPort());
}
}
}
}

View File

@@ -49,7 +49,17 @@ public class WireMockApplicationListener implements ApplicationListener<Applicat
}
Map<String, Object> source = ((MapPropertySource) propertySources
.get("wiremock")).getSource();
source.put("wiremock.server.port", SocketUtils.findAvailableTcpPort(10000, 15000));
source.put("wiremock.server.port", SocketUtils.findAvailableTcpPort(10000, 12500));
}
if (environment.getProperty("wiremock.server.https-port", Integer.class, 0) == 0) {
MutablePropertySources propertySources = environment.getPropertySources();
if (!propertySources.contains("wiremock")) {
propertySources.addFirst(
new MapPropertySource("wiremock", new HashMap<String, Object>()));
}
Map<String, Object> source = ((MapPropertySource) propertySources
.get("wiremock")).getSource();
source.put("wiremock.server.https-port", SocketUtils.findAvailableTcpPort(12500, 15000));
}
}

View File

@@ -43,30 +43,37 @@ public class WireMockConfiguration implements SmartLifecycle, ImportAware {
@Autowired(required = false)
private Options options;
@Value("${wiremock.server.port:8080}")
private int port = 8080;
@Value("${wiremock.server.https-port:-1}")
private int httpsPort = -1;
@Override
public void setImportMetadata(AnnotationMetadata metadata) {
int port = AnnotationAttributes
.fromMap(metadata
.getAnnotationAttributes(AutoConfigureWireMock.class.getName()))
.getNumber("port").intValue();
if (port>0) {
AnnotationAttributes map = AnnotationAttributes.fromMap(
metadata.getAnnotationAttributes(AutoConfigureWireMock.class.getName()));
int port = map.getNumber("port").intValue();
if (port > 0) {
this.port = port;
}
int httpsPort = map.getNumber("httpsPort").intValue();
if (httpsPort > 0) {
this.httpsPort = httpsPort;
}
}
@PostConstruct
public void init() {
if (options == null) {
com.github.tomakehurst.wiremock.core.WireMockConfiguration factory = com.github.tomakehurst.wiremock.core.WireMockConfiguration
.wireMockConfig()
.httpServerFactory(new SpringBootHttpServerFactory());
com.github.tomakehurst.wiremock.core.WireMockConfiguration factory = WireMockSpring.options();
if (port != 8080) {
factory.port(port);
}
if (httpsPort != -1) {
factory.httpsPort(httpsPort);
}
this.options = factory;
}
server = new WireMockServer(options);

View File

@@ -0,0 +1,33 @@
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 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;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = WiremockTestsApplication.class, properties = "app.baseUrl=https://localhost:${wiremock.server.https-port}", webEnvironment = WebEnvironment.NONE)
@DirtiesContext
@AutoConfigureWireMock(httpsPort = 9999)
public class AutoConfigureWireMockHttpsPortApplicationTests {
@Autowired
private Service service;
@Test
public void contextLoads() throws Exception {
stubFor(get(urlEqualTo("/resource")).willReturn(aResponse()
.withHeader("Content-Type", "text/plain").withBody("Hello World!")));
assertThat(this.service.go()).isEqualTo("Hello World!");
}
}

View File

@@ -0,0 +1,33 @@
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 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;
@RunWith(SpringRunner.class)
@SpringBootTest(classes=WiremockTestsApplication.class, properties="app.baseUrl=https://localhost:${wiremock.server.https-port}", webEnvironment=WebEnvironment.NONE)
@DirtiesContext
@AutoConfigureWireMock(port=0, httpsPort=0)
public class AutoConfigureWireMockRandomPortHttpsApplicationTests {
@Autowired
private Service service;
@Test
public void contextLoads() throws Exception {
stubFor(get(urlEqualTo("/resource"))
.willReturn(aResponse().withHeader("Content-Type", "text/plain").withBody("Hello World!")));
assertThat(this.service.go()).isEqualTo("Hello World!");
}
}