Merge branch '2.6.x' into 2.7.x

Closes gh-29823
This commit is contained in:
Stephane Nicoll 2022-02-15 16:20:45 +01:00
commit 197203968a
4 changed files with 38 additions and 56 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2021 the original author or authors. * Copyright 2012-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -51,7 +51,6 @@ import org.springframework.core.io.buffer.NettyDataBufferFactory;
import org.springframework.http.client.reactive.ReactorResourceFactory; import org.springframework.http.client.reactive.ReactorResourceFactory;
import org.springframework.messaging.rsocket.RSocketRequester; import org.springframework.messaging.rsocket.RSocketRequester;
import org.springframework.messaging.rsocket.RSocketStrategies; import org.springframework.messaging.rsocket.RSocketStrategies;
import org.springframework.util.SocketUtils;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
@ -97,11 +96,10 @@ class NettyRSocketServerFactoryTests {
void specificPort() { void specificPort() {
NettyRSocketServerFactory factory = getFactory(); NettyRSocketServerFactory factory = getFactory();
int specificPort = doWithRetry(() -> { int specificPort = doWithRetry(() -> {
int port = SocketUtils.findAvailableTcpPort(41000); factory.setPort(0);
factory.setPort(port);
this.server = factory.create(new EchoRequestResponseAcceptor()); this.server = factory.create(new EchoRequestResponseAcceptor());
this.server.start(); this.server.start();
return port; return this.server.address().getPort();
}); });
this.requester = createRSocketTcpClient(); this.requester = createRSocketTcpClient();
assertThat(this.server.address().getPort()).isEqualTo(specificPort); assertThat(this.server.address().getPort()).isEqualTo(specificPort);

View File

@ -16,10 +16,7 @@
package org.springframework.boot.web.embedded.tomcat; package org.springframework.boot.web.embedded.tomcat;
import java.io.IOException;
import java.net.ConnectException; import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.time.Duration; import java.time.Duration;
import java.util.Arrays; import java.util.Arrays;
import java.util.Map; import java.util.Map;
@ -48,7 +45,6 @@ import org.springframework.boot.web.server.PortInUseException;
import org.springframework.boot.web.server.Shutdown; import org.springframework.boot.web.server.Shutdown;
import org.springframework.boot.web.server.WebServerException; import org.springframework.boot.web.server.WebServerException;
import org.springframework.http.server.reactive.HttpHandler; import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.util.SocketUtils;
import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.client.WebClient;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -224,15 +220,13 @@ class TomcatReactiveWebServerFactoryTests extends AbstractReactiveWebServerFacto
} }
@Test @Test
void portClashOfPrimaryConnectorResultsInPortInUseException() throws IOException { void portClashOfPrimaryConnectorResultsInPortInUseException() throws Exception {
doWithBlockedPort((port) -> { doWithBlockedPort((port) -> assertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> {
assertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> { AbstractReactiveWebServerFactory factory = getFactory();
AbstractReactiveWebServerFactory factory = getFactory(); factory.setPort(port);
factory.setPort(port); this.webServer = factory.getWebServer(mock(HttpHandler.class));
this.webServer = factory.getWebServer(mock(HttpHandler.class)); this.webServer.start();
this.webServer.start(); }).satisfies((ex) -> handleExceptionCausedByBlockedPortOnPrimaryConnector(ex, port)));
}).satisfies((ex) -> handleExceptionCausedByBlockedPortOnPrimaryConnector(ex, port));
});
} }
@Override @Override
@ -278,34 +272,9 @@ class TomcatReactiveWebServerFactoryTests extends AbstractReactiveWebServerFacto
assertThat(webServerReference).hasValue(webServer); assertThat(webServerReference).hasValue(webServer);
} }
private void doWithBlockedPort(BlockedPortAction action) throws IOException {
int port = SocketUtils.findAvailableTcpPort(40000);
ServerSocket serverSocket = new ServerSocket();
for (int i = 0; i < 10; i++) {
try {
serverSocket.bind(new InetSocketAddress(port));
break;
}
catch (Exception ex) {
}
}
try {
action.run(port);
}
finally {
serverSocket.close();
}
}
private void handleExceptionCausedByBlockedPortOnPrimaryConnector(RuntimeException ex, int blockedPort) { private void handleExceptionCausedByBlockedPortOnPrimaryConnector(RuntimeException ex, int blockedPort) {
assertThat(ex).isInstanceOf(PortInUseException.class); assertThat(ex).isInstanceOf(PortInUseException.class);
assertThat(((PortInUseException) ex).getPort()).isEqualTo(blockedPort); assertThat(((PortInUseException) ex).getPort()).isEqualTo(blockedPort);
} }
interface BlockedPortAction {
void run(int port);
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2021 the original author or authors. * Copyright 2012-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -20,6 +20,7 @@ import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.security.KeyStore; import java.security.KeyStore;
import java.time.Duration; import java.time.Duration;
@ -73,7 +74,6 @@ import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.http.server.reactive.HttpHandler; import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.util.SocketUtils;
import org.springframework.util.unit.DataSize; import org.springframework.util.unit.DataSize;
import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.client.WebClient;
@ -109,11 +109,10 @@ public abstract class AbstractReactiveWebServerFactoryTests {
void specificPort() throws Exception { void specificPort() throws Exception {
AbstractReactiveWebServerFactory factory = getFactory(); AbstractReactiveWebServerFactory factory = getFactory();
int specificPort = doWithRetry(() -> { int specificPort = doWithRetry(() -> {
int port = SocketUtils.findAvailableTcpPort(41000); factory.setPort(0);
factory.setPort(port);
this.webServer = factory.getWebServer(new EchoHandler()); this.webServer = factory.getWebServer(new EchoHandler());
this.webServer.start(); this.webServer.start();
return port; return this.webServer.getPort();
}); });
Mono<String> result = getWebClient(this.webServer.getPort()).build().post().uri("/test") Mono<String> result = getWebClient(this.webServer.getPort()).build().post().uri("/test")
.contentType(MediaType.TEXT_PLAIN).body(BodyInserters.fromValue("Hello World")).retrieve() .contentType(MediaType.TEXT_PLAIN).body(BodyInserters.fromValue("Hello World")).retrieve()
@ -569,6 +568,26 @@ public abstract class AbstractReactiveWebServerFactoryTests {
throw new IllegalStateException("Action was not successful in 10 attempts", lastFailure); throw new IllegalStateException("Action was not successful in 10 attempts", lastFailure);
} }
protected final void doWithBlockedPort(BlockedPortAction action) throws Exception {
ServerSocket serverSocket = new ServerSocket();
int blockedPort = doWithRetry(() -> {
serverSocket.bind(null);
return serverSocket.getLocalPort();
});
try {
action.run(blockedPort);
}
finally {
serverSocket.close();
}
}
public interface BlockedPortAction {
void run(int port);
}
protected static class EchoHandler implements HttpHandler { protected static class EchoHandler implements HttpHandler {
public EchoHandler() { public EchoHandler() {

View File

@ -22,7 +22,6 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.ServerSocket; import java.net.ServerSocket;
import java.net.URI; import java.net.URI;
@ -145,7 +144,6 @@ import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
import org.springframework.util.FileCopyUtils; import org.springframework.util.FileCopyUtils;
import org.springframework.util.SocketUtils;
import org.springframework.util.StreamUtils; import org.springframework.util.StreamUtils;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -324,11 +322,10 @@ public abstract class AbstractServletWebServerFactoryTests {
void specificPort() throws Exception { void specificPort() throws Exception {
AbstractServletWebServerFactory factory = getFactory(); AbstractServletWebServerFactory factory = getFactory();
int specificPort = doWithRetry(() -> { int specificPort = doWithRetry(() -> {
int port = SocketUtils.findAvailableTcpPort(41000); factory.setPort(0);
factory.setPort(port);
this.webServer = factory.getWebServer(exampleServletRegistration()); this.webServer = factory.getWebServer(exampleServletRegistration());
this.webServer.start(); this.webServer.start();
return port; return this.webServer.getPort();
}); });
assertThat(getResponse("http://localhost:" + specificPort + "/hello")).isEqualTo("Hello World"); assertThat(getResponse("http://localhost:" + specificPort + "/hello")).isEqualTo("Hello World");
assertThat(this.webServer.getPort()).isEqualTo(specificPort); assertThat(this.webServer.getPort()).isEqualTo(specificPort);
@ -1461,9 +1458,8 @@ public abstract class AbstractServletWebServerFactoryTests {
protected final void doWithBlockedPort(BlockedPortAction action) throws Exception { protected final void doWithBlockedPort(BlockedPortAction action) throws Exception {
ServerSocket serverSocket = new ServerSocket(); ServerSocket serverSocket = new ServerSocket();
int blockedPort = doWithRetry(() -> { int blockedPort = doWithRetry(() -> {
int port = SocketUtils.findAvailableTcpPort(40000); serverSocket.bind(null);
serverSocket.bind(new InetSocketAddress(port)); return serverSocket.getLocalPort();
return port;
}); });
try { try {
action.run(blockedPort); action.run(blockedPort);