cmd: move project names

Kim committed Oct 28, 2025 at 13:20 UTC 905cb7eda8c77c31f01f644ec4e8ea603945359d
6 files changed +90 -8
Dockerfile
+1 -1
@@ -10,7 +10,7 @@ RUN --mount=type=cache,target=/go/pkg/mod \
10 COPY . .
11 RUN --mount=type=cache,target=/go/pkg/mod \
12 CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
13 - go build -trimpath -ldflags "-s -w" -o /out/relayserver ./cmd/server
13 + go build -trimpath -ldflags "-s -w" -o /out/relayserver ./cmd/relay-server
14
15 # Minimal runtime image
16 FROM gcr.io/distroless/static-debian12:nonroot
cmd/demo-app/main.go renamed
+1 -5
@@ -30,7 +30,7 @@ var rootCmd = &cobra.Command{
30 func init() {
31 flags := rootCmd.PersistentFlags()
32 flags.StringArrayVar(&flagBootstraps, "bootstrap", []string{"ws://127.0.0.1:4017/relay"}, "bootstrap websocket url (repeatable), e.g. ws://127.0.0.1:4017/relay")
33 - flags.StringVar(&flagName, "name", "demo", "lease name to display on server UI")
33 + flags.StringVar(&flagName, "name", "demo-app", "lease name to display on server UI")
34 flags.StringArrayVar(&flagALPNs, "alpn", []string{"h1"}, "ALPN identifier for this service")
35 flags.IntVar(&flagAdminPort, "admin-port", 0, "optional admin UI port (0 to disable)")
36 }
@@ -42,10 +42,6 @@ func main() {
42 }
43
44 func runClient(cmd *cobra.Command, args []string) error {
45 - if len(flagBootstraps) == 0 {
46 - return fmt.Errorf("no bootstrap servers provided; use --bootstrap ws://host:port/relay")
47 - }
48 -
45 // Ctrl-C / SIGTERM handling
46 ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
47 defer stop()
cmd/demo-app/view.go renamed
cmd/relay-server/main.go renamed
cmd/relay-server/view.go renamed
+86
@@ -5,7 +5,12 @@ import (
5 "encoding/json"
6 "fmt"
7 "html/template"
8 + "net"
9 "net/http"
10 + "net/http/httputil"
11 + "net/url"
12 + "strings"
13 + "sync"
14 "time"
15
16 "github.com/gorilla/websocket"
@@ -13,6 +18,7 @@ import (
18
19 "github.com/gosuda/relaydns/relaydns"
20 "github.com/gosuda/relaydns/relaydns/utils/wsstream"
21 + "github.com/gosuda/relaydns/sdk"
22 )
23
24 type leaseRow struct {
@@ -122,6 +128,86 @@ func serveHTTP(ctx context.Context, addr string, serv *relaydns.RelayServer, nod
128
129 mux := http.NewServeMux()
130
131 + // Per-peer HTTP reverse proxy over RelayDNS
132 + // Route: /peer/{leaseID}/*
133 + var (
134 + proxyClient *sdk.RDClient
135 + proxyClientOnce sync.Once
136 + proxyClientErr error
137 + )
138 + // Lazily initialize a client that connects to provided bootstraps or the current server
139 + initProxyClient := func(r *http.Request) (*sdk.RDClient, error) {
140 + proxyClientOnce.Do(func() {
141 + bs := bootstraps
142 + if len(bs) == 0 {
143 + // Derive bootstrap from current request host
144 + // Assume same host/port as admin with path /relay
145 + scheme := "ws"
146 + // No TLS handling here; extend to wss if needed in future
147 + bs = []string{fmt.Sprintf("%s://%s/relay", scheme, r.Host)}
148 + }
149 + proxyClient, proxyClientErr = sdk.NewClient(func(c *sdk.RDClientConfig) {
150 + c.BootstrapServers = bs
151 + })
152 + })
153 + return proxyClient, proxyClientErr
154 + }
155 +
156 + mux.HandleFunc("/peer/", func(w http.ResponseWriter, r *http.Request) {
157 + // Expect path /peer/{leaseID}[/{rest}]
158 + path := strings.TrimPrefix(r.URL.Path, "/peer/")
159 + if path == "" {
160 + http.NotFound(w, r)
161 + return
162 + }
163 + // Split leaseID and remainder
164 + var leaseID, rest string
165 + slash := strings.IndexByte(path, '/')
166 + if slash == -1 {
167 + leaseID, rest = path, "/"
168 + } else {
169 + leaseID, rest = path[:slash], path[slash:]
170 + if rest == "" {
171 + rest = "/"
172 + }
173 + }
174 +
175 + client, err := initProxyClient(r)
176 + if err != nil {
177 + http.Error(w, "proxy init failed", http.StatusBadGateway)
178 + log.Error().Err(err).Msg("[server] init proxy client")
179 + return
180 + }
181 +
182 + // Create a reverse proxy whose transport dials via RelayDNS to the lease
183 + target, _ := url.Parse("http://relay-peer")
184 + proxy := httputil.NewSingleHostReverseProxy(target)
185 + proxy.Director = func(req *http.Request) {
186 + // Preserve original method, headers, query; rewrite URL to dummy host
187 + req.URL.Scheme = "http"
188 + req.URL.Host = target.Host
189 + req.URL.Path = rest
190 + // Keep Host header as-is (or could clear)
191 + }
192 + proxy.Transport = &http.Transport{
193 + DialContext: func(c context.Context, network, address string) (net.Conn, error) {
194 + // Create a fresh credential per dial
195 + cred, cerr := sdk.NewCredential()
196 + if cerr != nil {
197 + return nil, cerr
198 + }
199 + return client.Dial(cred, leaseID, "h1")
200 + },
201 + }
202 +
203 + proxy.ErrorHandler = func(rw http.ResponseWriter, req *http.Request, e error) {
204 + log.Error().Err(e).Str("lease", leaseID).Msg("[server] proxy error")
205 + http.Error(rw, "upstream error", http.StatusBadGateway)
206 + }
207 +
208 + proxy.ServeHTTP(w, r)
209 + })
210 +
211 mux.HandleFunc("/relay", func(w http.ResponseWriter, r *http.Request) {
212 if r.Method != http.MethodGet {
213 w.Header().Set("Allow", http.MethodGet)
docker-compose.yml
+2 -2
@@ -5,7 +5,7 @@ services:
5 dockerfile: Dockerfile
6 command:
7 - "--http-port"
8 - - "19080"
8 + - "4017"
9 ports:
10 - - "19080:19080"
10 + - "4017:4017"
11 restart: unless-stopped