Skip to content

Commit 9ed1daa

Browse files
authored
Merge pull request #1685 from dgageot/fix-1679
Fix A2A agent card advertising unroutable wildcard address
2 parents 4284053 + ee47fa0 commit 9ed1daa

File tree

3 files changed

+48
-2
lines changed

3 files changed

+48
-2
lines changed

pkg/a2a/server.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,19 @@ import (
2323
"github.com/docker/cagent/pkg/version"
2424
)
2525

26+
// routableAddr replaces wildcard listen addresses (like "0.0.0.0" or "::") with
27+
// "localhost" so the agent card URL is actually usable by clients.
28+
func routableAddr(addr string) string {
29+
host, port, err := net.SplitHostPort(addr)
30+
if err != nil {
31+
return addr
32+
}
33+
if host == "" || host == "0.0.0.0" || host == "::" {
34+
return net.JoinHostPort("localhost", port)
35+
}
36+
return addr
37+
}
38+
2639
func Run(ctx context.Context, agentFilename, agentName string, runConfig *config.RuntimeConfig, ln net.Listener) error {
2740
slog.Debug("Starting A2A server", "agent", agentName, "addr", ln.Addr().String())
2841

@@ -46,7 +59,7 @@ func Run(ctx context.Context, agentFilename, agentName string, runConfig *config
4659
return fmt.Errorf("failed to create ADK agent adapter: %w", err)
4760
}
4861

49-
baseURL := &url.URL{Scheme: "http", Host: ln.Addr().String()}
62+
baseURL := &url.URL{Scheme: "http", Host: routableAddr(ln.Addr().String())}
5063

5164
slog.Debug("A2A server listening", "url", baseURL.String())
5265

pkg/a2a/server_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package a2a
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
)
8+
9+
func TestRoutableAddr(t *testing.T) {
10+
t.Parallel()
11+
12+
tests := []struct {
13+
name string
14+
addr string
15+
want string
16+
}{
17+
{"ipv6 wildcard", "[::]:8080", "localhost:8080"},
18+
{"ipv4 wildcard", "0.0.0.0:8080", "localhost:8080"},
19+
{"empty host", ":8080", "localhost:8080"},
20+
{"localhost stays", "localhost:8080", "localhost:8080"},
21+
{"ipv4 loopback stays", "127.0.0.1:8080", "127.0.0.1:8080"},
22+
{"specific ip stays", "192.168.1.1:9090", "192.168.1.1:9090"},
23+
{"hostname stays", "my-host:8080", "my-host:8080"},
24+
{"invalid addr returned as-is", "not-a-host-port", "not-a-host-port"},
25+
}
26+
27+
for _, tt := range tests {
28+
t.Run(tt.name, func(t *testing.T) {
29+
t.Parallel()
30+
assert.Equal(t, tt.want, routableAddr(tt.addr))
31+
})
32+
}
33+
}

pkg/server/listen.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,5 @@ func listenUnix(ctx context.Context, path string) (net.Listener, error) {
3636

3737
func listenTCP(ctx context.Context, addr string) (net.Listener, error) {
3838
var lc net.ListenConfig
39-
return lc.Listen(ctx, "tcp", addr)
39+
return lc.Listen(ctx, "tcp4", addr)
4040
}

0 commit comments

Comments
 (0)