@Override
    public SELF serviceUnder(String pathPrefix, HttpService service) {
        requireNonNull(pathPrefix, "pathPrefix");
        requireNonNull(service, "service");
        final HttpServiceWithRoutes serviceWithRoutes = service.as(HttpServiceWithRoutes.class);
        if (serviceWithRoutes != null) {
            serviceWithRoutes.routes().forEach(route -> {
                for (String contextPath: contextPaths) {
                    final ServiceConfigBuilder serviceConfigBuilder =
                            new ServiceConfigBuilder(route.withPrefix(pathPrefix), contextPath, service);
                    serviceConfigBuilder.addMappedRoute(route);
                    addServiceConfigSetters(serviceConfigBuilder);
                }
            });
        } else {
            service(Route.builder().pathPrefix(pathPrefix).build(), service);
        }
        return self();
    }
Binds the specified {@link HttpService} under the specified context path.
If the specified {@link HttpService} is an {@link HttpServiceWithRoutes}, the {@code pathPrefix} is added
to each {@link Route} of {@link HttpServiceWithRoutes#routes()}. For example, the
{@code serviceWithRoutes} in the following code will be bound to
({@code "/v1/foo/bar"}) and ({@code "/v1/foo/baz"}):
<pre>{@code
> HttpServiceWithRoutes serviceWithRoutes = new HttpServiceWithRoutes() {
>     @Override
>     public HttpResponse serve(ServiceRequestContext ctx, HttpRequest req) { ... }
>
>     @Override
>     public Set<Route> routes() {
>         return Set.of(Route.builder().path("/bar").build(),
>                       Route.builder().path("/baz").build());
>     }
> };
>
> Server.builder()
>       .contextPath("/v1")
>       .serviceUnder("/foo", serviceWithRoutes)
>       .build();
}</pre>
core/src/main/java/com/linecorp/armeria/server/AbstractContextPathServicesBuilder.java