com.linecorp.armeria.server.ServerBuilder Java Examples

The following examples show how to use com.linecorp.armeria.server.ServerBuilder. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: ServerSentEventsTest.java    From armeria with Apache License 2.0 6 votes vote down vote up
@Override
protected void configure(ServerBuilder sb) throws Exception {
    sb.service("/sse/publisher", (ctx, req) -> ServerSentEvents.fromPublisher(
            Flux.just(ServerSentEvent.ofData("foo"), ServerSentEvent.ofData("bar"))));
    sb.service("/sse/stream", (ctx, req) -> ServerSentEvents.fromStream(
            Stream.of(ServerSentEvent.ofData("foo"), ServerSentEvent.ofData("bar")),
            MoreExecutors.directExecutor()));

    sb.service("/converter/publisher", (ctx, req) -> ServerSentEvents.fromPublisher(
            Flux.just("foo", "bar"), ServerSentEvent::ofComment));
    sb.service("/converter/stream", (ctx, req) -> ServerSentEvents.fromStream(
            Stream.of("foo", "bar"), MoreExecutors.directExecutor(), ServerSentEvent::ofComment));

    sb.service("/single/sse", (ctx, req) -> ServerSentEvents.fromEvent(
            ServerSentEvent.ofEvent("add")));
}
 
Example #2
Source File: TMultiplexedProtocolIntegrationTest.java    From armeria with Apache License 2.0 6 votes vote down vote up
@Override
protected void configure(ServerBuilder sb) throws Exception {
    sb.service(
            "/",
            THttpService.builder()
                        .addService((Iface) name -> "none:" + name)
                        .addService("foo", (Iface) name -> "foo:" + name)
                        .addService("bar", (Iface) name -> "bar:" + name)
                        .build()
                        .decorate((delegate, ctx, req) -> {
                            ctx.log().whenAvailable(RequestLogProperty.REQUEST_CONTENT)
                               .thenAccept(log -> {
                                   final RpcRequest call = (RpcRequest) log.requestContent();
                                   if (call != null) {
                                       methodNames.add(call.method());
                                   }
                               });
                            return delegate.serve(ctx, req);
                        }));
}
 
Example #3
Source File: CentralDogma.java    From centraldogma with Apache License 2.0 6 votes vote down vote up
private void configureMetrics(ServerBuilder sb, PrometheusMeterRegistry registry) {
    sb.meterRegistry(registry);
    sb.service(METRICS_PATH, new PrometheusExpositionService(registry.getPrometheusRegistry()));
    sb.decorator(MetricCollectingService.newDecorator(MeterIdPrefixFunction.ofDefault("api")));

    // Bind system metrics.
    new FileDescriptorMetrics().bindTo(registry);
    new ProcessorMetrics().bindTo(registry);
    new ClassLoaderMetrics().bindTo(registry);
    new UptimeMetrics().bindTo(registry);
    new DiskSpaceMetrics(cfg.dataDir()).bindTo(registry);
    new JvmGcMetrics().bindTo(registry);
    new JvmMemoryMetrics().bindTo(registry);
    new JvmThreadMetrics().bindTo(registry);

    // Bind global thread pool metrics.
    ExecutorServiceMetrics.monitor(registry, ForkJoinPool.commonPool(), "commonPool");
}
 
Example #4
Source File: JsonTextSequencesTest.java    From armeria with Apache License 2.0 6 votes vote down vote up
@Override
protected void configure(ServerBuilder sb) throws Exception {
    sb.service("/seq/publisher",
               (ctx, req) -> JsonTextSequences.fromPublisher(Flux.just("foo", "bar", "baz", "qux")))
      .service("/seq/stream",
               (ctx, req) -> JsonTextSequences.fromStream(
                       Stream.of("foo", "bar", "baz", "qux"), MoreExecutors.directExecutor()))
      .service("/seq/custom-mapper",
               (ctx, req) -> JsonTextSequences.fromPublisher(
                       Flux.just("foo", "bar", "baz", "qux"),
                       new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT)))
      .service("/seq/single",
               (ctx, req) -> JsonTextSequences.fromObject("foo"));
    sb.disableServerHeader();
    sb.disableDateHeader();
}
 
