Skip to content

Armeria per-port VirtualHost and random port are incompatible #6410

@davinkevin

Description

@davinkevin

Hello 👋

I'd like to report a behavior. It might not be considered as a bug but it makes developer life a bit more complicated.

To summarize, if I use this kind of code:

fun main(){
    val server = Server.builder().apply {
        service("/foo") { ctx, req -> HttpResponse.of("Hello foo")}
    }
        .http(0)
        .build()

    server.closeOnJvmShutdown()
    server.start().join()
}

It works perfectly and reports a specific port used at startup, like this:

SLF4J(I): Connected with provider of type [ch.qos.logback.classic.spi.LogbackServiceProvider]
08:13:50.854 [armeria-boss-http-*:51313] INFO  -- Serving HTTP at /[0:0:0:0:0:0:0:0]:51313 - http://127.0.0.1:51313/

And if I use multiple ports:

SLF4J(I): Connected with provider of type [ch.qos.logback.classic.spi.LogbackServiceProvider]
08:18:39.446 [armeria-boss-http-*:51461] INFO  -- Serving HTTP at /[0:0:0:0:0:0:0:0]:51461 - http://127.0.0.1:51461/
08:18:39.448 [armeria-boss-http-*:51462] INFO  -- Serving HTTP at /[0:0:0:0:0:0:0:0]:51462 - http://127.0.0.1:51462/

This is very handy, especially in test setup when I want to avoid conflicting port usage in CI.

But, my business case led me to a situation where I have to consider per-port service. For that, we used the VirtualHost feature, but this one is incompatible with random port selection if set to 0.

See, the following code works:

val isRandomPort = System.getenv("IS_RANDOM_PORT").toBooleanStrict()

fun main(){
    val firstHost = if (isRandomPort) 0 else 8080
    val secondHost = if (isRandomPort) 0 else 8081
    val server = Server.builder().apply {

        http(firstHost)
        virtualHost(firstHost).apply {
            service("/foo") { ctx, req -> HttpResponse.of("Hello, foo!")}
        }

        http(secondHost)
        virtualHost(secondHost).apply {
            service("/bar") { ctx, req -> HttpResponse.of("Hello, bar!")}
        }
    }
        .build()

    server.closeOnJvmShutdown()
    server.start().join()
}

But I can't anymore use the random port feature. because they'll both be with 0 and the virtualHost mechanism won't work, with the following error:

> Task :server:run FAILED
SLF4J(I): Connected with provider of type [ch.qos.logback.classic.spi.LogbackServiceProvider]
Exception in thread "main" java.lang.IllegalArgumentException: port: 0 (expected: 1-65535)
        at com.linecorp.armeria.internal.shaded.guava.base.Preconditions.checkArgument(Preconditions.java:191)
        at com.linecorp.armeria.server.ServerBuilder.virtualHost(ServerBuilder.java:1734)
        at com.gitlab.davinkevin.experimentations.armeria.grpc.MainKt.main(Main.kt:15)
        at com.gitlab.davinkevin.experimentations.armeria.grpc.MainKt.main(Main.kt)

FAILURE: Build failed with an exception.
Image

Is there a solution to still leverage the random port feature, almost crucial in CI and being compatible with virtualHost? Maybe something like virtualHost(ServerPort s) where s should be the exact same object provided to the port(…) method.

Thank you for your help,

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions