-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
137 lines (108 loc) · 3.06 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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package web
import (
"fmt"
"net"
"net/http"
"path"
)
type Options struct {
Listen string `long:"http-listen" value-name:"[HOST]:PORT | /PATH" default:":8284"`
Static string `long:"http-static" value-name:"PATH"`
StaticCacheControl string `long:"http-static-cache-control" value-name:"HEADER-VALUE" default:"no-cache"`
}
type Route struct {
Pattern string
Handler http.Handler
}
type CacheFilter struct {
Handler http.Handler
CacheControl string
}
func (cacheFilter CacheFilter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Cache-Control", cacheFilter.CacheControl)
cacheFilter.Handler.ServeHTTP(w, r)
}
func RoutePrefix(prefix string, handler http.Handler) Route {
return Route{
Pattern: prefix,
Handler: http.StripPrefix(prefix, handler),
}
}
// Return a route that services the tree relative to --http-static=
func (options Options) Route(prefix string, handler http.Handler) Route {
return Route{
Pattern: prefix,
Handler: http.StripPrefix(prefix, handler),
}
}
// Return a route that services the tree relative to --http-static=
func (options Options) RouteStatic(prefix string) Route {
var route = Route{Pattern: prefix}
var handler http.Handler
if options.Static != "" {
log.Infof("Serve %v from %v", prefix, options.Static)
handler = http.FileServer(http.Dir(options.Static))
if options.StaticCacheControl != "" {
handler = CacheFilter{handler, options.StaticCacheControl}
}
route.Handler = http.StripPrefix(prefix, handler)
}
return route
}
// Return a route that serves a named static file, relative to --http-static=
func (options Options) RouteFile(url string, file string) Route {
file = path.Join(options.Static, file)
return Route{
Pattern: url,
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != url {
w.WriteHeader(404)
} else {
http.ServeFile(w, r, file)
}
}),
}
}
func (options Options) RouteAPI(prefix string, api API) Route {
return Route{
Pattern: prefix,
Handler: http.StripPrefix(prefix, api),
}
}
func (options Options) RouteEvents(url string, events Events) Route {
return Route{
Pattern: url,
Handler: events,
}
}
func (options Options) Server(routes ...Route) error {
var serveMux = http.NewServeMux()
for _, route := range routes {
if route.Handler == nil {
continue
}
serveMux.Handle(route.Pattern, route.Handler)
}
if options.Listen == "" {
} else if options.Listen[0] == '/' || options.Listen[0] == '.' {
var server = http.Server{
Handler: serveMux,
}
log.Infof("Listen on unix:%v...", options.Listen)
if listener, err := net.Listen("unix", options.Listen); err != nil {
return err
} else if err := server.Serve(listener); err != nil {
return fmt.Errorf("Server %v: %v", options.Listen, err)
}
} else {
var server = http.Server{
Addr: options.Listen,
Handler: serveMux,
}
log.Infof("Listen on %v...", options.Listen)
if err := server.ListenAndServe(); err != nil {
return fmt.Errorf("ListenAndServe %v: %v", options.Listen, err)
}
}
return nil
}