Example #5
Source File: PooledResponseBufferBenchmark.java    From armeria with Apache License 2.0 6 votes vote down vote up
@Setup
public void startServer() throws Exception {
    final ServerBuilder sb =
            Server.builder()
                  .service("/a", THttpService.of((AsyncIface) (name, cb) -> cb.onComplete(RESPONSE))
                                             .decorate(PooledDecoratingService::new))
                  .service("/b", THttpService.of((AsyncIface) (name, cb) -> cb.onComplete(RESPONSE))
                                             .decorate(UnpooledDecoratingService::new));
    server = sb.build();
    server.start().join();

    final int httpPort = server.activeLocalPort(SessionProtocol.HTTP);
    pooledClient = Clients.newClient("tbinary+http://127.0.0.1:" + httpPort + "/a",
                                     HelloService.Iface.class);
    unpooledClient = Clients.newClient("tbinary+http://127.0.0.1:" + httpPort + "/b",
                                       HelloService.Iface.class);
}
 
Example #6
Source File: ArmeriaSpringActuatorAutoConfiguration.java    From armeria with Apache License 2.0 6 votes vote down vote up
private static void configureSecureDecorator(ServerBuilder sb, Port port,
                                             @Nullable String basePath, ArmeriaSettings armeriaSettings) {
    final DecoratingServiceBindingBuilder builder = sb.routeDecorator();
    if (armeriaSettings.isEnableMetrics() && !Strings.isNullOrEmpty(armeriaSettings.getMetricsPath())) {
        builder.path(armeriaSettings.getMetricsPath());
    }
    if (!Strings.isNullOrEmpty(armeriaSettings.getHealthCheckPath())) {
        builder.path(armeriaSettings.getHealthCheckPath());
    }
    if (!Strings.isNullOrEmpty(armeriaSettings.getDocsPath())) {
        builder.path(armeriaSettings.getDocsPath());
    }
    if (!Strings.isNullOrEmpty(basePath)) {
        builder.path(basePath)
               .pathPrefix(basePath);
    }
    builder.build((delegate, ctx, req) -> {
        final InetSocketAddress laddr = ctx.localAddress();
        if (port.getPort() == laddr.getPort()) {
            return delegate.serve(ctx, req);
        } else {
            return HttpResponse.of(404);
        }
    });
}
 
Example #7
Source File: ThrottlingServiceTest.java    From armeria with Apache License 2.0 6 votes vote down vote up
@Override
protected void configure(ServerBuilder sb) throws Exception {
    sb.service("/http-always", SERVICE.decorate(ThrottlingService.newDecorator(always())));
    sb.service("/http-never", SERVICE.decorate(ThrottlingService.newDecorator(never())));
    sb.service("/http-never-custom", SERVICE.decorate(
            ThrottlingService.newDecorator(ThrottlingStrategy.of((ctx, req) -> completedFuture(false)),
                (delegate, ctx, req, cause) -> HttpResponse.of(HttpStatus.SERVICE_UNAVAILABLE))

    ));
    sb.service("/http-always-custom", SERVICE.decorate(
            ThrottlingService.builder(ThrottlingStrategy.of((ctx, req) -> completedFuture(true)))
                             .onAcceptedRequest((delegate, ctx, req) -> {
                                 ctx.addAdditionalResponseHeader(
                                         "X-RateLimit-Limit",
                                         "10, 10;window=1;burst=1000, 1000;window=3600");
                                 return delegate.serve(ctx, req);
                             })
                             .newDecorator()
    ));
}
 
Example #8
Source File: ManagedArmeriaServer.java    From armeria with Apache License 2.0 6 votes vote down vote up
@Override
public void start() throws Exception {
    logger.trace("Getting Armeria Server Builder");
    final ServerBuilder sb = ((ArmeriaServerFactory) serverFactory).getServerBuilder();
    logger.trace("Calling Server Configurator");
    serverConfigurator.configure(sb);
    server = sb.build();
    if (logger.isDebugEnabled()) {
        logger.debug("Built server {}", server);
    }
    logger.info("Starting Armeria Server");
    try {
        server.start().join();
    } catch (Throwable cause) {
        Exceptions.throwUnsafely(Exceptions.peel(cause));
    }
    logger.info("Started Armeria Server");
}
 
