From 974ed5e456300b316480f13aed3c329f8e4f484c Mon Sep 17 00:00:00 2001 From: Trustin Lee Date: Tue, 6 Mar 2018 10:50:29 +0900 Subject: [PATCH] More concise port and TLS configuration Motivation: - A user currently has to specify SessionProtocol when adding a port, which increases the chance of specifying incorrect SessionProtocol. - sslContext() builder methods require SessionProtocol which is practically unncessary. - It would be confusing if Server serves plaintext HTTP when a user configured TLS even if he or she did not specify a port. More sensible behavior would be serving HTTPS when no port is specified in this case. Modifications: - Add http() and https() which supercede most port() methods. - Add tls() which supercede sslContext() methods. - Serve HTTPS by default when a user called tls() and no port was specified. - Add log messages that indicates the protocol and local address. - Deprecate the old methods. - Update documentation. - Miscellaneous: - Remove redundant `port(0, HTTP)` calls - Add `@Nullable` where necessary Result: - Fixes #1050 - More user-friendliness --- .../armeria/core/HttpServerBenchmark.java | 1 - .../downstream/DownstreamSimpleBenchmark.java | 1 - .../downstream/LargePayloadBenchmark.java | 1 - .../thrift/PooledResponseBufferBenchmark.java | 1 - .../server/AbstractVirtualHostBuilder.java | 58 +++- .../com/linecorp/armeria/server/Server.java | 42 +-- .../armeria/server/ServerBuilder.java | 251 ++++++++++++++++-- .../linecorp/armeria/server/ServerConfig.java | 16 -- .../linecorp/armeria/server/ServerPort.java | 5 +- .../client/HttpClientIntegrationTest.java | 3 - .../armeria/client/HttpClientSniTest.java | 6 +- .../HttpHealthCheckedEndpointGroupTest.java | 6 +- ...nectionLimitingHandlerIntegrationTest.java | 2 - .../armeria/server/HttpServerPathTest.java | 2 - .../armeria/server/HttpServerTest.java | 8 +- .../armeria/server/RedirectServiceTest.java | 2 +- .../armeria/server/SniServerTest.java | 9 +- .../HttpHealthCheckServiceTest.java | 3 - .../armeria/client/grpc/GrpcClientTest.java | 2 - .../it/grpc/GrpcMetricsIntegrationTest.java | 2 - .../server/grpc/GrpcServiceServerTest.java | 2 - .../interop/ArmeriaGrpcServerInteropTest.java | 5 +- .../server/jetty/JettyServiceTest.java | 10 +- .../jetty/UnmanagedJettyServiceTest.java | 10 +- site/src/sphinx/server-basics.rst | 19 +- site/src/sphinx/server-docservice.rst | 2 +- .../spring/ArmeriaAutoConfiguration.java | 10 +- .../thrift/ThriftOverHttpClientTest.java | 6 +- .../thrift/AbstractThriftOverHttpTest.java | 6 +- .../server/tomcat/TomcatServiceTest.java | 10 +- .../zookeeper/ZooKeeperRegistrationTest.java | 3 +- 31 files changed, 334 insertions(+), 170 deletions(-) diff --git a/benchmarks/src/jmh/java/com/linecorp/armeria/core/HttpServerBenchmark.java b/benchmarks/src/jmh/java/com/linecorp/armeria/core/HttpServerBenchmark.java index 680d21273468..9bf206834d62 100644 --- a/benchmarks/src/jmh/java/com/linecorp/armeria/core/HttpServerBenchmark.java +++ b/benchmarks/src/jmh/java/com/linecorp/armeria/core/HttpServerBenchmark.java @@ -67,7 +67,6 @@ String uriText() { @Setup public void startServer() throws Exception { server = new ServerBuilder() - .port(0, HTTP) .service("/empty", ((ctx, req) -> HttpResponse.of(HttpStatus.OK))) .defaultRequestTimeout(Duration.ZERO) .meterRegistry(NoopMeterRegistry.get()) diff --git a/benchmarks/src/jmh/java/com/linecorp/armeria/grpc/downstream/DownstreamSimpleBenchmark.java b/benchmarks/src/jmh/java/com/linecorp/armeria/grpc/downstream/DownstreamSimpleBenchmark.java index e5b2b33f218d..c3b3a4ec3eae 100644 --- a/benchmarks/src/jmh/java/com/linecorp/armeria/grpc/downstream/DownstreamSimpleBenchmark.java +++ b/benchmarks/src/jmh/java/com/linecorp/armeria/grpc/downstream/DownstreamSimpleBenchmark.java @@ -59,7 +59,6 @@ protected GithubServiceFutureStub normalFutureClient() { @Override protected void setUp() throws Exception { server = new ServerBuilder() - .port(0, HTTP) .serviceUnder("/", new GrpcServiceBuilder().addService(new GithubApiService()).build()) .build(); server.start().join(); diff --git a/benchmarks/src/jmh/java/com/linecorp/armeria/grpc/downstream/LargePayloadBenchmark.java b/benchmarks/src/jmh/java/com/linecorp/armeria/grpc/downstream/LargePayloadBenchmark.java index 7256d8a8aae3..1896d4420da1 100644 --- a/benchmarks/src/jmh/java/com/linecorp/armeria/grpc/downstream/LargePayloadBenchmark.java +++ b/benchmarks/src/jmh/java/com/linecorp/armeria/grpc/downstream/LargePayloadBenchmark.java @@ -67,7 +67,6 @@ public class LargePayloadBenchmark { @Setup public void setUp() { server = new ServerBuilder() - .port(0, HTTP) .serviceUnder("/", new GrpcServiceBuilder().addService( new BinaryProxyImplBase() { @Override diff --git a/benchmarks/src/jmh/java/com/linecorp/armeria/thrift/PooledResponseBufferBenchmark.java b/benchmarks/src/jmh/java/com/linecorp/armeria/thrift/PooledResponseBufferBenchmark.java index d9553d52c220..08fd9c70db8d 100644 --- a/benchmarks/src/jmh/java/com/linecorp/armeria/thrift/PooledResponseBufferBenchmark.java +++ b/benchmarks/src/jmh/java/com/linecorp/armeria/thrift/PooledResponseBufferBenchmark.java @@ -141,7 +141,6 @@ public void onComplete() { @Setup public void startServer() throws Exception { ServerBuilder sb = new ServerBuilder() - .port(0, HTTP) .service("/a", THttpService.of( (AsyncIface) (name, resultHandler) -> resultHandler.onComplete(RESPONSE)) diff --git a/core/src/main/java/com/linecorp/armeria/server/AbstractVirtualHostBuilder.java b/core/src/main/java/com/linecorp/armeria/server/AbstractVirtualHostBuilder.java index d22bdc7e516b..1fae79f8750b 100644 --- a/core/src/main/java/com/linecorp/armeria/server/AbstractVirtualHostBuilder.java +++ b/core/src/main/java/com/linecorp/armeria/server/AbstractVirtualHostBuilder.java @@ -29,6 +29,7 @@ import java.util.List; import java.util.function.Function; +import javax.annotation.Nullable; import javax.net.ssl.SSLException; import org.slf4j.Logger; @@ -119,7 +120,9 @@ abstract class AbstractVirtualHostBuilder private final String defaultHostname; private final String hostnamePattern; private final List services = new ArrayList<>(); + @Nullable private SslContext sslContext; + @Nullable private Function, Service> decorator; /** @@ -162,17 +165,54 @@ abstract class AbstractVirtualHostBuilder } /** - * Sets the {@link SslContext} of this {@link VirtualHost}. + * Configures SSL or TLS of this {@link VirtualHost} with the specified {@link SslContext}. */ - public B sslContext(SslContext sslContext) { + public B tls(SslContext sslContext) { this.sslContext = VirtualHost.validateSslContext(requireNonNull(sslContext, "sslContext")); return self(); } + /** + * Configures SSL or TLS of this {@link VirtualHost} with the specified {@code keyCertChainFile} + * and cleartext {@code keyFile}. + */ + public B tls(File keyCertChainFile, File keyFile) throws SSLException { + tls(keyCertChainFile, keyFile, null); + return self(); + } + + /** + * Configures SSL or TLS of this {@link VirtualHost} with the specified {@code keyCertChainFile}, + * {@code keyFile} and {@code keyPassword}. + */ + public B tls(File keyCertChainFile, File keyFile, @Nullable String keyPassword) throws SSLException { + final SslContextBuilder builder = SslContextBuilder.forServer(keyCertChainFile, keyFile, keyPassword); + + builder.sslProvider(Flags.useOpenSsl() ? SslProvider.OPENSSL : SslProvider.JDK); + builder.ciphers(Http2SecurityUtil.CIPHERS, SupportedCipherSuiteFilter.INSTANCE); + builder.applicationProtocolConfig(HTTPS_ALPN_CFG); + + tls(builder.build()); + return self(); + } + + /** + * Sets the {@link SslContext} of this {@link VirtualHost}. + * + * @deprecated Use {@link #tls(SslContext)}. + */ + @Deprecated + public B sslContext(SslContext sslContext) { + return tls(sslContext); + } + /** * Sets the {@link SslContext} of this {@link VirtualHost} from the specified {@link SessionProtocol}, * {@code keyCertChainFile} and cleartext {@code keyFile}. + * + * @deprecated Use {@link #tls(File, File)}. */ + @Deprecated public B sslContext( SessionProtocol protocol, File keyCertChainFile, File keyFile) throws SSLException { sslContext(protocol, keyCertChainFile, keyFile, null); @@ -182,23 +222,19 @@ public B sslContext( /** * Sets the {@link SslContext} of this {@link VirtualHost} from the specified {@link SessionProtocol}, * {@code keyCertChainFile}, {@code keyFile} and {@code keyPassword}. + * + * @deprecated Use {@link #tls(File, File, String)}. */ + @Deprecated public B sslContext( SessionProtocol protocol, - File keyCertChainFile, File keyFile, String keyPassword) throws SSLException { + File keyCertChainFile, File keyFile, @Nullable String keyPassword) throws SSLException { if (requireNonNull(protocol, "protocol") != SessionProtocol.HTTPS) { throw new IllegalArgumentException("unsupported protocol: " + protocol); } - final SslContextBuilder builder = SslContextBuilder.forServer(keyCertChainFile, keyFile, keyPassword); - - builder.sslProvider(Flags.useOpenSsl() ? SslProvider.OPENSSL : SslProvider.JDK); - builder.ciphers(Http2SecurityUtil.CIPHERS, SupportedCipherSuiteFilter.INSTANCE); - builder.applicationProtocolConfig(HTTPS_ALPN_CFG); - - sslContext(builder.build()); - return self(); + return tls(keyCertChainFile, keyFile, keyPassword); } /** diff --git a/core/src/main/java/com/linecorp/armeria/server/Server.java b/core/src/main/java/com/linecorp/armeria/server/Server.java index b0ecc65ef9f7..80023b359bce 100644 --- a/core/src/main/java/com/linecorp/armeria/server/Server.java +++ b/core/src/main/java/com/linecorp/armeria/server/Server.java @@ -64,7 +64,6 @@ import io.netty.channel.EventLoopGroup; import io.netty.handler.ssl.SslContext; import io.netty.util.DomainNameMapping; -import io.netty.util.DomainNameMappingBuilder; import io.netty.util.concurrent.FastThreadLocalThread; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.GlobalEventExecutor; @@ -80,6 +79,7 @@ public final class Server implements AutoCloseable { private static final Logger logger = LoggerFactory.getLogger(Server.class); private final ServerConfig config; + @Nullable private final DomainNameMapping sslContexts; private final StateManager stateManager = new StateManager(); @@ -92,6 +92,7 @@ public final class Server implements AutoCloseable { private final ConnectionLimitingHandler connectionLimitingHandler; + @Nullable private volatile ServerPort primaryActivePort; /** @@ -100,34 +101,11 @@ public final class Server implements AutoCloseable { */ private volatile GracefulShutdownSupport gracefulShutdownSupport = GracefulShutdownSupport.disabled(); - Server(ServerConfig config) { + Server(ServerConfig config, @Nullable DomainNameMapping sslContexts) { this.config = requireNonNull(config, "config"); - config.setServer(this); - - // Pre-populate the domain name mapping for later matching. - SslContext lastSslContext = null; - for (VirtualHost h: config.virtualHosts()) { - lastSslContext = h.sslContext(); - } + this.sslContexts = sslContexts; - if (lastSslContext == null) { - sslContexts = null; - for (ServerPort p: config.ports()) { - if (p.protocol().isTls()) { - throw new IllegalArgumentException("no SSL context specified"); - } - } - } else { - final DomainNameMappingBuilder - mappingBuilder = new DomainNameMappingBuilder<>(lastSslContext); - for (VirtualHost h : config.virtualHosts()) { - final SslContext sslCtx = h.sslContext(); - if (sslCtx != null) { - mappingBuilder.add(h.hostnamePattern(), sslCtx); - } - } - sslContexts = mappingBuilder.build(); - } + config.setServer(this); // Invoke the serviceAdded() method in Service so that it can keep the reference to this Server or // add a listener to it. @@ -489,7 +467,7 @@ static final class State { final StateType type; final CompletableFuture future; - State(StateType type, CompletableFuture future) { + State(StateType type, @Nullable CompletableFuture future) { this.type = type; this.future = future; } @@ -653,6 +631,14 @@ public void operationComplete(ChannelFuture f) throws Exception { primaryActivePort = actualPort; } + if (localAddress.getAddress().isAnyLocalAddress() || + localAddress.getAddress().isLoopbackAddress()) { + logger.info("Serving {} at {} - {}://127.0.0.1:{}/", + port.protocol(), localAddress, port.protocol(), localAddress.getPort()); + } else { + logger.info("Serving {} at {}", port.protocol(), localAddress); + } + if (remainingPorts.decrementAndGet() == 0) { completeFuture(startFuture); } diff --git a/core/src/main/java/com/linecorp/armeria/server/ServerBuilder.java b/core/src/main/java/com/linecorp/armeria/server/ServerBuilder.java index d7b75493df7b..e649043296cb 100644 --- a/core/src/main/java/com/linecorp/armeria/server/ServerBuilder.java +++ b/core/src/main/java/com/linecorp/armeria/server/ServerBuilder.java @@ -17,6 +17,7 @@ package com.linecorp.armeria.server; import static com.linecorp.armeria.common.SessionProtocol.HTTP; +import static com.linecorp.armeria.common.SessionProtocol.HTTPS; import static com.linecorp.armeria.server.ServerConfig.validateDefaultMaxRequestLength; import static com.linecorp.armeria.server.ServerConfig.validateDefaultRequestTimeoutMillis; import static com.linecorp.armeria.server.ServerConfig.validateNonNegative; @@ -26,13 +27,14 @@ import java.net.InetSocketAddress; import java.time.Duration; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.concurrent.Executor; import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Collectors; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import javax.net.ssl.SSLException; import com.google.common.collect.ImmutableList; @@ -53,6 +55,8 @@ import io.micrometer.core.instrument.Metrics; import io.netty.channel.EventLoopGroup; import io.netty.handler.ssl.SslContext; +import io.netty.util.DomainNameMapping; +import io.netty.util.DomainNameMappingBuilder; /** * Builds a new {@link Server} and its {@link ServerConfig}. @@ -60,7 +64,7 @@ *
{@code
  * ServerBuilder sb = new ServerBuilder();
  * // Add a port to listen
- * sb.port(8080, SessionProtocol.HTTP);
+ * sb.http(8080);
  * // Build and add a virtual host.
  * sb.virtualHost(new VirtualHostBuilder("*.foo.com").service(...).build());
  * // Add services to the default virtual host.
@@ -74,15 +78,30 @@
  * 
{@code
  * ServerBuilder sb = new ServerBuilder();
  * Server server =
- *      sb.port(8080, SessionProtocol.HTTP) // Add a port to listen
- *      .withDefaultVirtualHost() // Add services to the default virtual host.
- *          .service(...)
- *          .serviceUnder(...)
- *      .and().withVirtualHost("*.foo.com") // Add a another virtual host.
- *          .service(...)
- *          .serviceUnder(...)
- *      .and().build(); // Build a server.
+ *     sb.http(8080) // Add a port to listen
+ *       .withDefaultVirtualHost() // Add services to the default virtual host.
+ *           .service(...)
+ *           .serviceUnder(...)
+ *       .and().withVirtualHost("*.foo.com") // Add a another virtual host.
+ *           .service(...)
+ *           .serviceUnder(...)
+ *       .and().build(); // Build a server.
  * }
+ * + * + *

What happens if no HTTP(S) port is specified?

+ * + *

When no TCP/IP port number or local address is specified, {@link ServerBuilder} will automatically bind + * to a random TCP/IP port assigned by O/S. It will serve HTTPS if you configured TLS (or HTTP otherwise), e.g. + * + *

{@code
+ * // Build an HTTP server that runs on an ephemeral TCP/IP port.
+ * Server httpServer = new ServerBuilder().service(...).build();
+ *
+ * // Build an HTTPS server that runs on an ephemeral TCP/IP port.
+ * Server httpsServer = new ServerBuilder().tls(...).service(...).build();
+ * }
+ * * @see VirtualHostBuilder */ public final class ServerBuilder { @@ -102,6 +121,7 @@ public final class ServerBuilder { private final ChainedVirtualHostBuilder defaultVirtualHostBuilder = new ChainedVirtualHostBuilder(this); private boolean updatedDefaultVirtualHostBuilder; + @Nullable private VirtualHost defaultVirtualHost; private EventLoopGroup workerGroup = CommonPools.workerGroup(); private boolean shutdownWorkerGroupOnStop; @@ -119,22 +139,81 @@ public final class ServerBuilder { private String serviceLoggerPrefix = DEFAULT_SERVICE_LOGGER_PREFIX; private Consumer accessLogWriter = AccessLogWriters.disabled(); + @Nullable private Function, Service> decorator; + /** + * Adds an HTTP port that listens on all available network interfaces. + * + * @param port the HTTP port number. + * + * @see #http(InetSocketAddress) + * @see What happens if no HTTP(S) port is specified? + */ + public ServerBuilder http(int port) { + ports.add(new ServerPort(port, HTTP)); + return this; + } + + /** + * Adds an HTTP port that listens to the specified {@code localAddress}. + * + * @param localAddress the local address to bind + * + * @see #http(int) + * @see What happens if no HTTP(S) port is specified? + */ + public ServerBuilder http(InetSocketAddress localAddress) { + ports.add(new ServerPort(requireNonNull(localAddress, "localAddress"), HTTP)); + return this; + } + + /** + * Adds an HTTPS port that listens on all available network interfaces. + * + * @param port the HTTPS port number. + * + * @see #https(InetSocketAddress) + * @see What happens if no HTTP(S) port is specified? + */ + public ServerBuilder https(int port) { + ports.add(new ServerPort(port, HTTPS)); + return this; + } + + /** + * Adds an HTTPS port that listens to the specified {@code localAddress}. + * + * @param localAddress the local address to bind + * + * @see #http(int) + * @see What happens if no HTTP(S) port is specified? + */ + public ServerBuilder https(InetSocketAddress localAddress) { + ports.add(new ServerPort(requireNonNull(localAddress, "localAddress"), HTTPS)); + return this; + } + /** * Adds a new {@link ServerPort} that listens to the specified {@code port} of all available network - * interfaces using the specified protocol. If no port is added (i.e. no {@code port()} method is called), - * a default of {@code 0} (randomly-assigned port) and {@code "http"} will be used. + * interfaces using the specified protocol. + * + * @deprecated Use {@link #http(int)} or {@link #https(int)}. + * @see What happens if no HTTP(S) port is specified? */ + @Deprecated public ServerBuilder port(int port, String protocol) { return port(port, SessionProtocol.of(requireNonNull(protocol, "protocol"))); } /** * Adds a new {@link ServerPort} that listens to the specified {@code port} of all available network - * interfaces using the specified {@link SessionProtocol}. If no port is added (i.e. no {@code port()} - * method is called), a default of {@code 0} (randomly-assigned port) and {@code "http"} will be used. + * interfaces using the specified {@link SessionProtocol}. + * + * @deprecated Use {@link #http(int)} or {@link #https(int)}. + * @see What happens if no HTTP(S) port is specified? */ + @Deprecated public ServerBuilder port(int port, SessionProtocol protocol) { ports.add(new ServerPort(port, protocol)); return this; @@ -142,26 +221,33 @@ public ServerBuilder port(int port, SessionProtocol protocol) { /** * Adds a new {@link ServerPort} that listens to the specified {@code localAddress} using the specified - * protocol. If no port is added (i.e. no {@code port()} method is called), a default of {@code 0} - * (randomly-assigned port) and {@code "http"} will be used. + * protocol. + * + * @deprecated Use {@link #http(InetSocketAddress)} or {@link #https(InetSocketAddress)}. + * @see What happens if no HTTP(S) port is specified? */ + @Deprecated public ServerBuilder port(InetSocketAddress localAddress, String protocol) { return port(localAddress, SessionProtocol.of(requireNonNull(protocol, "protocol"))); } /** * Adds a new {@link ServerPort} that listens to the specified {@code localAddress} using the specified - * {@link SessionProtocol}. If no port is added (i.e. no {@code port()} method is called), a default of - * {@code 0} (randomly-assigned port) and {@code "http"} will be used. + * {@link SessionProtocol}. + * + * @deprecated Use {@link #http(InetSocketAddress)} or {@link #https(InetSocketAddress)}. + * @see What happens if no HTTP(S) port is specified? */ + @Deprecated public ServerBuilder port(InetSocketAddress localAddress, SessionProtocol protocol) { ports.add(new ServerPort(localAddress, protocol)); return this; } /** - * Adds the specified {@link ServerPort}. If no port is added (i.e. no {@code port()} method is called), - * a default of {@code 0} (randomly-assigned port) and {@code "http"} will be used. + * Adds the specified {@link ServerPort}. + * + * @see What happens if no HTTP(S) port is specified? */ public ServerBuilder port(ServerPort port) { ports.add(requireNonNull(port, "port")); @@ -369,9 +455,52 @@ public ServerBuilder accessLogWriter(Consumer accessLogWrite * @throws IllegalStateException if the default {@link VirtualHost} has been set via * {@link #defaultVirtualHost(VirtualHost)} already */ + public ServerBuilder tls(SslContext sslContext) { + defaultVirtualHostBuilderUpdated(); + defaultVirtualHostBuilder.tls(sslContext); + return this; + } + + /** + * Sets the {@link SslContext} of the default {@link VirtualHost} from the specified + * {@code keyCertChainFile} and cleartext {@code keyFile}. + * + * @throws IllegalStateException if the default {@link VirtualHost} has been set via + * {@link #defaultVirtualHost(VirtualHost)} already + */ + public ServerBuilder tls(File keyCertChainFile, File keyFile) throws SSLException { + defaultVirtualHostBuilderUpdated(); + defaultVirtualHostBuilder.tls(keyCertChainFile, keyFile); + return this; + } + + /** + * Sets the {@link SslContext} of the default {@link VirtualHost} from the specified + * {@code keyCertChainFile}, {@code keyFile} and {@code keyPassword}. + * + * @throws IllegalStateException if the default {@link VirtualHost} has been set via + * {@link #defaultVirtualHost(VirtualHost)} already + */ + public ServerBuilder tls( + File keyCertChainFile, File keyFile, @Nullable String keyPassword) throws SSLException { + + defaultVirtualHostBuilderUpdated(); + defaultVirtualHostBuilder.tls(keyCertChainFile, keyFile, keyPassword); + return this; + } + + /** + * Sets the {@link SslContext} of the default {@link VirtualHost}. + * + * @deprecated Use {@link #tls(SslContext)}. + * + * @throws IllegalStateException if the default {@link VirtualHost} has been set via + * {@link #defaultVirtualHost(VirtualHost)} already + */ + @Deprecated public ServerBuilder sslContext(SslContext sslContext) { defaultVirtualHostBuilderUpdated(); - defaultVirtualHostBuilder.sslContext(sslContext); + defaultVirtualHostBuilder.tls(sslContext); return this; } @@ -379,9 +508,12 @@ public ServerBuilder sslContext(SslContext sslContext) { * Sets the {@link SslContext} of the default {@link VirtualHost} from the specified * {@link SessionProtocol}, {@code keyCertChainFile} and cleartext {@code keyFile}. * + * @deprecated Use {@link #tls(File, File)}. + * * @throws IllegalStateException if the default {@link VirtualHost} has been set via * {@link #defaultVirtualHost(VirtualHost)} already */ + @Deprecated public ServerBuilder sslContext( SessionProtocol protocol, File keyCertChainFile, File keyFile) throws SSLException { defaultVirtualHostBuilderUpdated(); @@ -393,9 +525,12 @@ public ServerBuilder sslContext( * Sets the {@link SslContext} of the default {@link VirtualHost} from the specified * {@link SessionProtocol}, {@code keyCertChainFile}, {@code keyFile} and {@code keyPassword}. * + * @deprecated Use {@link #tls(File, File, String)}. + * * @throws IllegalStateException if the default {@link VirtualHost} has been set via * {@link #defaultVirtualHost(VirtualHost)} already */ + @Deprecated public ServerBuilder sslContext( SessionProtocol protocol, File keyCertChainFile, File keyFile, String keyPassword) throws SSLException { @@ -608,7 +743,7 @@ private void defaultVirtualHostBuilderUpdated() { * @throws IllegalStateException * if other default {@link VirtualHost} builder methods have been invoked already, including: *
    - *
  • {@link #sslContext(SslContext)}
  • + *
  • {@link #tls(SslContext)}
  • *
  • {@link #service(String, Service)}
  • *
  • {@link #serviceUnder(String, Service)}
  • *
  • {@link #service(PathMapping, Service)}
  • @@ -703,10 +838,6 @@ ServerBuilder decorator(Function decorator) { * Returns a newly-created {@link Server} based on the configuration properties set so far. */ public Server build() { - final List ports = - !this.ports.isEmpty() ? this.ports - : Collections.singletonList(new ServerPort(0, HTTP)); - final VirtualHost defaultVirtualHost; if (this.defaultVirtualHost != null) { defaultVirtualHost = this.defaultVirtualHost.decorate(decorator); @@ -725,16 +856,78 @@ public Server build() { virtualHosts = this.virtualHosts; } + final List ports; + + // Pre-populate the domain name mapping for later matching. + final DomainNameMapping sslContexts; + final SslContext defaultSslContext = findDefaultSslContext(defaultVirtualHost, virtualHosts); + + if (defaultSslContext == null) { + sslContexts = null; + if (!this.ports.isEmpty()) { + ports = ImmutableList.copyOf(this.ports); + for (ServerPort p : ports) { + if (p.protocol().isTls()) { + throw new IllegalArgumentException("TLS not configured; cannot serve HTTPS"); + } + } + } else { + ports = ImmutableList.of(new ServerPort(0, HTTP)); + } + } else { + if (!this.ports.isEmpty()) { + ports = ImmutableList.copyOf(this.ports); + } else { + ports = ImmutableList.of(new ServerPort(0, HTTPS)); + } + + final DomainNameMappingBuilder + mappingBuilder = new DomainNameMappingBuilder<>(defaultSslContext); + for (VirtualHost h : virtualHosts) { + final SslContext sslCtx = h.sslContext(); + if (sslCtx != null) { + mappingBuilder.add(h.hostnamePattern(), sslCtx); + } + } + sslContexts = mappingBuilder.build(); + } + final Server server = new Server(new ServerConfig( - ports, defaultVirtualHost, virtualHosts, workerGroup, shutdownWorkerGroupOnStop, - maxNumConnections, idleTimeoutMillis, defaultRequestTimeoutMillis, defaultMaxRequestLength, + ports, normalizeDefaultVirtualHost(defaultVirtualHost, defaultSslContext), virtualHosts, + workerGroup, shutdownWorkerGroupOnStop, maxNumConnections, + idleTimeoutMillis, defaultRequestTimeoutMillis, defaultMaxRequestLength, maxHttp1InitialLineLength, maxHttp1HeaderSize, maxHttp1ChunkSize, gracefulShutdownQuietPeriod, gracefulShutdownTimeout, blockingTaskExecutor, - meterRegistry, serviceLoggerPrefix, accessLogWriter)); + meterRegistry, serviceLoggerPrefix, accessLogWriter), sslContexts); + serverListeners.forEach(server::addListener); return server; } + private static VirtualHost normalizeDefaultVirtualHost(VirtualHost h, SslContext defaultSslContext) { + final SslContext sslCtx = h.sslContext() != null ? h.sslContext() : defaultSslContext; + return new VirtualHost( + h.defaultHostname(), "*", sslCtx, + h.serviceConfigs().stream().map( + e -> new ServiceConfig(e.pathMapping(), e.service(), e.loggerName().orElse(null))) + .collect(Collectors.toList()), h.producibleMediaTypes()); + } + + @Nonnull + private static SslContext findDefaultSslContext(VirtualHost defaultVirtualHost, + List virtualHosts) { + SslContext lastSslContext = null; + for (VirtualHost h : virtualHosts) { + if (h.sslContext() != null) { + lastSslContext = h.sslContext(); + } + } + if (defaultVirtualHost.sslContext() != null) { + lastSslContext = defaultVirtualHost.sslContext(); + } + return lastSslContext; + } + @Override public String toString() { return ServerConfig.toString( diff --git a/core/src/main/java/com/linecorp/armeria/server/ServerConfig.java b/core/src/main/java/com/linecorp/armeria/server/ServerConfig.java index 8a981fd854f7..e0d0a80a17cf 100644 --- a/core/src/main/java/com/linecorp/armeria/server/ServerConfig.java +++ b/core/src/main/java/com/linecorp/armeria/server/ServerConfig.java @@ -140,7 +140,6 @@ public final class ServerConfig { this.ports = Collections.unmodifiableList(portsCopy); // Set virtual host definitions and initialize their domain name mapping. - defaultVirtualHost = normalizeDefaultVirtualHost(defaultVirtualHost, portsCopy); final DomainNameMappingBuilder mappingBuilder = new DomainNameMappingBuilder<>(defaultVirtualHost); final List virtualHostsCopy = new ArrayList<>(); @@ -222,21 +221,6 @@ static void validateGreaterThanOrEqual(Duration larger, String largerFieldName, } } - private static VirtualHost normalizeDefaultVirtualHost(VirtualHost h, List ports) { - final SslContext sslCtx = h.sslContext(); - // The default virtual host must have sslContext set if TLS is in use. - if (sslCtx == null && ports.stream().anyMatch(p -> p.protocol().isTls())) { - throw new IllegalArgumentException( - "defaultVirtualHost must have sslContext set when TLS is enabled."); - } - - return new VirtualHost( - h.defaultHostname(), "*", sslCtx, - h.serviceConfigs().stream().map( - e -> new ServiceConfig(e.pathMapping(), e.service(), e.loggerName().orElse(null))) - .collect(Collectors.toList()), h.producibleMediaTypes()); - } - /** * Returns the {@link Server}. */ diff --git a/core/src/main/java/com/linecorp/armeria/server/ServerPort.java b/core/src/main/java/com/linecorp/armeria/server/ServerPort.java index 849c647cfbfe..cd7280e33828 100644 --- a/core/src/main/java/com/linecorp/armeria/server/ServerPort.java +++ b/core/src/main/java/com/linecorp/armeria/server/ServerPort.java @@ -25,6 +25,8 @@ import java.net.InetSocketAddress; import java.net.UnknownHostException; +import javax.annotation.Nullable; + import com.linecorp.armeria.common.SessionProtocol; /** @@ -36,6 +38,7 @@ public final class ServerPort implements Comparable { private final String localAddressString; private final SessionProtocol protocol; private int hashCode; + @Nullable private String strVal; /** @@ -136,7 +139,7 @@ public String toString() { return strVal; } - static String toString(Class type, InetSocketAddress localAddress, SessionProtocol protocol) { + static String toString(@Nullable Class type, InetSocketAddress localAddress, SessionProtocol protocol) { StringBuilder buf = new StringBuilder(); if (type != null) { buf.append(type.getSimpleName()); diff --git a/core/src/test/java/com/linecorp/armeria/client/HttpClientIntegrationTest.java b/core/src/test/java/com/linecorp/armeria/client/HttpClientIntegrationTest.java index c15617f711fd..3c9e560e362d 100644 --- a/core/src/test/java/com/linecorp/armeria/client/HttpClientIntegrationTest.java +++ b/core/src/test/java/com/linecorp/armeria/client/HttpClientIntegrationTest.java @@ -16,7 +16,6 @@ package com.linecorp.armeria.client; -import static com.linecorp.armeria.common.SessionProtocol.HTTP; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.awaitility.Awaitility.await; @@ -172,8 +171,6 @@ protected HttpResponse doGet(ServiceRequestContext ctx, HttpRequest req) public static final ServerRule server = new ServerRule() { @Override protected void configure(ServerBuilder sb) throws Exception { - sb.port(0, HTTP); - sb.service("/httptestbody", new AbstractHttpService() { @Override diff --git a/core/src/test/java/com/linecorp/armeria/client/HttpClientSniTest.java b/core/src/test/java/com/linecorp/armeria/client/HttpClientSniTest.java index 8fddecca431b..80acfacc4a9f 100644 --- a/core/src/test/java/com/linecorp/armeria/client/HttpClientSniTest.java +++ b/core/src/test/java/com/linecorp/armeria/client/HttpClientSniTest.java @@ -68,16 +68,14 @@ public class HttpClientSniTest { sscA = new SelfSignedCertificate("a.com"); sscB = new SelfSignedCertificate("b.com"); - sb.port(0, HTTPS); - final VirtualHostBuilder a = new VirtualHostBuilder("a.com"); final VirtualHostBuilder b = new VirtualHostBuilder("b.com"); a.service("/", new SniTestService("a.com")); b.service("/", new SniTestService("b.com")); - a.sslContext(HTTPS, sscA.certificate(), sscA.privateKey()); - b.sslContext(HTTPS, sscB.certificate(), sscB.privateKey()); + a.tls(sscA.certificate(), sscA.privateKey()); + b.tls(sscB.certificate(), sscB.privateKey()); sb.virtualHost(a.build()); sb.defaultVirtualHost(b.build()); diff --git a/core/src/test/java/com/linecorp/armeria/client/endpoint/healthcheck/HttpHealthCheckedEndpointGroupTest.java b/core/src/test/java/com/linecorp/armeria/client/endpoint/healthcheck/HttpHealthCheckedEndpointGroupTest.java index 665b11db05ca..70469837852d 100644 --- a/core/src/test/java/com/linecorp/armeria/client/endpoint/healthcheck/HttpHealthCheckedEndpointGroupTest.java +++ b/core/src/test/java/com/linecorp/armeria/client/endpoint/healthcheck/HttpHealthCheckedEndpointGroupTest.java @@ -67,9 +67,9 @@ protected HealthCheckServerRule() { @Override protected void configure(ServerBuilder sb) throws Exception { - sb.port(0, HTTP); - sb.port(0, HTTPS); - sb.sslContext(HTTPS, certificate.certificateFile(), certificate.privateKeyFile()); + sb.http(0); + sb.https(0); + sb.tls(certificate.certificateFile(), certificate.privateKeyFile()); sb.service(HEALTH_CHECK_PATH, new HttpHealthCheckService()); } } diff --git a/core/src/test/java/com/linecorp/armeria/internal/ConnectionLimitingHandlerIntegrationTest.java b/core/src/test/java/com/linecorp/armeria/internal/ConnectionLimitingHandlerIntegrationTest.java index 42c44af272d5..c86eac3e1234 100644 --- a/core/src/test/java/com/linecorp/armeria/internal/ConnectionLimitingHandlerIntegrationTest.java +++ b/core/src/test/java/com/linecorp/armeria/internal/ConnectionLimitingHandlerIntegrationTest.java @@ -16,7 +16,6 @@ package com.linecorp.armeria.internal; -import static org.apache.http.HttpVersion.HTTP; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.awaitility.Awaitility.await; @@ -43,7 +42,6 @@ public class ConnectionLimitingHandlerIntegrationTest { @Override protected void configure(ServerBuilder sb) throws Exception { sb.workerGroup(EventLoopGroups.newEventLoopGroup(1), true); - sb.port(0, HTTP); sb.maxNumConnections(2); sb.serviceUnder("/", new AbstractHttpService() {}); } diff --git a/core/src/test/java/com/linecorp/armeria/server/HttpServerPathTest.java b/core/src/test/java/com/linecorp/armeria/server/HttpServerPathTest.java index feb4b6ae5669..99189b126ae5 100644 --- a/core/src/test/java/com/linecorp/armeria/server/HttpServerPathTest.java +++ b/core/src/test/java/com/linecorp/armeria/server/HttpServerPathTest.java @@ -32,7 +32,6 @@ import com.linecorp.armeria.common.HttpRequest; import com.linecorp.armeria.common.HttpResponse; import com.linecorp.armeria.common.HttpStatus; -import com.linecorp.armeria.common.SessionProtocol; import com.linecorp.armeria.testing.server.ServerRule; import io.netty.util.NetUtil; @@ -43,7 +42,6 @@ public class HttpServerPathTest { public static final ServerRule server = new ServerRule() { @Override protected void configure(ServerBuilder sb) throws Exception { - sb.port(0, SessionProtocol.HTTP); sb.service("/service/foo", new AbstractHttpService() { @Override protected HttpResponse doGet(ServiceRequestContext ctx, HttpRequest req) { diff --git a/core/src/test/java/com/linecorp/armeria/server/HttpServerTest.java b/core/src/test/java/com/linecorp/armeria/server/HttpServerTest.java index 6d784cff6f90..7453edc4ca1f 100644 --- a/core/src/test/java/com/linecorp/armeria/server/HttpServerTest.java +++ b/core/src/test/java/com/linecorp/armeria/server/HttpServerTest.java @@ -20,8 +20,6 @@ import static com.linecorp.armeria.common.SessionProtocol.H1C; import static com.linecorp.armeria.common.SessionProtocol.H2; import static com.linecorp.armeria.common.SessionProtocol.H2C; -import static com.linecorp.armeria.common.SessionProtocol.HTTP; -import static com.linecorp.armeria.common.SessionProtocol.HTTPS; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; import static org.junit.Assert.assertNotNull; @@ -147,11 +145,11 @@ public static Collection parameters() { protected void configure(ServerBuilder sb) throws Exception { sb.workerGroup(workerGroup, true); - sb.port(0, HTTP); - sb.port(0, HTTPS); + sb.http(0); + sb.https(0); SelfSignedCertificate ssc = new SelfSignedCertificate(); - sb.sslContext(HTTPS, ssc.certificate(), ssc.privateKey()); + sb.tls(ssc.certificate(), ssc.privateKey()); sb.service("/delay/{delay}", new AbstractHttpService() { @Override diff --git a/core/src/test/java/com/linecorp/armeria/server/RedirectServiceTest.java b/core/src/test/java/com/linecorp/armeria/server/RedirectServiceTest.java index ce9bb68b1b4d..935eec0bb375 100755 --- a/core/src/test/java/com/linecorp/armeria/server/RedirectServiceTest.java +++ b/core/src/test/java/com/linecorp/armeria/server/RedirectServiceTest.java @@ -64,7 +64,7 @@ protected void configure(ServerBuilder sb) throws Exception { try (ServerSocket ss = new ServerSocket(0)) { final int serverRule1Port = ss.getLocalPort(); - sb.port(serverRule1Port, "HTTP"); + sb.http(serverRule1Port); sb.service("/new0/branch1", SERVICE_BRANCH_1); sb.service("/new0/branch2", SERVICE_BRANCH_2); diff --git a/core/src/test/java/com/linecorp/armeria/server/SniServerTest.java b/core/src/test/java/com/linecorp/armeria/server/SniServerTest.java index 832bd20cb429..e8e57bb5d6b5 100644 --- a/core/src/test/java/com/linecorp/armeria/server/SniServerTest.java +++ b/core/src/test/java/com/linecorp/armeria/server/SniServerTest.java @@ -16,7 +16,6 @@ package com.linecorp.armeria.server; -import static com.linecorp.armeria.common.SessionProtocol.HTTPS; import static org.assertj.core.api.Assertions.assertThat; import java.security.cert.X509Certificate; @@ -75,15 +74,13 @@ protected void configure(ServerBuilder sb) throws Exception { b.service("/", new SniTestService("b.com")); c.service("/", new SniTestService("c.com")); - a.sslContext(HTTPS, sscA.certificateFile(), sscA.privateKeyFile()); - b.sslContext(HTTPS, sscB.certificateFile(), sscB.privateKeyFile()); - c.sslContext(HTTPS, sscC.certificateFile(), sscC.privateKeyFile()); + a.tls(sscA.certificateFile(), sscA.privateKeyFile()); + b.tls(sscB.certificateFile(), sscB.privateKeyFile()); + c.tls(sscC.certificateFile(), sscC.privateKeyFile()); sb.virtualHost(a.build()); sb.virtualHost(b.build()); sb.defaultVirtualHost(c.build()); - - sb.port(0, HTTPS); } }; diff --git a/core/src/test/java/com/linecorp/armeria/server/healthcheck/HttpHealthCheckServiceTest.java b/core/src/test/java/com/linecorp/armeria/server/healthcheck/HttpHealthCheckServiceTest.java index 3b7f2530ea99..8625137ebbe4 100644 --- a/core/src/test/java/com/linecorp/armeria/server/healthcheck/HttpHealthCheckServiceTest.java +++ b/core/src/test/java/com/linecorp/armeria/server/healthcheck/HttpHealthCheckServiceTest.java @@ -16,7 +16,6 @@ package com.linecorp.armeria.server.healthcheck; -import static com.linecorp.armeria.common.SessionProtocol.HTTP; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.when; @@ -115,7 +114,6 @@ private void assertNotOk() throws Exception { @Test public void testGet() throws Exception { final ServerBuilder builder = new ServerBuilder(); - builder.port(0, HTTP); builder.service("/l7check", new HttpHealthCheckService()); final Server server = builder.build(); try { @@ -143,7 +141,6 @@ public void testGet() throws Exception { @Test public void testHead() throws Exception { final ServerBuilder builder = new ServerBuilder(); - builder.port(0, HTTP); builder.service("/l7check", new HttpHealthCheckService()); final Server server = builder.build(); try { diff --git a/grpc/src/test/java/com/linecorp/armeria/client/grpc/GrpcClientTest.java b/grpc/src/test/java/com/linecorp/armeria/client/grpc/GrpcClientTest.java index 1af89201d08e..d7bda4a6f77d 100644 --- a/grpc/src/test/java/com/linecorp/armeria/client/grpc/GrpcClientTest.java +++ b/grpc/src/test/java/com/linecorp/armeria/client/grpc/GrpcClientTest.java @@ -16,7 +16,6 @@ package com.linecorp.armeria.client.grpc; -import static com.linecorp.armeria.common.SessionProtocol.HTTP; import static com.linecorp.armeria.grpc.testing.Messages.PayloadType.COMPRESSABLE; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.catchThrowable; @@ -105,7 +104,6 @@ public class GrpcClientTest { @Override protected void configure(ServerBuilder sb) throws Exception { sb.workerGroup(EventLoopGroups.newEventLoopGroup(1), true); - sb.port(0, HTTP); sb.defaultMaxRequestLength(MAX_MESSAGE_SIZE); sb.idleTimeoutMillis(0); diff --git a/grpc/src/test/java/com/linecorp/armeria/it/grpc/GrpcMetricsIntegrationTest.java b/grpc/src/test/java/com/linecorp/armeria/it/grpc/GrpcMetricsIntegrationTest.java index 1a0e4ce54458..28ec2fa8c6b8 100644 --- a/grpc/src/test/java/com/linecorp/armeria/it/grpc/GrpcMetricsIntegrationTest.java +++ b/grpc/src/test/java/com/linecorp/armeria/it/grpc/GrpcMetricsIntegrationTest.java @@ -44,7 +44,6 @@ import com.linecorp.armeria.common.HttpResponse; import com.linecorp.armeria.common.MediaType; import com.linecorp.armeria.common.SerializationFormat; -import com.linecorp.armeria.common.SessionProtocol; import com.linecorp.armeria.common.grpc.GrpcSerializationFormats; import com.linecorp.armeria.common.metric.MeterIdPrefix; import com.linecorp.armeria.common.metric.MeterIdPrefixFunction; @@ -95,7 +94,6 @@ public void unaryCall2(SimpleRequest request, StreamObserver res @Override protected void configure(ServerBuilder sb) throws Exception { sb.meterRegistry(registry); - sb.port(0, SessionProtocol.HTTP); sb.serviceUnder("/", new GrpcServiceBuilder() .addService(new TestServiceImpl()) .enableUnframedRequests(true) diff --git a/grpc/src/test/java/com/linecorp/armeria/server/grpc/GrpcServiceServerTest.java b/grpc/src/test/java/com/linecorp/armeria/server/grpc/GrpcServiceServerTest.java index 32215bb59acf..c5a02972f89b 100644 --- a/grpc/src/test/java/com/linecorp/armeria/server/grpc/GrpcServiceServerTest.java +++ b/grpc/src/test/java/com/linecorp/armeria/server/grpc/GrpcServiceServerTest.java @@ -16,7 +16,6 @@ package com.linecorp.armeria.server.grpc; -import static com.linecorp.armeria.common.SessionProtocol.HTTP; import static com.linecorp.armeria.internal.grpc.GrpcTestUtil.REQUEST_MESSAGE; import static com.linecorp.armeria.internal.grpc.GrpcTestUtil.RESPONSE_MESSAGE; import static org.assertj.core.api.Assertions.assertThat; @@ -262,7 +261,6 @@ public void streamClientCancelsBeforeResponseClosedCancels( @Override protected void configure(ServerBuilder sb) throws Exception { sb.workerGroup(EventLoopGroups.newEventLoopGroup(1), true); - sb.port(0, HTTP); sb.defaultMaxRequestLength(0); sb.serviceUnder("/", new GrpcServiceBuilder() diff --git a/it/src/test/java/com/linecorp/armeria/server/grpc/interop/ArmeriaGrpcServerInteropTest.java b/it/src/test/java/com/linecorp/armeria/server/grpc/interop/ArmeriaGrpcServerInteropTest.java index 472a925d57a9..60f031a6ed79 100644 --- a/it/src/test/java/com/linecorp/armeria/server/grpc/interop/ArmeriaGrpcServerInteropTest.java +++ b/it/src/test/java/com/linecorp/armeria/server/grpc/interop/ArmeriaGrpcServerInteropTest.java @@ -31,7 +31,6 @@ import com.google.common.collect.ImmutableList; import com.squareup.okhttp.ConnectionSpec; -import com.linecorp.armeria.common.SessionProtocol; import com.linecorp.armeria.server.Server; import com.linecorp.armeria.server.ServerBuilder; import com.linecorp.armeria.server.ServerListenerAdapter; @@ -94,8 +93,8 @@ public void serverStopped(Server server) throws Exception { } }); - sb.port(new InetSocketAddress("127.0.0.1", 0), SessionProtocol.HTTPS); - sb.sslContext(newSslContext()); + sb.https(new InetSocketAddress("127.0.0.1", 0)); + sb.tls(newSslContext()); sb.defaultMaxRequestLength(16 * 1024 * 1024); sb.serviceUnder("/", new GrpcServiceBuilder() .addService(ServerInterceptors.intercept( diff --git a/jetty/src/test/java/com/linecorp/armeria/server/jetty/JettyServiceTest.java b/jetty/src/test/java/com/linecorp/armeria/server/jetty/JettyServiceTest.java index 63b8e4cea2cd..55e1085e5d4a 100644 --- a/jetty/src/test/java/com/linecorp/armeria/server/jetty/JettyServiceTest.java +++ b/jetty/src/test/java/com/linecorp/armeria/server/jetty/JettyServiceTest.java @@ -42,7 +42,6 @@ import org.junit.ClassRule; import org.junit.Test; -import com.linecorp.armeria.common.SessionProtocol; import com.linecorp.armeria.server.ServerBuilder; import com.linecorp.armeria.server.logging.LoggingService; import com.linecorp.armeria.testing.internal.webapp.WebAppContainerTest; @@ -58,11 +57,10 @@ public class JettyServiceTest extends WebAppContainerTest { public static final ServerRule server = new ServerRule() { @Override protected void configure(ServerBuilder sb) throws Exception { - sb.port(0, SessionProtocol.HTTP); - sb.port(0, SessionProtocol.HTTPS); - sb.sslContext(SessionProtocol.HTTPS, - certificate.certificateFile(), - certificate.privateKeyFile()); + sb.http(0); + sb.https(0); + sb.tls(certificate.certificateFile(), + certificate.privateKeyFile()); sb.serviceUnder( "/jsp/", diff --git a/jetty/src/test/java/com/linecorp/armeria/server/jetty/UnmanagedJettyServiceTest.java b/jetty/src/test/java/com/linecorp/armeria/server/jetty/UnmanagedJettyServiceTest.java index 3712d15a55f2..181dbd340aa8 100644 --- a/jetty/src/test/java/com/linecorp/armeria/server/jetty/UnmanagedJettyServiceTest.java +++ b/jetty/src/test/java/com/linecorp/armeria/server/jetty/UnmanagedJettyServiceTest.java @@ -20,7 +20,6 @@ import org.junit.AfterClass; import org.junit.ClassRule; -import com.linecorp.armeria.common.SessionProtocol; import com.linecorp.armeria.server.ServerBuilder; import com.linecorp.armeria.server.logging.LoggingService; import com.linecorp.armeria.testing.internal.webapp.WebAppContainerTest; @@ -34,11 +33,10 @@ public class UnmanagedJettyServiceTest extends WebAppContainerTest { public static final ServerRule server = new ServerRule() { @Override protected void configure(ServerBuilder sb) throws Exception { - sb.port(0, SessionProtocol.HTTP); - sb.port(0, SessionProtocol.HTTPS); - sb.sslContext(SessionProtocol.HTTPS, - certificate.certificateFile(), - certificate.privateKeyFile()); + sb.http(0); + sb.https(0); + sb.tls(certificate.certificateFile(), + certificate.privateKeyFile()); jetty = new Server(0); jetty.setHandler(JettyServiceTest.newWebAppContext()); diff --git a/site/src/sphinx/server-basics.rst b/site/src/sphinx/server-basics.rst index cf7c3474bf1f..0438de094020 100644 --- a/site/src/sphinx/server-basics.rst +++ b/site/src/sphinx/server-basics.rst @@ -28,11 +28,9 @@ To serve anything, you need to specify which TCP/IP port you want to bind onto: .. code-block:: java - import static com.linecorp.armeria.common.SessionProtocol.HTTP; - ServerBuilder sb = new ServerBuilder(); // Configure an HTTP port. - sb.port(8080, HTTP); + sb.http(8080); // TODO: Add your services here. Server server = sb.build(); CompletableFuture future = server.start(); @@ -50,7 +48,6 @@ Even if we opened a port, it's of no use if we didn't bind any services to them. import com.linecorp.armeria.common.HttpResponse; import com.linecorp.armeria.common.HttpStatus; import com.linecorp.armeria.common.MediaType; - import com.linecorp.armeria.common.SessionProtocol; import com.linecorp.armeria.server.AbstractHttpService; import com.linecorp.armeria.server.Server; @@ -65,7 +62,7 @@ Even if we opened a port, it's of no use if we didn't bind any services to them. import com.linecorp.armeria.server.logging.LoggingService; ServerBuilder sb = new ServerBuilder(); - sb.port(8080, HTTP); + sb.http(8080); // Add a simple 'Hello, world!' service. sb.service("/", (ctx, res) -> HttpResponse.of( @@ -158,11 +155,9 @@ You can also add an HTTPS port with your certificate and its private key files: .. code-block:: java - import static com.linecorp.armeria.common.SessionProtocol.HTTPS; - ServerBuilder sb = new ServerBuilder(); - sb.port(8443, HTTPS) - .sslContext(HTTPS, new File("certificate.crt"), new File("private.key"), "myPassphrase"); + sb.https(8443) + .tls(new File("certificate.crt"), new File("private.key"), "myPassphrase"); ... Virtual hosts @@ -179,14 +174,14 @@ Use ``ServerBuilder.withVirtualHost()`` to configure `a name-based virtual host` // Configure foo.com. sb.withVirtualHost("foo.com") .service(...) - .sslContext(...) + .tls(...) .and() // Configure *.bar.com. .withVirtualHost("*.bar.com") .service(...) - .sslContext(...) + .tls(...) .and() // Configure the default virtual host. .service(...) - .sslContext(...); + .tls(...); ... See also diff --git a/site/src/sphinx/server-docservice.rst b/site/src/sphinx/server-docservice.rst index 0c3f6db79e58..3f469c3502ff 100644 --- a/site/src/sphinx/server-docservice.rst +++ b/site/src/sphinx/server-docservice.rst @@ -19,7 +19,7 @@ First, add DocService_ to the ServerBuilder_: .. code-block:: java ServerBuilder sb = new ServerBuilder(); - sb.port(8080, "http"); + sb.http(8080); // Add some RPC services. sb.service("/hello", THttpService.of(new MyHelloService()); // Add DocService. diff --git a/spring-boot/autoconfigure/src/main/java/com/linecorp/armeria/spring/ArmeriaAutoConfiguration.java b/spring-boot/autoconfigure/src/main/java/com/linecorp/armeria/spring/ArmeriaAutoConfiguration.java index 1ec8f83c5f9d..24658548ec9a 100644 --- a/spring-boot/autoconfigure/src/main/java/com/linecorp/armeria/spring/ArmeriaAutoConfiguration.java +++ b/spring-boot/autoconfigure/src/main/java/com/linecorp/armeria/spring/ArmeriaAutoConfiguration.java @@ -57,6 +57,7 @@ import com.linecorp.armeria.server.AbstractHttpService; import com.linecorp.armeria.server.Server; import com.linecorp.armeria.server.ServerBuilder; +import com.linecorp.armeria.server.ServerPort; import com.linecorp.armeria.server.Service; import com.linecorp.armeria.server.ServiceRequestContext; import com.linecorp.armeria.server.docs.DocServiceBuilder; @@ -233,7 +234,7 @@ private static void addPrometheusExposition(ArmeriaSettings armeriaSettings, Ser private static void configurePorts(ArmeriaSettings armeriaSettings, ServerBuilder server) { if (armeriaSettings.getPorts().isEmpty()) { - server.port(DEFAULT_PORT.getPort(), DEFAULT_PORT.getProtocol()); + server.port(new ServerPort(DEFAULT_PORT.getPort(), DEFAULT_PORT.getProtocol())); return; } @@ -245,12 +246,12 @@ private static void configurePorts(ArmeriaSettings armeriaSettings, ServerBuilde if (ip == null) { if (iface == null) { - server.port(new InetSocketAddress(port), proto); + server.port(new ServerPort(port, proto)); } else { try { Enumeration e = NetworkInterface.getByName(iface).getInetAddresses(); while (e.hasMoreElements()) { - server.port(new InetSocketAddress(e.nextElement(), port), proto); + server.port(new ServerPort(new InetSocketAddress(e.nextElement(), port), proto)); } } catch (SocketException e) { throw new IllegalStateException("Failed to find an iface: " + iface, e); @@ -260,7 +261,8 @@ private static void configurePorts(ArmeriaSettings armeriaSettings, ServerBuilde if (NetUtil.isValidIpV4Address(ip) || NetUtil.isValidIpV6Address(ip)) { final byte[] bytes = NetUtil.createByteArrayFromIpAddressString(ip); try { - server.port(new InetSocketAddress(InetAddress.getByAddress(bytes), port), proto); + server.port(new ServerPort(new InetSocketAddress( + InetAddress.getByAddress(bytes), port), proto)); } catch (UnknownHostException e) { // Should never happen. throw new Error(e); diff --git a/thrift/src/test/java/com/linecorp/armeria/client/thrift/ThriftOverHttpClientTest.java b/thrift/src/test/java/com/linecorp/armeria/client/thrift/ThriftOverHttpClientTest.java index acebf1dafa79..5d3fd330c4f6 100644 --- a/thrift/src/test/java/com/linecorp/armeria/client/thrift/ThriftOverHttpClientTest.java +++ b/thrift/src/test/java/com/linecorp/armeria/client/thrift/ThriftOverHttpClientTest.java @@ -189,11 +189,11 @@ String path(SerializationFormat serializationFormat) { final ServerBuilder sb = new ServerBuilder(); try { - sb.port(0, HTTP); - sb.port(0, HTTPS); + sb.http(0); + sb.https(0); ssc = new SelfSignedCertificate("127.0.0.1"); - sb.sslContext(HTTPS, ssc.certificate(), ssc.privateKey()); + sb.tls(ssc.certificate(), ssc.privateKey()); for (Handlers h : Handlers.values()) { for (SerializationFormat defaultSerializationFormat : ThriftSerializationFormats.values()) { diff --git a/thrift/src/test/java/com/linecorp/armeria/server/thrift/AbstractThriftOverHttpTest.java b/thrift/src/test/java/com/linecorp/armeria/server/thrift/AbstractThriftOverHttpTest.java index 81267a4ba96a..a134a15ca036 100644 --- a/thrift/src/test/java/com/linecorp/armeria/server/thrift/AbstractThriftOverHttpTest.java +++ b/thrift/src/test/java/com/linecorp/armeria/server/thrift/AbstractThriftOverHttpTest.java @@ -98,11 +98,11 @@ protected String getResponse(String name) { final ServerBuilder sb = new ServerBuilder(); try { - sb.port(0, HTTP); - sb.port(0, HTTPS); + sb.http(0); + sb.https(0); ssc = new SelfSignedCertificate("127.0.0.1"); - sb.sslContext(HTTPS, ssc.certificate(), ssc.privateKey()); + sb.tls(ssc.certificate(), ssc.privateKey()); sb.service("/hello", THttpService.of( (AsyncIface) (name, resultHandler) -> resultHandler.onComplete("Hello, " + name + '!'))); diff --git a/tomcat/src/test/java/com/linecorp/armeria/server/tomcat/TomcatServiceTest.java b/tomcat/src/test/java/com/linecorp/armeria/server/tomcat/TomcatServiceTest.java index 56809bae3c48..bd42b35e16b9 100644 --- a/tomcat/src/test/java/com/linecorp/armeria/server/tomcat/TomcatServiceTest.java +++ b/tomcat/src/test/java/com/linecorp/armeria/server/tomcat/TomcatServiceTest.java @@ -30,7 +30,6 @@ import org.junit.ClassRule; import org.junit.Test; -import com.linecorp.armeria.common.SessionProtocol; import com.linecorp.armeria.server.ServerBuilder; import com.linecorp.armeria.server.logging.LoggingService; import com.linecorp.armeria.testing.internal.webapp.WebAppContainerTest; @@ -49,11 +48,10 @@ public class TomcatServiceTest extends WebAppContainerTest { public static final ServerRule server = new ServerRule() { @Override protected void configure(ServerBuilder sb) throws Exception { - sb.port(0, SessionProtocol.HTTP); - sb.port(0, SessionProtocol.HTTPS); - sb.sslContext(SessionProtocol.HTTPS, - certificate.certificateFile(), - certificate.privateKeyFile()); + sb.http(0); + sb.https(0); + sb.tls(certificate.certificateFile(), + certificate.privateKeyFile()); sb.serviceUnder( "/jsp/", diff --git a/zookeeper/src/test/java/com/linecorp/armeria/server/zookeeper/ZooKeeperRegistrationTest.java b/zookeeper/src/test/java/com/linecorp/armeria/server/zookeeper/ZooKeeperRegistrationTest.java index 58bb1acf3294..d259294e097f 100644 --- a/zookeeper/src/test/java/com/linecorp/armeria/server/zookeeper/ZooKeeperRegistrationTest.java +++ b/zookeeper/src/test/java/com/linecorp/armeria/server/zookeeper/ZooKeeperRegistrationTest.java @@ -36,7 +36,6 @@ import com.linecorp.armeria.common.HttpRequest; import com.linecorp.armeria.common.HttpResponse; import com.linecorp.armeria.common.HttpStatus; -import com.linecorp.armeria.common.SessionProtocol; import com.linecorp.armeria.common.util.CompletionActions; import com.linecorp.armeria.common.zookeeper.NodeValueCodec; import com.linecorp.armeria.server.AbstractHttpService; @@ -61,7 +60,7 @@ public void startServers() { listeners = new ArrayList<>(); for (Endpoint endpoint : sampleEndpoints) { - Server server = new ServerBuilder().port(endpoint.port(), SessionProtocol.HTTP) + Server server = new ServerBuilder().http(endpoint.port()) .service("/", new EchoService()) .build(); ZooKeeperUpdatingListener listener;