Skip to content

Add VirtualHost support for random ports (#6410)#6603

Merged
ikhoon merged 11 commits intoline:mainfrom
junjunclub:feature/virtualhost-random-port-support
Apr 3, 2026
Merged

Add VirtualHost support for random ports (#6410)#6603
ikhoon merged 11 commits intoline:mainfrom
junjunclub:feature/virtualhost-random-port-support

Conversation

@junjunclub
Copy link
Copy Markdown
Contributor

@junjunclub junjunclub commented Jan 24, 2026

Motivation

Currently, using virtualHost(0) throws an IllegalArgumentException:
java.lang.IllegalArgumentException: port: 0 (expected: 1-65535)

This is problematic for CI environments where random ports are essential to avoid port conflicts. The existing virtualHost(int port) API cannot support random ports because:

  • The int value 0 cannot distinguish between multiple random ports.
  • Calling virtualHost(0) twice returns the same VirtualHostBuilder due to the builder reuse logic.

See: issue #6410

Modifications

  • Added ServerBuilder.virtualHost(ServerPort) API that uses reference equality to distinguish different random port configurations.
  • Added VirtualHostBuilder.serverPort field and constructor to support ServerPort-based virtual hosts.
  • Added VirtualHost.serverPort field and accessor.
  • Added ServerPort.originalServerPort field to track the original configuration when binding to ephemeral ports.
  • Passed original ServerPort reference when creating actualPort in Server.java.
  • Updated DefaultServerConfig.findVirtualHost() to route requests based on the actual bound port (priority lookup).
  • Added unit tests for VirtualHostBuilder.serverPort(), VirtualHost.serverPort(), and ServerPort.originalServerPort() accessors.
  • Added integration test for the new virtualHost(ServerPort) API routing behavior.

Result

ServerPort port1 = new ServerPort(0, SessionProtocol.HTTP);
ServerPort port2 = new ServerPort(0, SessionProtocol.HTTP);

Server server = Server.builder()
    .port(port1)
    .virtualHost(port1)
        .service("/foo", (ctx, req) -> HttpResponse.of("foo"))
    .and()
    .port(port2)
    .virtualHost(port2)
        .service("/bar", (ctx, req) -> HttpResponse.of("bar"))
    .and()
    .build();

Each ServerPort instance is assigned a different random port by the OS, and requests are correctly routed to the corresponding VirtualHost.


Follow-up: O(1) ServerPort-based VirtualHost lookup (new in this PR)

While implementing virtualHost(ServerPort), we noticed that findVirtualHost(String hostname, int port) can become inefficient for ServerPort-based virtual hosts using ephemeral ports, because it may scan activePorts and virtualHosts to resolve the actual bound port.

This PR also introduces an actualPort() approach and a precomputed mapping to make this routing step O(1) after all ports are bound.

Additional changes

  • ServerPort.actualPort()

    • Added volatile int actualPort to store the actual bound port.
    • Added actualPort() getter and package-private setActualPort(int) setter.
  • Server.java

    • Call port.setActualPort(...) after binding ephemeral ports.
  • DefaultServerConfig

    • Added volatile Map<Integer, VirtualHost> actualPortToVirtualHost.
    • Added buildActualPortMapping() to populate the mapping after all ports are bound.
    • Updated findVirtualHost(String, int) to prefer the O(1) map lookup for ServerPort-based routing.
  • Tests

    • Added unit tests for ServerPort.actualPort() getter/setter behavior.
    • Added integration tests verifying actualPort is reflected after server start and that multiple random-port virtual hosts work as expected.

Outcome

  • findVirtualHost() now performs O(1) lookup for ServerPort-based virtual host routing once ports are bound.
  • ServerPort.actualPort() provides a clean API to retrieve the actual bound port.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Jan 24, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds ServerPort-aware virtual hosts and runtime port mapping: ServerPort now tracks actual bound ports; ServerBuilder gains virtualHost(ServerPort) and validates ServerPort presence; VirtualHost/VirtualHostBuilder carry ServerPort; DefaultServerConfig builds/rebuilds domain-and-port mappings after ports bind; tests added for ephemeral-port scenarios.

Changes

Cohort / File(s) Summary
Server core: ServerPort & binding
core/src/main/java/com/linecorp/armeria/server/ServerPort.java, core/src/main/java/com/linecorp/armeria/server/Server.java
Add actualPort field, actualPort() accessor and setActualPort(); propagate bound ephemeral port back to the original ServerPort after bind; Server.doStart triggers mapping rebuild.
Builder API & validation
core/src/main/java/com/linecorp/armeria/server/ServerBuilder.java
Add public VirtualHostBuilder virtualHost(ServerPort) overload; validate that any VirtualHost bound to a ServerPort references a ServerPort present in the server's ports list at build time.
VirtualHost wiring
core/src/main/java/com/linecorp/armeria/server/VirtualHost.java, core/src/main/java/com/linecorp/armeria/server/VirtualHostBuilder.java
Carry optional ServerPort through constructors and builders; add accessor; preserve serverPort during decoration/ssl changes; augment cached hostname/hostnamePattern to include serverPort.actualPort() when bound.
Runtime config & resolution
core/src/main/java/com/linecorp/armeria/server/DefaultServerConfig.java
Make per-port mapping volatile; exclude port-bound hosts from name-only domain map; add rebuildDomainAndPortMapping() and adapt findVirtualHost(hostname, port) to consult port mappings (including ServerPort.actualPort()) before name-based lookup.
Tests
core/src/test/java/com/linecorp/armeria/server/PortBasedVirtualHostTest.java, core/src/test/java/com/linecorp/armeria/server/ServerPortTest.java
Add/extend tests for ServerPort behavior and ServerPort-based virtual hosts: ephemeral-port binding, setActualPort validation, virtualHost(ServerPort) semantics, routing per-port, and reuse/isolation cases.

Sequence Diagram(s)

sequenceDiagram
    participant App as Application
    participant SB as ServerBuilder
    participant SP as ServerPort
    participant VHB as VirtualHostBuilder
    participant S as Server
    participant DSC as DefaultServerConfig
    participant Client as Client

    App->>SB: port(ServerPort) / port(0)
    SB->>SP: create ServerPort(ephemeral)
    App->>SB: virtualHost(ServerPort)
    SB->>VHB: new VirtualHostBuilder(ServerPort)
    VHB-->>SB: register VirtualHostBuilder(serverPort)
    App->>SB: build()
    SB->>S: build/start
    S->>SP: bind to actual port (OS)
    S->>SP: setActualPort(actualPort)
    S->>DSC: rebuildDomainAndPortMapping()
    Client->>DSC: findVirtualHost(hostname, actualPort)
    DSC-->>Client: return VirtualHost bound to original ServerPort
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested labels

new feature

Suggested reviewers

  • trustin
  • minwoox
  • ikhoon

Poem

🐇 I nudged the zero, held tight to my seed,
Kept my origin through bind and need.
When OS gave a number, I claimed my spot,
Hosts find their door where the true port got. 🥕

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@core/src/main/java/com/linecorp/armeria/server/ServerBuilder.java`:
- Around line 2506-2513: The validation currently uses
this.ports.contains(serverPort) which relies on equals() but runtime matching
requires reference identity; update the check in the ServerBuilder validation
loop (involving VirtualHostBuilder and its serverPort() call) to test identity
instead of equality (e.g., ensure any entry in this.ports is == serverPort) and
keep the existing checkState message; locate the block using VirtualHostBuilder
vhb, serverPort(), and this.ports and replace the contains(...) condition with
an identity-based predicate (anyMatch(p -> p == serverPort) or equivalent).
- Around line 1860-1889: The new public overload virtualHost(ServerPort) in
ServerBuilder must be annotated with `@UnstableApi` to mark the API as unstable;
update the declaration of the virtualHost(ServerPort) method in ServerBuilder to
add the `@UnstableApi` annotation (importing it if needed) so the public API
surface for VirtualHostBuilder returned by virtualHost(ServerPort) is properly
marked per project guidelines.
🧹 Nitpick comments (2)
core/src/test/java/com/linecorp/armeria/server/PortBasedVirtualHostTest.java (1)

241-331: Add assertions for /bar routing in virtualHostWithServerPort.
Right now /bar responses are computed but never asserted, so misrouting could slip through.

✅ Proposed test assertion
             // Check /bar on both ports
             final AggregatedHttpResponse resp1Bar = client1.get("/bar").aggregate().join();
             final AggregatedHttpResponse resp2Bar = client2.get("/bar").aggregate().join();

             // One port should serve /foo with OK, the other with NOT_FOUND
             final boolean port1ServesFoo = resp1Foo.status() == HttpStatus.OK;
             final boolean port2ServesFoo = resp2Foo.status() == HttpStatus.OK;
             assertThat(port1ServesFoo || port2ServesFoo)
                     .as("At least one port should serve /foo, but got: port1=%s, port2=%s",
                         resp1Foo.status(), resp2Foo.status())
                     .isTrue();
+            // One port should serve /bar with OK as well.
+            final boolean port1ServesBar = resp1Bar.status() == HttpStatus.OK;
+            final boolean port2ServesBar = resp2Bar.status() == HttpStatus.OK;
+            assertThat(port1ServesBar || port2ServesBar)
+                    .as("At least one port should serve /bar, but got: port1=%s, port2=%s",
+                        resp1Bar.status(), resp2Bar.status())
+                    .isTrue();
core/src/main/java/com/linecorp/armeria/server/VirtualHost.java (1)

316-341: Consider documenting the dynamic port resolution behavior.

The defaultHostname() and hostnamePattern() methods now return different values depending on whether the server has bound to its ports. Before binding, serverPort.localAddress() returns null, so the pre-computed value is returned. After binding, the actual ephemeral port is appended.

This dynamic behavior is intentional for ephemeral port support, but callers may not expect the return value to change over the VirtualHost lifecycle. Consider adding Javadoc clarification, e.g.:

/**
 * Returns the default hostname of this virtual host. If this virtual host is bound to a
 * {`@link` ServerPort} with an ephemeral port (0), the actual bound port is appended after
 * the server starts.
 */

Comment thread core/src/main/java/com/linecorp/armeria/server/ServerBuilder.java
Comment thread core/src/main/java/com/linecorp/armeria/server/ServerBuilder.java Outdated
Comment thread core/src/main/java/com/linecorp/armeria/server/DefaultServerConfig.java Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In
`@core/src/test/java/com/linecorp/armeria/server/PortBasedVirtualHostTest.java`:
- Around line 241-286: The test virtualHostWithServerPort collects responses for
/foo and /bar but never asserts the /bar results; update the test to compute
booleans for resp1Bar.status() and resp2Bar.status() (e.g., port1ServesBar,
port2ServesBar) and add assertions: (1) at least one port serves /bar
(port1ServesBar || port2ServesBar) and (2) ensure exclusivity per port by
asserting each port serves exactly one of the endpoints (for each port assert
(servesFoo ^ servesBar) is true), referencing the existing
resp1Foo/resp2Foo/resp1Bar/resp2Bar variables in virtualHostWithServerPort so
the test verifies both routing and exclusivity.
♻️ Duplicate comments (2)
core/src/main/java/com/linecorp/armeria/server/ServerBuilder.java (2)

1860-1903: Add @UnstableApi to the new public overload.
New public APIs should be annotated as unstable per project guidelines.

✅ Proposed fix
+    `@UnstableApi`
     public VirtualHostBuilder virtualHost(ServerPort serverPort) {
         requireNonNull(serverPort, "serverPort");
As per coding guidelines, ...

2506-2513: Validate ServerPort by identity, not equals.
contains() uses equals, but runtime matching uses reference identity (==), so a different-but-equal instance would pass validation yet never match.

🐛 Proposed fix
-            if (serverPort != null) {
-                checkState(this.ports.contains(serverPort),
+            if (serverPort != null) {
+                final boolean presentByIdentity = this.ports.stream().anyMatch(p -> p == serverPort);
+                checkState(presentByIdentity,
                            "The ServerPort for a virtual host is not in the server's port list. " +
                            "Please add the ServerPort using port(ServerPort) before creating a virtual host.");
             }
🧹 Nitpick comments (1)
core/src/main/java/com/linecorp/armeria/server/DefaultServerConfig.java (1)

427-445: Consider avoiding per-request full scans when no ServerPort-based vhosts exist.
findVirtualHost(...) now iterates active ports (and then virtual hosts) on every request; a boolean guard or a precomputed map could keep the hot path cheaper.

Comment thread core/src/test/java/com/linecorp/armeria/server/PortBasedVirtualHostTest.java Outdated
@codecov
Copy link
Copy Markdown

codecov bot commented Jan 26, 2026

Codecov Report

❌ Patch coverage is 81.44330% with 18 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.26%. Comparing base (8150425) to head (ed1c481).
⚠️ Report is 387 commits behind head on main.

Files with missing lines Patch % Lines
.../java/com/linecorp/armeria/server/VirtualHost.java 45.45% 10 Missing and 2 partials ⚠️
...n/java/com/linecorp/armeria/server/ServerPort.java 72.22% 3 Missing and 2 partials ⚠️
...ava/com/linecorp/armeria/server/ServerBuilder.java 93.75% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #6603      +/-   ##
============================================
- Coverage     74.46%   74.26%   -0.20%     
- Complexity    22234    23974    +1740     
============================================
  Files          1963     2161     +198     
  Lines         82437    89633    +7196     
  Branches      10764    11707     +943     
============================================
+ Hits          61385    66570    +5185     
- Misses        15918    17482    +1564     
- Partials       5134     5581     +447     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread core/src/main/java/com/linecorp/armeria/server/DefaultServerConfig.java Outdated
…lookup

- Add actualPort field and methods to ServerPort for storing actual bound port
- Add actualPortToVirtualHost map to DefaultServerConfig for O(1) lookup
- Update Server to set actualPort after binding and build port mapping
- Add tests for actualPort and multiple random port VirtualHosts
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
core/src/main/java/com/linecorp/armeria/server/Server.java (1)

800-825: ⚠️ Potential issue | 🔴 Critical

Add build-time validation to prevent virtualHost(ServerPort) with port groups or ensure setActualPort() is called for port group reuse scenarios.

When a ServerPort belongs to a port group and reuses a previously bound port in NextServerPortStartListener (lines 900-904), the temporary ServerPort created doesn't have setActualPort() called on the original config port. This causes buildActualPortMapping() to skip creating routing entries for ephemeral ports, breaking port-based virtual host routing silently.

Consider adding a build-time check in ServerBuilder to either:

  1. Reject configurations where virtualHost(ServerPort) uses a ServerPort with a portGroup, or
  2. Fix the runtime behavior to ensure setActualPort() is called for all reused ports in a port group
🤖 Fix all issues with AI agents
In `@core/src/main/java/com/linecorp/armeria/server/DefaultServerConfig.java`:
- Around line 405-423: ServerBuilder.virtualHost(ServerPort) currently accepts
any ServerPort but DefaultServerConfig.buildActualPortMapping only maps
ephemeral ports (where ServerPort.localAddress().getPort() == 0), so add a
validation in ServerBuilder.virtualHost(ServerPort) to enforce ephemeral ports:
check serverPort.localAddress().getPort() == 0 and throw an
IllegalArgumentException (or use Objects.requireNonNull/assert) with a clear
message if not ephemeral; reference ServerBuilder.virtualHost(ServerPort),
ServerPort.localAddress().getPort(), and
DefaultServerConfig.buildActualPortMapping to locate the related logic.

In `@core/src/main/java/com/linecorp/armeria/server/ServerPort.java`:
- Around line 249-260: Add the `@UnstableApi` annotation to the new public method
actualPort() in the ServerPort class to follow project guidelines for newly
added public APIs; update imports to include the UnstableApi annotation (e.g.,
com.linecorp.armeria.common.annotation.UnstableApi) and place the annotation
immediately above the actualPort() method signature so the method is marked as
unstable.
🧹 Nitpick comments (2)
core/src/main/java/com/linecorp/armeria/server/ServerPort.java (2)

270-277: setActualPort has a non-atomic check-then-act on a volatile field.

The guard checkState(this.actualPort == -1, ...) followed by this.actualPort = actualPort is not atomic. While this is package-private and currently only called from a single event-loop thread in ServerPortStartListener, a future caller from a different thread could trigger a race where two threads both see -1 and both proceed to write.

Consider either:

  • Documenting the single-thread assumption (e.g., @GuardedBy or a Javadoc note), or
  • Using a CAS via AtomicInteger / VarHandle for correctness.

337-345: toString() does not reflect actualPort or originalServerPort.

After binding, actualPort holds meaningful diagnostic information (the real ephemeral port). Including it in toString() would improve debuggability when inspecting bound ports in logs.

Comment thread core/src/main/java/com/linecorp/armeria/server/ServerPort.java
- Add @UnstableApi annotation to ServerPort.actualPort() per Armeria conventions
- Add fixedPortVirtualHostWithServerPort() test to verify virtualHost(ServerPort) works correctly
Comment thread core/src/main/java/com/linecorp/armeria/server/DefaultServerConfig.java Outdated
Comment thread core/src/main/java/com/linecorp/armeria/server/ServerPort.java Outdated
Copy link
Copy Markdown
Contributor

@jrhee17 jrhee17 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes look reasonable to me 👍

Comment thread core/src/main/java/com/linecorp/armeria/server/VirtualHost.java Outdated
Comment thread core/src/main/java/com/linecorp/armeria/server/VirtualHost.java Outdated
- Defer VirtualHost domain/port mapping until after ports are bound,
  unifying virtualHostAndPortMapping and actualPortToVirtualHost into
  a single volatile map that is rebuilt via rebuildDomainAndPortMapping()
- Remove originalServerPort from ServerPort as it is no longer used
  after the mapping unification
- Cache defaultHostname() and hostnamePattern() results in VirtualHost
  to avoid repeated String allocation on every call
- Remove unnecessary null check on ServerPort.localAddress() which is
  guaranteed non-null by requireNonNull in constructor
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
core/src/main/java/com/linecorp/armeria/server/DefaultServerConfig.java (2)

447-465: ⚠️ Potential issue | 🟠 Major

Multiple reads of volatile virtualHostAndPortMapping — use a local snapshot.

findVirtualHost reads the volatile field on lines 449, 453, and 463 without capturing it in a local variable. If rebuildDomainAndPortMapping() replaces the reference between reads, different reads may see different map instances, leading to inconsistent lookups within a single call.

Proposed fix
     `@Override`
     public VirtualHost findVirtualHost(String hostname, int port) {
-        if (virtualHostAndPortMapping == null) {
+        final Int2ObjectMap<Mapping<String, VirtualHost>> mapping = virtualHostAndPortMapping;
+        if (mapping == null) {
             return defaultVirtualHost;
         }
 
-        final Mapping<String, VirtualHost> virtualHostMapping = virtualHostAndPortMapping.get(port);
+        final Mapping<String, VirtualHost> virtualHostMapping = mapping.get(port);
         if (virtualHostMapping != null) {
             final VirtualHost virtualHost = virtualHostMapping.map(hostname + ':' + port);
             // Exclude the default virtual host from port-based virtual hosts.
             if (virtualHost != defaultVirtualHost) {
                 return virtualHost;
             }
         }
 
         // No port-based virtual host is configured. Look for named-based virtual host.
-        final Mapping<String, VirtualHost> nameBasedMapping = requireNonNull(virtualHostAndPortMapping.get(-1));
+        final Mapping<String, VirtualHost> nameBasedMapping = requireNonNull(mapping.get(-1));
         return nameBasedMapping.map(hostname);
     }

439-445: ⚠️ Potential issue | 🟡 Minor

Same volatile read issue in deprecated findVirtualHost(String).

This method also reads virtualHostAndPortMapping twice without a local snapshot (lines 440 and 443). Apply the same local-variable pattern for consistency.

Proposed fix
     `@Override`
     `@Deprecated`
     public VirtualHost findVirtualHost(String hostname) {
-        if (virtualHostAndPortMapping == null) {
+        final Int2ObjectMap<Mapping<String, VirtualHost>> mapping = virtualHostAndPortMapping;
+        if (mapping == null) {
             return defaultVirtualHost;
         }
-        final Mapping<String, VirtualHost> virtualHostMapping = virtualHostAndPortMapping.get(-1);
+        final Mapping<String, VirtualHost> virtualHostMapping = mapping.get(-1);
         return virtualHostMapping.map(hostname);
     }
🧹 Nitpick comments (1)
core/src/test/java/com/linecorp/armeria/server/PortBasedVirtualHostTest.java (1)

241-293: Consider using ServerPort.actualPort() directly for clarity.

The serverPortBasedVirtualHostRoutesCorrectly and multipleRandomPortVirtualHosts tests access port1.actualPort() directly, which is cleaner than sorting activePorts(). This test could be simplified similarly, though it still works correctly as-is.

Comment thread core/src/main/java/com/linecorp/armeria/server/VirtualHost.java
- Restore two-pass approach in buildDomainAndPortMapping() to collect
  per-port default VirtualHosts before building DomainMappingBuilder,
  fixing order-dependent bug where computeIfAbsent ignored the correct
  port-specific default when a named VirtualHost was processed first
- Fix compilation error in RoutersBenchmark caused by missing
  TlsEngineType parameter in VirtualHost constructor
- Add shouldFallbackToDefaultPortVirtualHost test
- Capture virtualHostAndPortMapping into a local variable before use
  in findVirtualHost() to prevent inconsistent reads if the field is
  replaced by rebuildDomainAndPortMapping() between accesses
Comment thread core/src/main/java/com/linecorp/armeria/server/ServerPort.java
Copy link
Copy Markdown
Contributor

@ikhoon ikhoon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks nice! @junjunclub 👍👍

Comment thread core/src/main/java/com/linecorp/armeria/server/ServerBuilder.java Outdated
@ikhoon ikhoon added this to the 1.38.0 milestone Mar 4, 2026
Comment thread core/src/main/java/com/linecorp/armeria/server/ServerBuilder.java Outdated
Copy link
Copy Markdown
Contributor

@minwoox minwoox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot, @junjunclub!

@ikhoon ikhoon merged commit bd549bb into line:main Apr 3, 2026
16 of 19 checks passed
@injae-kim
Copy link
Copy Markdown
Contributor

🎉 🎉 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Armeria per-port VirtualHost and random port are incompatible

5 participants