Example #9
Source File: DropwizardArmeriaApplication.java    From armeria with Apache License 2.0 6 votes vote down vote up
@Override
public void initialize(Bootstrap<DropwizardArmeriaConfiguration> bootstrap) {
    final ArmeriaBundle<DropwizardArmeriaConfiguration> bundle =
            new ArmeriaBundle<DropwizardArmeriaConfiguration>() {
        @Override
        public void configure(ServerBuilder builder) {
            builder.service("/", (ctx, res) -> HttpResponse.of(MediaType.HTML_UTF_8, "<h2>It works!</h2>"));
            builder.service("/armeria", (ctx, res) -> HttpResponse.of("Hello, Armeria!"));

            builder.annotatedService(new HelloService());

            // You can also bind asynchronous RPC services such as Thrift and gRPC:
            // builder.service(THttpService.of(...));
            // builder.service(GrpcService.builder()...build());
        }
    };
    bootstrap.addBundle(bundle);
}
 
Example #10
Source File: CentralDogma.java    From centraldogma with Apache License 2.0 6 votes vote down vote up
private void configureThriftService(ServerBuilder sb, ProjectManager pm, CommandExecutor executor,
                                    WatchService watchService, MetadataService mds) {
    final CentralDogmaServiceImpl service =
            new CentralDogmaServiceImpl(pm, executor, watchService, mds);

    HttpService thriftService =
            ThriftCallService.of(service)
                             .decorate(CentralDogmaTimeoutScheduler::new)
                             .decorate(CentralDogmaExceptionTranslator::new)
                             .decorate(THttpService.newDecorator());

    if (cfg.isCsrfTokenRequiredForThrift()) {
        thriftService = thriftService.decorate(AuthService.newDecorator(new CsrfTokenAuthorizer()));
    } else {
        thriftService = thriftService.decorate(TokenlessClientLogger::new);
    }

    // Enable content compression for API responses.
    thriftService = thriftService.decorate(contentEncodingDecorator());

    sb.service("/cd/thrift/v1", thriftService);
}
 
Example #11
Source File: UnmanagedTomcatServiceTest.java    From armeria with Apache License 2.0 5 votes vote down vote up
@Override
protected void configure(ServerBuilder sb) throws Exception {
    // Prepare Tomcat instances.
    tomcatWithWebApp = new Tomcat();
    tomcatWithWebApp.setPort(0);
    tomcatWithWebApp.setBaseDir("build" + File.separatorChar +
                                "tomcat-" + UnmanagedTomcatServiceTest.class.getSimpleName() + "-1");

    tomcatWithWebApp.addWebapp("", WebAppContainerTest.webAppRoot().getAbsolutePath());
    TomcatUtil.engine(tomcatWithWebApp.getService(), "foo").setName("tomcatWithWebApp");

    tomcatWithoutWebApp = new Tomcat();
    tomcatWithoutWebApp.setPort(0);
    tomcatWithoutWebApp.setBaseDir("build" + File.separatorChar +
                                   "tomcat-" + UnmanagedTomcatServiceTest.class.getSimpleName() + "-2");
    assertThat(TomcatUtil.engine(tomcatWithoutWebApp.getService(), "bar")).isNotNull();

    // Start the Tomcats.
    tomcatWithWebApp.start();
    tomcatWithoutWebApp.start();

    // Bind them to the Server.
    sb.serviceUnder("/empty/", TomcatService.of(new Connector(), "someHost"))
      .serviceUnder("/some-webapp-nohostname/",
                    TomcatService.of(tomcatWithWebApp.getConnector()))
      .serviceUnder("/no-webapp/", TomcatService.of(tomcatWithoutWebApp))
      .serviceUnder("/some-webapp/", TomcatService.of(tomcatWithWebApp));
}
 
Example #12
Source File: PublisherBasedHttpResponseTest.java    From armeria with Apache License 2.0 5 votes vote down vote up
@Override
protected void configure(ServerBuilder sb) throws Exception {
    sb.service("/", (ctx, req) -> {
        final Flux<HttpObject> publisher = Flux.just(ResponseHeaders.of(200), HttpData.ofUtf8("hello"));
        final HttpResponse response = HttpResponse.of(publisher);
        response.whenComplete().whenComplete((unused, cause) -> {
            exceptionIsRaised.set(cause != null);
        });
        return response;
    });
}
 
Example #13
Source File: RetryingClientAuthorityHeaderTest.java    From armeria with Apache License 2.0 5 votes vote down vote up
@Override
protected void configure(ServerBuilder sb) throws Exception {
    sb.service("/", new AbstractHttpService() {

        @Override
        protected HttpResponse doGet(ServiceRequestContext ctx, HttpRequest req) throws Exception {
            return HttpResponse.of(req.headers().authority());
        }
    });
    sb.decorator(LoggingService.newDecorator());
}
 
