package main import ( "crypto/rand" "flag" "fmt" "log" "net/http" "os" "time" "p83.nl/go/websub-hub/cmd/hubserver/storage" ) func init() { log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) } const challengeBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" // randStringBytes is the hub's challenge. It comes from crypto/rand: a // challenge a subscriber has to echo is a secret, and math/rand makes it // predictable for anyone who observes a few of them. func randStringBytes(n int) string { buf := make([]byte, n) if _, err := rand.Read(buf); err != nil { log.Fatalf("could not read random bytes: %v", err) } out := make([]byte, n) for i, b := range buf { out[i] = challengeBytes[int(b)%len(challengeBytes)] } return string(out) } type Stat struct { Updates int LastUpdate time.Time } func main() { hostPort := flag.String("http", ":80", "host and port to listen on") baseURL := flag.String("baseurl", "", "baseurl that the server should response with") database := flag.String("database", "localhost:9999", "database host:port") dbUser := flag.String("database-user", envOr("HUB_DB_USER", "postgres"), "database user") dbPassword := flag.String("database-password", envOr("HUB_DB_PASSWORD", "simple"), "database password") flag.Parse() log.Printf("Using arguments http=%s baseurl=%s database=%s user=%s", *hostPort, *baseURL, *database, *dbUser) if os.Getenv("HUB_DB_PASSWORD") == "" { log.Printf("warning: HUB_DB_PASSWORD is unset, using the built-in default; set it in the deployment") } dsn := fmt.Sprintf("postgres://%s:%s@%s/?sslmode=disable", *dbUser, *dbPassword, *database) store, err := storage.New(dsn) if err != nil { log.Fatal(err) } defer store.Close() handler := &subscriptionHandler{ store: store, baseURL: *baseURL, // One client with a timeout: a topic or callback that hangs must not // hold the hub forever. client: &http.Client{Timeout: 30 * time.Second}, } http.Handle("/", handler) log.Fatal(http.ListenAndServe(*hostPort, handler)) } func envOr(key, fallback string) string { if v := os.Getenv(key); v != "" { return v } return fallback }