/
main.go
97 lines (82 loc) · 1.81 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package main
import "fmt"
import "net/http"
import "net/url"
import "os"
import "github.com/fzzbt/radix/redis"
func searchEnv(list []string) string {
for _, x := range list {
s := os.Getenv(x)
if len(s) > 0 {
return s
}
}
return ""
}
func redisUrl() url.URL {
s := searchEnv([]string{"REDIS_URL", "REDISTOGO_URL", "OPENREDIS_URL", "MYREDIS_URL", "REDISGREEN_URL", "REDISCLOUD_URL"})
if s == "" {
s = "redis://localhost:6379"
}
u, err := url.Parse(s)
if err != nil {
fmt.Fprintln(os.Stderr, "error:", err)
os.Exit(1)
}
return *u
}
// TODO support domain sockets
func redisConf() redis.Config {
u := redisUrl()
conf := redis.DefaultConfig()
conf.Network = "tcp"
conf.Address = u.Host
if u.User != nil {
pass, set := u.User.Password()
if set {
conf.Password = pass
}
}
return conf
}
func main() {
c := redis.NewClient(redisConf())
defer c.Close()
h := func(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" {
// TODO return error if these are not set
// TODO do we need a mutex here?
c.Publish(r.FormValue("channel"), r.FormValue("data"))
}
if r.Method == "GET" {
// spawn a new client since we'll be modifing pubsub behavior
c := redis.NewClient(redisConf())
defer c.Close()
// TODO allow channel size to be configurable
lines := make(chan string)
h := func(msg *redis.Message) {
switch msg.Type {
case redis.MessageMessage:
lines <- msg.Payload
}
}
sub, err := c.Subscription(h)
if err != nil {
panic(err)
}
defer sub.Close()
sub.Subscribe(r.FormValue("channel"))
for l := range lines {
fmt.Fprintf(w, "%s\n", l)
if f, ok := w.(http.Flusher); ok {
f.Flush()
}
}
}
}
http.HandleFunc("/", h)
err := http.ListenAndServe(":"+os.Getenv("PORT"), nil)
if err != nil {
panic(err)
}
}