Example #14
Source File: GrpcFlowControlTest.java    From armeria with Apache License 2.0 5 votes vote down vote up
@Override
protected void configure(ServerBuilder sb) throws Exception {
    sb.maxRequestLength(0);
    sb.requestTimeoutMillis(0);

    sb.serviceUnder("/",
                    GrpcService.builder()
                               .addService(new FlowControlService())
                               .setMaxInboundMessageSizeBytes(Integer.MAX_VALUE)
                               .build());
}
 
Example #15
Source File: GrpcMetricsIntegrationTest.java    From armeria with Apache License 2.0 5 votes vote down vote up
@Override
protected void configure(ServerBuilder sb) throws Exception {
    sb.meterRegistry(registry);
    sb.service(GrpcService.builder()
                          .addService(new TestServiceImpl())
                          .enableUnframedRequests(true)
                          .build(),
               MetricCollectingService.newDecorator(MeterIdPrefixFunction.ofDefault("server")),
               LoggingService.newDecorator());
}
 
Example #16
Source File: JettyServiceTest.java    From armeria with Apache License 2.0 5 votes vote down vote up
@Override
protected void configure(ServerBuilder sb) throws Exception {
    sb.http(0);
    sb.https(0);
    sb.tlsSelfSigned();

    sb.serviceUnder(
            "/jsp/",
            JettyService.builder()
                        .handler(newWebAppContext())
                        .configurator(s -> jettyBeans.addAll(s.getBeans()))
                        .build()
                        .decorate(LoggingService.newDecorator()));

    sb.serviceUnder(
            "/default/",
            JettyService.builder()
                        .handler(new DefaultHandler())
                        .build());

    final ResourceHandler resourceHandler = new ResourceHandler();
    resourceHandler.setResourceBase(webAppRoot().getPath());
    sb.serviceUnder(
            "/resources/",
            JettyService.builder()
                        .handler(resourceHandler)
                        .build());
}
 
Example #17
Source File: HttpClientMaxConcurrentStreamTest.java    From armeria with Apache License 2.0 5 votes vote down vote up
@Override
protected void configure(ServerBuilder sb) throws Exception {
    sb.service(PATH, (ctx, req) -> {
        final CompletableFuture<HttpResponse> f = new CompletableFuture<>();
        responses.add(f);
        return HttpResponse.from(f);
    });
    sb.http2MaxStreamsPerConnection(1);
    sb.maxNumConnections(MAX_NUM_CONNECTIONS);
    sb.idleTimeoutMillis(3000);
}
 
Example #18
Source File: GrpcDocServicePluginTest.java    From armeria with Apache License 2.0 5 votes vote down vote up
private static Map<String, ServiceInfo> services(DocServiceFilter include, DocServiceFilter exclude) {
    final ServerBuilder serverBuilder = Server.builder();

    // The case where a GrpcService is added to ServerBuilder without a prefix.
    final HttpServiceWithRoutes prefixlessService =
            GrpcService.builder()
                       .addService(mock(TestServiceImplBase.class))
                       .build();
    serverBuilder.service(prefixlessService);

    // The case where a GrpcService is added to ServerBuilder with a prefix.
    serverBuilder.service(
            Route.builder().pathPrefix("/test").build(),
            GrpcService.builder().addService(mock(UnitTestServiceImplBase.class)).build());

    // Another GrpcService with a different prefix.
    serverBuilder.service(
            Route.builder().pathPrefix("/reconnect").build(),
            GrpcService.builder().addService(mock(ReconnectServiceImplBase.class)).build());

    // Make sure all services and their endpoints exist in the specification.
    final ServiceSpecification specification = generator.generateSpecification(
            ImmutableSet.copyOf(serverBuilder.build().serviceConfigs()),
            unifyFilter(include, exclude));
    return specification
            .services()
            .stream()
            .collect(toImmutableMap(ServiceInfo::name, Function.identity()));
}
 
