Skip to content

Commit 3cb6ce3

Browse files
Dave Syerdsyer
authored andcommitted
Move code around so factory gets address not port
1 parent 85de440 commit 3cb6ce3

File tree

14 files changed

+262
-214
lines changed

14 files changed

+262
-214
lines changed

samples/grpc-server/src/test/java/org/springframework/grpc/sample/GrpcServerIntegrationTests.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
class GrpcServerIntegrationTests {
4444

4545
@Nested
46-
@SpringBootTest(properties = { "spring.grpc.server.address=0.0.0.0", "spring.grpc.server.port=0" })
46+
@SpringBootTest(properties = { "spring.grpc.server.host=0.0.0.0", "spring.grpc.server.port=0" })
4747
class ServerWithAnyIPv4AddressAndRandomPort {
4848

4949
@Test
@@ -55,7 +55,7 @@ void servesResponseToClientWithAnyIPv4AddressAndRandomPort(@Autowired GrpcChanne
5555
}
5656

5757
@Nested
58-
@SpringBootTest(properties = { "spring.grpc.server.address=::", "spring.grpc.server.port=0" })
58+
@SpringBootTest(properties = { "spring.grpc.server.host=::", "spring.grpc.server.port=0" })
5959
class ServerWithAnyIPv6AddressAndRandomPort {
6060

6161
@Test
@@ -67,7 +67,7 @@ void servesResponseToClientWithAnyIPv4AddressAndRandomPort(@Autowired GrpcChanne
6767
}
6868

6969
@Nested
70-
@SpringBootTest(properties = { "spring.grpc.server.address=127.0.0.1", "spring.grpc.server.port=0" })
70+
@SpringBootTest(properties = { "spring.grpc.server.host=127.0.0.1", "spring.grpc.server.port=0" })
7171
class ServerWithLocalhostAndRandomPort {
7272

7373
@Test
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright 2024-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.grpc.internal;
17+
18+
public class GrpcUtils {
19+
20+
public static int DEFAULT_PORT = 9090;
21+
22+
public static int getPort(String address) {
23+
String value = address;
24+
if (value.contains(":")) {
25+
value = value.substring(value.lastIndexOf(":") + 1);
26+
}
27+
if (value.contains("/")) {
28+
value = value.substring(0, value.indexOf("/"));
29+
}
30+
if (value.matches("[0-9]+")) {
31+
return Integer.parseInt(value);
32+
}
33+
if (address.startsWith("unix:")) {
34+
return -1;
35+
}
36+
return DEFAULT_PORT;
37+
}
38+
39+
}

spring-grpc-core/src/main/java/org/springframework/grpc/server/DefaultGrpcServerFactory.java

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,18 @@
2222
import java.util.Set;
2323

2424
import com.google.common.collect.Lists;
25+
26+
import io.grpc.Grpc;
27+
import io.grpc.InsecureServerCredentials;
2528
import io.grpc.Server;
2629
import io.grpc.ServerBuilder;
30+
import io.grpc.ServerCredentials;
2731
import io.grpc.ServerProvider;
2832
import io.grpc.ServerServiceDefinition;
33+
2934
import org.apache.commons.logging.Log;
3035
import org.apache.commons.logging.LogFactory;
36+
import org.springframework.grpc.internal.GrpcUtils;
3137

3238
/**
3339
* Default implementation for {@link GrpcServerFactory gRPC service factories}.
@@ -48,25 +54,17 @@ public class DefaultGrpcServerFactory<T extends ServerBuilder<T>> implements Grp
4854

4955
private final String address;
5056

51-
private final int port;
52-
5357
private final List<ServerBuilderCustomizer<T>> serverBuilderCustomizers;
5458

55-
public DefaultGrpcServerFactory(String address, int port,
56-
List<ServerBuilderCustomizer<T>> serverBuilderCustomizers) {
59+
public DefaultGrpcServerFactory(String address, List<ServerBuilderCustomizer<T>> serverBuilderCustomizers) {
5760
this.address = address;
58-
this.port = port;
5961
this.serverBuilderCustomizers = Objects.requireNonNull(serverBuilderCustomizers, "serverBuilderCustomizers");
6062
}
6163

62-
protected String getAddress() {
64+
protected String address() {
6365
return this.address;
6466
}
6567

66-
protected int getPort() {
67-
return this.port;
68-
}
69-
7068
@Override
7169
public Server createServer() {
7270
T builder = newServerBuilder();
@@ -85,7 +83,23 @@ public void addService(ServerServiceDefinition service) {
8583
*/
8684
@SuppressWarnings("unchecked")
8785
protected T newServerBuilder() {
88-
return (T) ServerBuilder.forPort(port);
86+
return (T) Grpc.newServerBuilderForPort(port(), credentials());
87+
}
88+
89+
/**
90+
* Returns the port number on which the server should listen. Use 0 to let the system
91+
* choose a port. Use -1 to denote that this server does not listen on a socket.
92+
* @return the port number
93+
*/
94+
protected int port() {
95+
return GrpcUtils.getPort(address());
96+
}
97+
98+
/**
99+
* @return some server credentials (default is insecure)
100+
*/
101+
protected ServerCredentials credentials() {
102+
return InsecureServerCredentials.create();
89103
}
90104

91105
/**

spring-grpc-core/src/main/java/org/springframework/grpc/server/NettyGrpcServerFactory.java

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@
1616

1717
package org.springframework.grpc.server;
1818

19-
import java.net.InetSocketAddress;
2019
import java.util.List;
2120

22-
import com.google.common.net.InetAddresses;
21+
import javax.net.ssl.KeyManagerFactory;
22+
23+
import io.grpc.ServerCredentials;
24+
import io.grpc.TlsServerCredentials;
2325
import io.grpc.netty.NettyServerBuilder;
2426
import io.netty.channel.epoll.EpollEventLoopGroup;
2527
import io.netty.channel.epoll.EpollServerDomainSocketChannel;
@@ -33,34 +35,33 @@
3335
*/
3436
public class NettyGrpcServerFactory extends DefaultGrpcServerFactory<NettyServerBuilder> {
3537

36-
private static final String ANY_IP_ADDRESS = "*";
38+
private KeyManagerFactory keyManager;
3739

38-
public NettyGrpcServerFactory(String address, int port,
40+
public NettyGrpcServerFactory(String address, KeyManagerFactory keyManager,
3941
List<ServerBuilderCustomizer<NettyServerBuilder>> serverBuilderCustomizers) {
40-
super(address, port, serverBuilderCustomizers);
42+
super(address, serverBuilderCustomizers);
43+
this.keyManager = keyManager;
4144
}
4245

43-
/**
44-
* Creates a new server builder.
45-
* @return The newly created server builder.
46-
*/
46+
@Override
4747
protected NettyServerBuilder newServerBuilder() {
48-
String address = getAddress();
49-
int port = getPort();
50-
if (address != null) {
51-
if (address.startsWith("unix:")) {
52-
String path = address.substring(5);
53-
return NettyServerBuilder.forAddress(new DomainSocketAddress(path))
54-
.channelType(EpollServerDomainSocketChannel.class)
55-
.bossEventLoopGroup(new EpollEventLoopGroup(1))
56-
.workerEventLoopGroup(new EpollEventLoopGroup());
57-
}
58-
if (!ANY_IP_ADDRESS.equals(address)) {
59-
return NettyServerBuilder.forAddress(new InetSocketAddress(InetAddresses.forString(address), port));
60-
}
61-
// TODO: Add more support for address resolution
48+
String address = address();
49+
if (address.startsWith("unix:")) {
50+
String path = address.substring(5);
51+
return NettyServerBuilder.forAddress(new DomainSocketAddress(path))
52+
.channelType(EpollServerDomainSocketChannel.class)
53+
.bossEventLoopGroup(new EpollEventLoopGroup(1))
54+
.workerEventLoopGroup(new EpollEventLoopGroup());
6255
}
6356
return super.newServerBuilder();
6457
}
6558

59+
@Override
60+
protected ServerCredentials credentials() {
61+
if (this.keyManager == null || port() == -1) {
62+
return super.credentials();
63+
}
64+
return TlsServerCredentials.newBuilder().keyManager(this.keyManager.getKeyManagers()).build();
65+
}
66+
6667
}

spring-grpc-core/src/main/java/org/springframework/grpc/server/ShadedNettyGrpcServerFactory.java

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@
1616

1717
package org.springframework.grpc.server;
1818

19-
import java.net.InetSocketAddress;
2019
import java.util.List;
2120

22-
import com.google.common.net.InetAddresses;
21+
import javax.net.ssl.KeyManagerFactory;
22+
23+
import io.grpc.ServerCredentials;
24+
import io.grpc.TlsServerCredentials;
2325
import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder;
2426
import io.grpc.netty.shaded.io.netty.channel.epoll.EpollEventLoopGroup;
2527
import io.grpc.netty.shaded.io.netty.channel.epoll.EpollServerDomainSocketChannel;
@@ -33,34 +35,33 @@
3335
*/
3436
public class ShadedNettyGrpcServerFactory extends DefaultGrpcServerFactory<NettyServerBuilder> {
3537

36-
private static final String ANY_IP_ADDRESS = "*";
38+
private KeyManagerFactory keyManager;
3739

38-
public ShadedNettyGrpcServerFactory(String address, int port,
40+
public ShadedNettyGrpcServerFactory(String address, KeyManagerFactory keyManager,
3941
List<ServerBuilderCustomizer<NettyServerBuilder>> serverBuilderCustomizers) {
40-
super(address, port, serverBuilderCustomizers);
42+
super(address, serverBuilderCustomizers);
43+
this.keyManager = keyManager;
4144
}
4245

43-
/**
44-
* Creates a new server builder.
45-
* @return The newly created server builder.
46-
*/
46+
@Override
4747
protected NettyServerBuilder newServerBuilder() {
48-
String address = getAddress();
49-
int port = getPort();
50-
if (address != null) {
51-
if (address.startsWith("unix:")) {
52-
String path = address.substring(5);
53-
return NettyServerBuilder.forAddress(new DomainSocketAddress(path))
54-
.channelType(EpollServerDomainSocketChannel.class)
55-
.bossEventLoopGroup(new EpollEventLoopGroup(1))
56-
.workerEventLoopGroup(new EpollEventLoopGroup());
57-
}
58-
if (!ANY_IP_ADDRESS.equals(address)) {
59-
return NettyServerBuilder.forAddress(new InetSocketAddress(InetAddresses.forString(address), port));
60-
}
61-
// TODO: Add more support for address resolution
48+
String address = address();
49+
if (address.startsWith("unix:")) {
50+
String path = address.substring(5);
51+
return NettyServerBuilder.forAddress(new DomainSocketAddress(path))
52+
.channelType(EpollServerDomainSocketChannel.class)
53+
.bossEventLoopGroup(new EpollEventLoopGroup(1))
54+
.workerEventLoopGroup(new EpollEventLoopGroup());
6255
}
6356
return super.newServerBuilder();
6457
}
6558

59+
@Override
60+
protected ServerCredentials credentials() {
61+
if (this.keyManager == null || port() == -1) {
62+
return super.credentials();
63+
}
64+
return TlsServerCredentials.newBuilder().keyManager(this.keyManager.getKeyManagers()).build();
65+
}
66+
6667
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package org.springframework.grpc.internal;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
5+
import org.junit.jupiter.api.Test;
6+
7+
class GrpcUtilsTests {
8+
9+
@Test
10+
void testGetPortFromAddress() {
11+
assertEquals(8080, GrpcUtils.getPort("localhost:8080"));
12+
}
13+
14+
@Test
15+
void testGetNoPort() {
16+
assertEquals(9090, GrpcUtils.getPort("localhost"));
17+
}
18+
19+
@Test
20+
void testGetPortFromAddressWithPath() {
21+
String address = "example.com:1234/path";
22+
assertEquals(1234, GrpcUtils.getPort(address));
23+
}
24+
25+
@Test
26+
void testGetDomainAddress() {
27+
String address = "unix:/some/file/somewhere";
28+
assertEquals(-1, GrpcUtils.getPort(address));
29+
}
30+
31+
@Test
32+
void testGetStaticSchema() {
33+
String address = "static://localhost";
34+
assertEquals(9090, GrpcUtils.getPort(address));
35+
}
36+
37+
@Test
38+
void testGetInvalidAddress() {
39+
String address = "invalid:broken";
40+
assertEquals(9090, GrpcUtils.getPort(address)); // -1?
41+
}
42+
43+
}

spring-grpc-docs/src/main/antora/modules/ROOT/partials/_configprops.adoc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
|spring.grpc.client.default-channel.ssl.bundle | | SSL bundle name.
1717
|spring.grpc.client.default-channel.ssl.enabled | | Whether to enable SSL support. Enabled automatically if "bundle" is provided unless specified otherwise.
1818
|spring.grpc.client.default-channel.user-agent | |
19-
|spring.grpc.server.address | `+++*+++` | Server address to bind to. The default is any IP address ('*').
19+
|spring.grpc.server.address | | The address to bind to. could be a host:port combination or a pseudo URL like static://host:port. Can not be set if host or port are set independently.
20+
|spring.grpc.server.host | `+++*+++` | Server address to bind to. The default is any IP address ('*').
2021
|spring.grpc.server.keep-alive.max-age | | Maximum time a connection may exist before being gracefully terminated (default infinite).
2122
|spring.grpc.server.keep-alive.max-age-grace | | Maximum time for graceful connection termination (default infinite).
2223
|spring.grpc.server.keep-alive.max-idle | | Maximum time a connection can remain idle before being gracefully terminated (default infinite).
@@ -26,7 +27,7 @@
2627
|spring.grpc.server.keep-alive.timeout | `+++20s+++` | Maximum time to wait for read activity after sending a keep alive ping. If sender does not receive an acknowledgment within this time, it will close the connection (default 20s).
2728
|spring.grpc.server.max-inbound-message-size | `+++4194304B+++` | Maximum message size allowed to be received by the server (default 4MiB).
2829
|spring.grpc.server.max-inbound-metadata-size | `+++8192B+++` | Maximum metadata size allowed to be received by the server (default 8KiB).
29-
|spring.grpc.server.port | `+++9090+++` | Server port to listen on. When the value is 0, a random available port is selected. The default is 9090.
30+
|spring.grpc.server.port | | Server port to listen on. When the value is 0, a random available port is selected. The default is 9090.
3031
|spring.grpc.server.shutdown-grace-period | `+++30s+++` | Maximum time to wait for the server to gracefully shutdown. When the value is negative, the server waits forever. When the value is 0, the server will force shutdown immediately. The default is 30 seconds.
3132
|spring.grpc.server.ssl.bundle | | SSL bundle name.
3233
|spring.grpc.server.ssl.enabled | | Whether to enable SSL support. Enabled automatically if "bundle" is provided unless specified otherwise.

spring-grpc-spring-boot-autoconfigure/src/main/java/org/springframework/grpc/autoconfigure/client/GrpcChannelFactoryConfigurations.java

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
*/
1616
package org.springframework.grpc.autoconfigure.client;
1717

18-
import java.net.URI;
1918
import java.util.List;
2019

2120
import javax.net.ssl.SSLException;
@@ -33,7 +32,6 @@
3332
import org.springframework.grpc.client.ShadedNettyGrpcChannelFactory;
3433
import org.springframework.grpc.client.VirtualTargets;
3534

36-
import io.grpc.ManagedChannelBuilder;
3735
import io.grpc.netty.GrpcSslContexts;
3836
import io.grpc.netty.NettyChannelBuilder;
3937
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
@@ -142,21 +140,6 @@ private static io.grpc.netty.NegotiationType of(final NegotiationType negotiatio
142140

143141
}
144142

145-
@Configuration(proxyBeanMethods = false)
146-
@ConditionalOnClass(ManagedChannelBuilder.class)
147-
@ConditionalOnMissingBean(GrpcChannelFactory.class)
148-
public static class DefaultChannelFactoryConfiguration {
149-
150-
@Bean
151-
public DefaultGrpcChannelFactory defaultGrpcChannelFactory(final List<GrpcChannelConfigurer> configurers,
152-
GrpcClientProperties channels) {
153-
DefaultGrpcChannelFactory factory = new DefaultGrpcChannelFactory(configurers);
154-
factory.setVirtualTargets(new NamedChannelVirtualTargets(channels));
155-
return factory;
156-
}
157-
158-
}
159-
160143
static class NamedChannelVirtualTargets implements VirtualTargets {
161144

162145
private final GrpcClientProperties channels;

spring-grpc-spring-boot-autoconfigure/src/main/java/org/springframework/grpc/autoconfigure/client/GrpcClientAutoConfiguration.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@
2929
@Configuration(proxyBeanMethods = false)
3030
@EnableConfigurationProperties(GrpcClientProperties.class)
3131
@Import({ GrpcChannelFactoryConfigurations.ShadedNettyChannelFactoryConfiguration.class,
32-
GrpcChannelFactoryConfigurations.NettyChannelFactoryConfiguration.class,
33-
GrpcChannelFactoryConfigurations.DefaultChannelFactoryConfiguration.class })
32+
GrpcChannelFactoryConfigurations.NettyChannelFactoryConfiguration.class })
3433
public class GrpcClientAutoConfiguration {
3534

3635
@Bean

0 commit comments

Comments
 (0)