Allow GrpcServlet to be configured
This adds the ability to apply `ServerBuilderCustomizer` customizers and `spring.grpc.server.max-inbound-message-size` property to `GrpcServlet`. Signed-off-by: Toshiaki Maki <makingx@gmail.com>
This commit is contained in:
committed by
Chris Bono
parent
5ab408b626
commit
7da1e80b55
@@ -25,14 +25,17 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnNotWebApplication;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.context.properties.PropertyMapper;
|
||||
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.util.unit.DataSize;
|
||||
|
||||
import io.grpc.BindableService;
|
||||
import io.grpc.servlet.jakarta.GrpcServlet;
|
||||
import io.grpc.servlet.jakarta.ServletServerBuilder;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for gRPC server-side components.
|
||||
@@ -42,6 +45,7 @@ import io.grpc.servlet.jakarta.GrpcServlet;
|
||||
*
|
||||
* @author David Syer
|
||||
* @author Chris Bono
|
||||
* @author Toshiaki Maki
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
|
||||
@@ -62,11 +66,21 @@ public class GrpcServerFactoryAutoConfiguration {
|
||||
static class GrpcServletConfiguration {
|
||||
|
||||
@Bean
|
||||
public ServletRegistrationBean<GrpcServlet> grpcServlet(List<BindableService> services) {
|
||||
public ServletRegistrationBean<GrpcServlet> grpcServlet(GrpcServerProperties properties,
|
||||
List<BindableService> services, ServerBuilderCustomizers serverBuilderCustomizers) {
|
||||
List<String> paths = services.stream()
|
||||
.map(service -> "/" + service.bindService().getServiceDescriptor().getName() + "/*")
|
||||
.collect(Collectors.toList());
|
||||
ServletRegistrationBean<GrpcServlet> servlet = new ServletRegistrationBean<>(new GrpcServlet(services));
|
||||
ServletServerBuilder servletServerBuilder = new ServletServerBuilder();
|
||||
services.forEach(servletServerBuilder::addService);
|
||||
PropertyMapper mapper = PropertyMapper.get().alwaysApplyingWhenNonNull();
|
||||
// Only maxInboundMessageSize is customizable
|
||||
mapper.from(properties.getMaxInboundMessageSize())
|
||||
.asInt(DataSize::toBytes)
|
||||
.to(servletServerBuilder::maxInboundMessageSize);
|
||||
serverBuilderCustomizers.customize(servletServerBuilder);
|
||||
ServletRegistrationBean<GrpcServlet> servlet = new ServletRegistrationBean<>(
|
||||
servletServerBuilder.buildServlet());
|
||||
servlet.setUrlMappings(paths);
|
||||
return servlet;
|
||||
}
|
||||
|
||||
@@ -16,49 +16,31 @@
|
||||
|
||||
package org.springframework.grpc.autoconfigure.server;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.inOrder;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.assertj.core.api.InstanceOfAssertFactories;
|
||||
import io.grpc.BindableService;
|
||||
import io.grpc.ServerServiceDefinition;
|
||||
import io.grpc.internal.GrpcUtil;
|
||||
import io.grpc.servlet.jakarta.ServletServerBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.grpc.server.GrpcServerFactory;
|
||||
import org.springframework.grpc.server.NettyGrpcServerFactory;
|
||||
import org.springframework.grpc.server.ServerBuilderCustomizer;
|
||||
import org.springframework.grpc.server.ShadedNettyGrpcServerFactory;
|
||||
import org.springframework.grpc.server.lifecycle.GrpcServerLifecycle;
|
||||
import org.springframework.util.unit.DataSize;
|
||||
|
||||
import io.grpc.BindableService;
|
||||
import io.grpc.Grpc;
|
||||
import io.grpc.ServerBuilder;
|
||||
import io.grpc.ServerServiceDefinition;
|
||||
import io.grpc.ServiceDescriptor;
|
||||
import io.grpc.netty.NettyServerBuilder;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Tests for {@link GrpcServerAutoConfiguration}.
|
||||
*
|
||||
* @author Chris Bono
|
||||
* @author Toshiaki Maki
|
||||
*/
|
||||
class GrpcServletAutoConfigurationTests {
|
||||
|
||||
@@ -93,4 +75,29 @@ class GrpcServletAutoConfigurationTests {
|
||||
this.contextRunner().run((context) -> assertThat(context).getBean(ServletRegistrationBean.class).isNotNull());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenCustomizerIsRegistered() {
|
||||
ServerBuilderCustomizer<ServletServerBuilder> customizer = mock();
|
||||
this.contextRunner()
|
||||
.withBean(ServerBuilderCustomizer.class, () -> customizer)
|
||||
.run(context -> verify(customizer).customize(any(ServletServerBuilder.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenMaxInboundMessageSizeIsSetThenItIsUsed() {
|
||||
this.contextRunner()
|
||||
.withPropertyValues("spring.grpc.server.max-inbound-message-size=10KB")
|
||||
.run(context -> assertThat(context).getBean(ServletRegistrationBean.class)
|
||||
.hasFieldOrPropertyWithValue("servlet.servletAdapter.maxInboundMessageSize",
|
||||
Math.toIntExact(DataSize.ofKilobytes(10).toBytes())));
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenMaxInboundMessageSizeIsNotSetThenDefaultIsUsed() {
|
||||
this.contextRunner()
|
||||
.run((context) -> assertThat(context).getBean(ServletRegistrationBean.class)
|
||||
.hasFieldOrPropertyWithValue("servlet.servletAdapter.maxInboundMessageSize",
|
||||
GrpcUtil.DEFAULT_MAX_MESSAGE_SIZE));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user