Example #19
Source File: DropwizardMetricsIntegrationTest.java    From armeria with Apache License 2.0 5 votes vote down vote up
@Override
protected void configure(ServerBuilder sb) throws Exception {
    sb.meterRegistry(registry);
    sb.service("/helloservice", THttpService.of((Iface) name -> {
        if ("world".equals(name)) {
            return "success";
        }
        throw new IllegalArgumentException("bad argument");
    }).decorate(MetricCollectingService.newDecorator(
            MeterIdPrefixFunction.ofDefault("armeria.server.hello.service"))));
}
 
Example #20
Source File: RetryingClientAuthorityHeaderTest.java    From armeria with Apache License 2.0 5 votes vote down vote up
@Override
protected void configure(ServerBuilder sb) throws Exception {
    sb.service("/", new AbstractHttpService() {

        @Override
        protected HttpResponse doGet(ServiceRequestContext ctx, HttpRequest req) throws Exception {
            return HttpResponse.of(SERVICE_UNAVAILABLE);
        }
    });
    sb.decorator(LoggingService.newDecorator());
}
 
Example #21
Source File: Main.java    From armeria with Apache License 2.0 5 votes vote down vote up
/**
 * Returns a new {@link Server} instance configured with annotated HTTP services.
 *
 * @param port the port that the server is to be bound to
 */
static Server newServer(int port) {
    final ServerBuilder sb = Server.builder();
    return sb.http(port)
             .annotatedService("/pathPattern", new PathPatternService())
             .annotatedService("/injection", new InjectionService())
             .annotatedService("/messageConverter", new MessageConverterService())
             .annotatedService("/exception", new ExceptionHandlerService())
             .serviceUnder("/docs", new DocService())
             .build();
}
 
Example #22
Source File: ArmeriaCallFactoryLargeStreamTest.java    From armeria with Apache License 2.0 5 votes vote down vote up
@Override
protected void configure(ServerBuilder sb) throws Exception {
    sb.service("/large-stream", new AbstractHttpService() {
        @Override
        protected HttpResponse doGet(ServiceRequestContext ctx, HttpRequest req) throws Exception {
            return HttpResponse.of(s -> s.onSubscribe(new Subscription() {
                int count;

                @Override
                public void request(long n) {
                    for (int i = 0; i < n; i++) {
                        if (count == 0) {
                            s.onNext(ResponseHeaders.of(HttpStatus.OK));
                        } else {
                            s.onNext(HttpData.wrap(new byte[1024]));
                        }
                    }
                    count += n;
                    // 10MB
                    if (count > 1024 * 10) {
                        s.onComplete();
                    }
                }

                @Override
                public void cancel() {
                }
            }));
        }
    });
    sb.requestTimeout(Duration.of(30, ChronoUnit.SECONDS));
}
 
Example #23
Source File: RetryingRpcClientTest.java    From armeria with Apache License 2.0 5 votes vote down vote up
@Override
protected void configure(ServerBuilder sb) throws Exception {
    final AtomicInteger retryCount = new AtomicInteger();
    sb.service("/thrift", THttpService.of(serviceHandler).decorate(
            (delegate, ctx, req) -> {
                final int count = retryCount.getAndIncrement();
                if (count != 0) {
                    assertThat(count).isEqualTo(req.headers().getInt(ARMERIA_RETRY_COUNT));
                }
                return delegate.serve(ctx, req);
            }));
    sb.service("/thrift-devnull", THttpService.of(devNullServiceHandler));
}
 
Example #24
Source File: ServerApplication.java    From skywalking with Apache License 2.0 5 votes vote down vote up
@PostConstruct
public void init() {
    ServerBuilder sb = new ServerBuilder().http(8085)
                                          .service("/healthCheck", (ctx, res) -> HttpResponse.of(SUCCESS))
                                          .service("/greet/{name}", (ctx, res) -> HttpResponse.of("Hello %s~", ctx.pathParam("name")));

    Server server = sb.build();
    CompletableFuture<Void> future = server.start();
    future.join();
}
 
Example #25
Source File: CompositeServiceTest.java    From armeria with Apache License 2.0 5 votes vote down vote up
@Override
protected void configure(ServerBuilder sb) throws Exception {
    sb.meterRegistry(PrometheusMeterRegistries.newRegistry());
    sb.serviceUnder("/qux/", composite);

    // Should not hit the following services
    sb.serviceUnder("/foo/", otherService);
    sb.serviceUnder("/bar/", otherService);
    sb.service(Route.builder().glob("/*").build(), otherService);
}
 
