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