feat(route): add bind address support for TCP/UDP routes

- Introduced a new `Bind` field in the route configuration to specify the address to listen on for TCP and UDP routes.
- Defaulted the bind address to "0.0.0.0" if not provided.
- Enhanced validation to ensure the bind address is a valid IP.
- Updated stream initialization to use the correct network type (tcp4/tcp6 or udp4/udp6) based on the bind address.
- Refactored stream creation functions to accept the network type as a parameter.
This commit is contained in:
yusing
2026-01-07 15:05:55 +08:00
parent 9205af3a4f
commit 25ceb512b4
6 changed files with 66 additions and 21 deletions

View File

@@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"net"
"net/url"
"os"
"reflect"
@@ -47,6 +48,9 @@ type (
Host string `json:"host,omitempty"`
Port route.Port `json:"port"`
// for TCP and UDP routes, bind address to listen on
Bind string `json:"bind,omitempty" validate:"omitempty,ip_addr" extensions:"x-nullable"`
Root string `json:"root,omitempty"`
SPA bool `json:"spa,omitempty"` // Single-page app mode: serves index for non-existent paths
Index string `json:"index,omitempty"` // Index file to serve for single-page app mode
@@ -278,7 +282,28 @@ func (r *Route) validate() gperr.Error {
r.ProxyURL = gperr.Collect(&errs, nettypes.ParseURL, fmt.Sprintf("%s://%s:%d", r.Scheme, r.Host, r.Port.Proxy))
case route.SchemeTCP, route.SchemeUDP:
if !r.ShouldExclude() {
r.LisURL = gperr.Collect(&errs, nettypes.ParseURL, fmt.Sprintf("%s://:%d", r.Scheme, r.Port.Listening))
if r.Bind == "" {
r.Bind = "0.0.0.0"
}
bindIP := net.ParseIP(r.Bind)
if bindIP == nil {
return gperr.Errorf("invalid bind address %s", r.Bind)
}
var scheme string
if bindIP.To4() == nil { // IPv6
if r.Scheme == route.SchemeTCP {
scheme = "tcp6"
} else {
scheme = "udp6"
}
} else {
if r.Scheme == route.SchemeTCP {
scheme = "tcp4"
} else {
scheme = "udp4"
}
}
r.LisURL = gperr.Collect(&errs, nettypes.ParseURL, fmt.Sprintf("%s://%s:%d", scheme, r.Bind, r.Port.Listening))
}
r.ProxyURL = gperr.Collect(&errs, nettypes.ParseURL, fmt.Sprintf("%s://%s:%d", r.Scheme, r.Host, r.Port.Proxy))
}