Example #26
Source File: ArmeriaConfigurationUtilTest.java    From armeria with Apache License 2.0 5 votes vote down vote up
@Test
void makesSureDecoratedServiceIsAdded() {
    final Function<? super HttpService, ? extends HttpService> decorator = spy(new DecoratingFunction());
    final AnnotatedServiceRegistrationBean bean = new AnnotatedServiceRegistrationBean()
            .setServiceName("test")
            .setService(new SimpleService())
            .setDecorators(decorator);

    final ServerBuilder sb = Server.builder();
    final DocServiceBuilder dsb = DocService.builder();
    configureAnnotatedServices(sb, dsb, ImmutableList.of(bean), null, null);
    final Server s = sb.build();
    verify(decorator, times(2)).apply(any());
    assertThat(service(s).as(SimpleDecorator.class)).isNotNull();
}
 
Example #27
Source File: ArmeriaConfigurationUtilTest.java    From armeria with Apache License 2.0 5 votes vote down vote up
@Test
void makesSureDecoratorsAreConfigured() {
    final Function<? super HttpService, ? extends HttpService> decorator = spy(new IdentityFunction());
    final AnnotatedServiceRegistrationBean bean = new AnnotatedServiceRegistrationBean()
            .setServiceName("test")
            .setService(new SimpleService())
            .setDecorators(decorator);

    final ServerBuilder sb1 = Server.builder();
    final DocServiceBuilder dsb1 = DocService.builder();
    configureAnnotatedServices(sb1, dsb1, ImmutableList.of(bean),
                                   MeterIdPrefixFunctionFactory.ofDefault(), null);
    final Server s1 = sb1.build();
    verify(decorator, times(2)).apply(any());
    assertThat(service(s1).as(MetricCollectingService.class)).isNotNull();

    reset(decorator);

    final ServerBuilder sb2 = Server.builder();
    final DocServiceBuilder dsb2 = DocService.builder();
    configureAnnotatedServices(sb2, dsb2, ImmutableList.of(bean),
                                   null, null);
    final Server s2 = sb2.build();
    verify(decorator, times(2)).apply(any());
    assertThat(getServiceForHttpMethod(sb2.build(), HttpMethod.OPTIONS))
            .isInstanceOf(AnnotatedService.class);
}
 
Example #28
Source File: HealthCheckedEndpointGroupCompatibilityTest.java    From armeria with Apache License 2.0 5 votes vote down vote up
@Override
protected void configure(ServerBuilder sb) throws Exception {
    sb.service("/no_value",
               (ctx, req) -> HttpResponse.of(HttpStatus.OK));
    sb.service("/bad_value",
               (ctx, req) -> HttpResponse.of(ResponseHeaders.of(
                       HttpStatus.OK, "armeria-lphc", "bad_value")));
    sb.service("/0.97",
               (ctx, req) -> HttpResponse.of(ResponseHeaders.of(
                       HttpStatus.OK, "armeria-lphc", 60)));
}
 
Example #29
Source File: AnnotatedServiceHandlersOrderTest.java    From armeria with Apache License 2.0 5 votes vote down vote up
@Override
protected void configure(ServerBuilder sb) throws Exception {
    sb.annotatedServiceExtensions(ImmutableList.of(new ServerLevelRequestConverter()),
                                  ImmutableList.of(new ServerLevelResponseConverter()),
                                  ImmutableList.of(new ServerLevelExceptionHandler()))
      .annotatedService("/1", new MyDecorationService1(), LoggingService.newDecorator(),
                        new ServiceLevelRequestConverter(), new ServiceLevelResponseConverter(),
                        new ServiceLevelExceptionHandler());
}
 
Example #30
Source File: HttpRequestSubscriberTest.java    From armeria with Apache License 2.0 5 votes vote down vote up
@Override
protected void configure(ServerBuilder sb) throws Exception {
    final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();

    // TODO(hyangtack) Remove one of the following services.
    // Returning a response immediately causes a failure of a test with PublisherBasedHttpRequest.
    sb.service("/ok", (ctx, req) -> HttpResponse.of(HttpStatus.OK));
    sb.service("/delayed_ok", (ctx, req) -> {
                   final CompletableFuture<HttpResponse> f = new CompletableFuture<>();
                   executor.schedule(() -> f.complete(HttpResponse.of(HttpStatus.OK)),
                                     100, TimeUnit.MILLISECONDS);
                   return HttpResponse.from(f);
               }
    );
}