Skip to content

Commit

Permalink
feat: add ToToml() to all configs
Browse files Browse the repository at this point in the history
  • Loading branch information
palkan committed Oct 8, 2024
1 parent 11f5d6b commit 70d62fa
Show file tree
Hide file tree
Showing 35 changed files with 1,325 additions and 104 deletions.
47 changes: 42 additions & 5 deletions broadcast/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,18 @@ const (
// HTTPConfig contains HTTP pubsub adapter configuration
type HTTPConfig struct {
// Port to listen on
Port int
Port int `toml:"port"`
// Path for HTTP broadast
Path string
Path string `toml:"path"`
// Secret token to authorize requests
Secret string
Secret string `toml:"secret"`
// SecretBase is a secret used to generate a token if none provided
SecretBase string
// AddCORSHeaders enables adding CORS headers (so you can perform broadcast requests from the browser)
// (We mostly need it for Stackblitz)
AddCORSHeaders bool
AddCORSHeaders bool `toml:"cors_headers"`
// CORSHosts contains a list of hostnames for CORS (comma-separated)
CORSHosts string
CORSHosts string `toml:"cors_hosts"`
}

// NewHTTPConfig builds a new config for HTTP pub/sub
Expand All @@ -47,6 +47,43 @@ func (c *HTTPConfig) IsSecured() bool {
return c.Secret != "" || c.SecretBase != ""
}

func (c HTTPConfig) ToToml() string {
var result strings.Builder

result.WriteString("# HTTP server port (can be the same as the main server port)\n")
result.WriteString(fmt.Sprintf("port = %d\n", c.Port))

result.WriteString("# HTTP endpoint path for broadcasts\n")
result.WriteString(fmt.Sprintf("path = \"%s\"\n", c.Path))

result.WriteString("# Secret token to authenticate broadcasting requests\n")
if c.Secret != "" {
result.WriteString(fmt.Sprintf("secret = \"%s\"\n", c.Secret))
} else {
result.WriteString("# secret = \"\"\n")
}

result.WriteString("# Enable CORS headers\n")
if c.AddCORSHeaders {
result.WriteString("cors_headers = true\n")

result.WriteString("# Allowed hosts for CORS (comma-separated)\n")
if c.CORSHosts != "" {
result.WriteString(fmt.Sprintf("cors_hosts = \"%s\"\n", c.CORSHosts))
} else {
result.WriteString("# cors_hosts = \"\"\n")
}
} else {
result.WriteString("# cors_headers = false\n")
result.WriteString("# Allowed hosts for CORS (comma-separated)\n")
result.WriteString("# cors_hosts = \"\"\n")
}

result.WriteString("\n")

return result.String()
}

// HTTPBroadcaster represents HTTP broadcaster
type HTTPBroadcaster struct {
port int
Expand Down
26 changes: 26 additions & 0 deletions broadcast/http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"strings"
"testing"

"github.com/BurntSushi/toml"
"github.com/anycable/anycable-go/mocks"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -89,3 +90,28 @@ func TestHttpHandler(t *testing.T) {
assert.Equal(t, http.StatusCreated, rr.Code)
})
}

func TestHTTPConfig__ToToml(t *testing.T) {
conf := NewHTTPConfig()
conf.Port = 8080
conf.Path = "/broadcast"
conf.Secret = ""
conf.AddCORSHeaders = true
conf.CORSHosts = "example.com,test.com"

tomlStr := conf.ToToml()

assert.Contains(t, tomlStr, "port = 8080")
assert.Contains(t, tomlStr, "path = \"/broadcast\"")
assert.Contains(t, tomlStr, "# secret = \"\"")
assert.Contains(t, tomlStr, "cors_headers = true")
assert.Contains(t, tomlStr, "cors_hosts = \"example.com,test.com\"")

// Round-trip test
conf2 := NewHTTPConfig()

_, err := toml.Decode(tomlStr, &conf2)
require.NoError(t, err)

assert.Equal(t, conf, conf2)
}
37 changes: 33 additions & 4 deletions broker/config.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
package broker

import (
"fmt"
"strings"
)

type Config struct {
// Adapter name
Adapter string
Adapter string `toml:"adapter"`
// For how long to keep history in seconds
HistoryTTL int64
HistoryTTL int64 `toml:"history_ttl"`
// Max size of messages to keep in the history per stream
HistoryLimit int
HistoryLimit int `toml:"history_limit"`
// Sessions cache TTL in seconds (after disconnect)
SessionsTTL int64
SessionsTTL int64 `toml:"sessions_ttl"`
}

func NewConfig() Config {
Expand All @@ -21,3 +26,27 @@ func NewConfig() Config {
SessionsTTL: 5 * 60,
}
}

