refactor: modify Listen method to receive metadata via functional options
MyungSub0519 committed
Nov 12, 2025 at 23:25 UTC
5afb3cac08ee30ab8eb5913666bcf0557881b2e8
3 files changed
+40
-20
cmd/demo-app/main.go
+2
-8
@@ -186,15 +186,9 @@ func runPaint() error {
186
return fmt.Errorf("new client: %w", err)
187
}
188
defer client.Close()
189
-
189
+
190
// 3) Register lease and obtain a net.Listener that accepts relayed connections
191
- metadata := &sdk.Metadata{
192
- Description: "Portal demo paint app",
193
- Tags: []string{"demo", "paint"},
194
- Owner: "PortalApp Developer",
195
- Country: "KR",
196
- }
197
- listener, err := client.Listen(cred, flagName, []string{"http/1.1"}, metadata)
191
+ listener, err := client.Listen(cred, flagName, []string{"http/1.1"}, sdk.WithDescription("Portal demo paint app"), sdk.WithTags([]string{"demo", "paint"}), sdk.WithOwner("PortalApp Developer"), sdk.WithCountry("KR"))
192
if err != nil {
193
return fmt.Errorf("listen: %w", err)
194
}
sdk/sdk.go
+36
-10
@@ -2,7 +2,6 @@ package sdk
2
3
import (
4
"context"
5
- "encoding/json"
5
"errors"
6
"fmt"
7
"io"
@@ -177,6 +176,38 @@ type Metadata struct {
176
Country string `json:"country"`
177
}
178
179
+type MetadataOption func(*Metadata)
180
+
181
+func WithDescription(description string) MetadataOption {
182
+ return func(m *Metadata) {
183
+ m.Description = description
184
+ }
185
+}
186
+
187
+func WithTags(tags []string) MetadataOption {
188
+ return func(m *Metadata) {
189
+ m.Tags = tags
190
+ }
191
+}
192
+
193
+func WithThumbnail(thumbnail string) MetadataOption {
194
+ return func(m *Metadata) {
195
+ m.Thumbnail = thumbnail
196
+ }
197
+}
198
+
199
+func WithOwner(owner string) MetadataOption {
200
+ return func(m *Metadata) {
201
+ m.Owner = owner
202
+ }
203
+}
204
+
205
+func WithCountry(country string) MetadataOption {
206
+ return func(m *Metadata) {
207
+ m.Country = country
208
+ }
209
+}
210
+
211
type RDClient struct {
212
mu sync.Mutex
213
@@ -316,12 +347,11 @@ func (g *RDClient) Dial(cred *cryptoops.Credential, leaseID string, alpn string)
347
return nil, ErrNoAvailableRelay
348
}
349
319
-func (g *RDClient) Listen(cred *cryptoops.Credential, name string, alpns []string, metadata *Metadata) (*RDListener, error) {
350
+func (g *RDClient) Listen(cred *cryptoops.Credential, name string, alpns []string, options ...MetadataOption) (*RDListener, error) {
351
log.Debug().
352
Str("lease_id", cred.ID()).
353
Str("name", name).
354
Strs("alpns", alpns).
324
- Bool("has_metadata", metadata != nil).
355
Msg("[SDK] Creating listener")
356
357
// Validate name is URL-safe
@@ -334,13 +364,9 @@ func (g *RDClient) Listen(cred *cryptoops.Credential, name string, alpns []strin
364
365
metadataValue := ""
366
337
- if metadata != nil {
338
- metadataJSON, err := json.Marshal(metadata)
339
- if err != nil {
340
- log.Error().Err(err).Msg("[SDK] Failed to marshal metadata")
341
- return nil, ErrInvalidMetadata
342
- }
343
- metadataValue = string(metadataJSON)
367
+ for _, option := range options {
368
+ metadata := &Metadata{}
369
+ option(metadata)
370
}
371
372
g.mu.Lock()
sdk/sdk_e2e_test.go
+2
-2
@@ -102,7 +102,7 @@ func TestE2E_ClientToAppThroughRelay(t *testing.T) {
102
103
// 5. Register listener on app side
104
log.Info().Msg("[TEST] Step 5: Registering app listener")
105
- appListener, err := appClient.Listen(appCred, "test-app", []string{"http/1.1"}, nil)
105
+ appListener, err := appClient.Listen(appCred, "test-app", []string{"http/1.1"})
106
if err != nil {
107
t.Fatalf("Failed to create app listener: %v", err)
108
}
@@ -276,7 +276,7 @@ func TestE2E_MultipleConnections(t *testing.T) {
276
}
277
defer appClient.Close()
278
279
- appListener, err := appClient.Listen(appCred, "multi-test-app", []string{"http/1.1"}, nil)
279
+ appListener, err := appClient.Listen(appCred, "multi-test-app", []string{"http/1.1"})
280
if err != nil {
281
t.Fatalf("Failed to create app listener: %v", err)
282
}