func (c Config) ToToml() string {
var result strings.Builder

result.WriteString("# Broker backend adapter\n")
if c.Adapter == "" {
result.WriteString("# adapter = \"memory\"\n")
} else {
result.WriteString(fmt.Sprintf("adapter = \"%s\"\n", c.Adapter))
}

result.WriteString("# For how long to keep streams history (seconds)\n")
result.WriteString(fmt.Sprintf("history_ttl = %d\n", c.HistoryTTL))

result.WriteString("# Max number of messages to keep in a stream history\n")
result.WriteString(fmt.Sprintf("history_limit = %d\n", c.HistoryLimit))

result.WriteString("# For how long to store sessions state for resumeability (seconds)\n")
result.WriteString(fmt.Sprintf("sessions_ttl = %d\n", c.SessionsTTL))

result.WriteString("\n")

return result.String()
}
50 changes: 50 additions & 0 deletions broker/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package broker

import (
"testing"

"github.com/BurntSushi/toml"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestConfig__DecodeToml(t *testing.T) {
tomlString := `
adapter = "nats"
history_ttl = 100
history_limit = 1000
sessions_ttl = 600
`

conf := NewConfig()
_, err := toml.Decode(tomlString, &conf)
require.NoError(t, err)

assert.Equal(t, "nats", conf.Adapter)
assert.Equal(t, int64(100), conf.HistoryTTL)
assert.Equal(t, 1000, conf.HistoryLimit)
assert.Equal(t, int64(600), conf.SessionsTTL)
}

func TestConfig__ToToml(t *testing.T) {
conf := NewConfig()
conf.Adapter = "nats"
conf.HistoryTTL = 100
conf.HistoryLimit = 1000
conf.SessionsTTL = 600

tomlStr := conf.ToToml()

assert.Contains(t, tomlStr, "adapter = \"nats\"")
assert.Contains(t, tomlStr, "history_ttl = 100")
assert.Contains(t, tomlStr, "history_limit = 1000")
assert.Contains(t, tomlStr, "sessions_ttl = 600")

// Round-trip test
conf2 := Config{}

_, err := toml.Decode(tomlStr, &conf2)
require.NoError(t, err)

assert.Equal(t, conf, conf2)
}
2 changes: 1 addition & 1 deletion cli/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ Use broadcast_key instead.`)
}

if shouldPrintConfig {
fmt.Print(c.Display())
fmt.Print(c.ToToml())
return &c, nil, true
}

Expand Down
47 changes: 46 additions & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func (c *Config) LoadFromFile() error {
return nil
}

func (c Config) Display() string {
func (c Config) ToToml() string {
var result strings.Builder

result.WriteString("# AnyCable server configuration.\n# Read more at https://docs.anycable.io/anycable-go/configuration\n\n")
Expand Down Expand Up @@ -168,5 +168,50 @@ func (c Config) Display() string {
result.WriteString(fmt.Sprintf("presets = [\"%s\"]\n\n", strings.Join(c.UserPresets, "\", \"")))
}

result.WriteString("# Server configuration\n[server]\n")
result.WriteString(c.Server.ToToml())

result.WriteString("# Logging configuration\n[logging]\n")
result.WriteString(c.Log.ToToml())

result.WriteString("# RPC configuration\n[rpc]\n")
result.WriteString(c.RPC.ToToml())

result.WriteString("# Broker configuration\n[broker]\n")
result.WriteString(c.Broker.ToToml())

result.WriteString("# JWT configuration\n[jwt]\n")
result.WriteString(c.JWT.ToToml())

result.WriteString("# Pub/sub (signed) streams configuration\n[streams]\n")
result.WriteString(c.Streams.ToToml())

result.WriteString("# WebSockets configuration\n[ws]\n")
result.WriteString(c.WS.ToToml())

result.WriteString("# SSE configuration\n[sse]\n")
result.WriteString(c.SSE.ToToml())

result.WriteString("# Redis configuration\n[redis]\n")
result.WriteString(c.Redis.ToToml())

result.WriteString("# NATS configuration\n[nats]\n")
result.WriteString(c.NATS.ToToml())

result.WriteString("# Broadcasting configuration\n[http_broadcast]\n")
result.WriteString(c.HTTPBroadcast.ToToml())

result.WriteString("# Metrics configuration\n[metrics]\n")
result.WriteString(c.Metrics.ToToml())

result.WriteString("# App configuration\n[app]\n")
result.WriteString(c.App.ToToml())

result.WriteString("# Disconnector configuration\n[disconnector]\n")
result.WriteString(c.DisconnectQueue.ToToml())

result.WriteString("# Embedded NATS configuration\n[embedded_nats]\n")
result.WriteString(c.EmbeddedNats.ToToml())

return result.String()
}
Loading

0 comments on commit 70d62fa

Please sign in to comment.