@@ -20,7 +20,6 @@ import (
20
20
"os"
21
21
"strconv"
22
22
"strings"
23
- "sync"
24
23
"sync/atomic"
25
24
"time"
26
25
@@ -37,11 +36,6 @@ func init() {
37
36
os .Stderr .WriteString ("devapp generates the dashboard that powers dev.golang.org.\n " )
38
37
flag .PrintDefaults ()
39
38
}
40
-
41
- // TODO don't bind relative to a working directory.
42
- http .Handle ("/" , http .FileServer (http .Dir ("./static/" )))
43
- http .HandleFunc ("/favicon.ico" , faviconHandler )
44
- http .Handle ("/release" , hstsHandler (func (w http.ResponseWriter , r * http.Request ) { servePage (w , r , "release" ) }))
45
39
}
46
40
47
41
func main () {
@@ -50,11 +44,14 @@ func main() {
50
44
devTLSPort = flag .Int ("dev-tls-port" , 0 , "if non-zero, port number to run localhost self-signed TLS server" )
51
45
autocertBucket = flag .String ("autocert-bucket" , "" , "if non-empty, listen on port 443 and serve a LetsEncrypt TLS cert using this Google Cloud Storage bucket as a cache" )
52
46
updateInterval = flag .Duration ("update-interval" , 5 * time .Minute , "how often to update the dashboard data" )
47
+ staticDir = flag .String ("static-dir" , "./static/" , "location of static directory relative to binary location" )
53
48
)
54
49
flag .Parse ()
55
50
56
51
go updateLoop (* updateInterval )
57
52
53
+ s := newServer (http .NewServeMux (), * staticDir )
54
+
58
55
ln , err := net .Listen ("tcp" , * listen )
59
56
if err != nil {
60
57
log .Fatalf ("Error listening on %s: %v\n " , * listen , err )
@@ -63,13 +60,19 @@ func main() {
63
60
64
61
errc := make (chan error )
65
62
if ln != nil {
66
- go func () { errc <- fmt .Errorf ("http.Serve = %v" , http .Serve (ln , nil )) }()
63
+ go func () {
64
+ handler := http .Handler (s )
65
+ if * autocertBucket != "" {
66
+ handler = http .HandlerFunc (redirectHTTP )
67
+ }
68
+ errc <- fmt .Errorf ("http.Serve = %v" , http .Serve (ln , handler ))
69
+ }()
67
70
}
68
71
if * autocertBucket != "" {
69
- go func () { errc <- serveAutocertTLS (* autocertBucket ) }()
72
+ go func () { errc <- serveAutocertTLS (s , * autocertBucket ) }()
70
73
}
71
74
if * devTLSPort != 0 {
72
- go func () { errc <- serveDevTLS (* devTLSPort ) }()
75
+ go func () { errc <- serveDevTLS (s , * devTLSPort ) }()
73
76
}
74
77
75
78
log .Fatal (<- errc )
@@ -85,15 +88,23 @@ func updateLoop(interval time.Duration) {
85
88
}
86
89
}
87
90
88
- func serveDevTLS (port int ) error {
91
+ func redirectHTTP (w http.ResponseWriter , r * http.Request ) {
92
+ if r .TLS != nil || r .Host == "" {
93
+ http .NotFound (w , r )
94
+ return
95
+ }
96
+ http .Redirect (w , r , "https://" + r .Host + r .RequestURI , http .StatusFound )
97
+ }
98
+
99
+ func serveDevTLS (h http.Handler , port int ) error {
89
100
ln , err := net .Listen ("tcp" , "localhost:" + strconv .Itoa (port ))
90
101
if err != nil {
91
102
return err
92
103
}
93
104
defer ln .Close ()
94
105
log .Printf ("Serving self-signed TLS at https://%s" , ln .Addr ())
95
106
// Abuse httptest for its localhost TLS setup code:
96
- ts := httptest .NewUnstartedServer (http . DefaultServeMux )
107
+ ts := httptest .NewUnstartedServer (h )
97
108
// Ditch the provided listener, replace with our own:
98
109
ts .Listener .Close ()
99
110
ts .Listener = ln
@@ -106,7 +117,7 @@ func serveDevTLS(port int) error {
106
117
select {}
107
118
}
108
119
109
- func serveAutocertTLS (bucket string ) error {
120
+ func serveAutocertTLS (h http. Handler , bucket string ) error {
110
121
ln , err := net .Listen ("tcp" , ":443" )
111
122
if err != nil {
112
123
return err
@@ -132,7 +143,8 @@ func serveAutocertTLS(bucket string) error {
132
143
}
133
144
tlsLn := tls .NewListener (tcpKeepAliveListener {ln .(* net.TCPListener )}, config )
134
145
server := & http.Server {
135
- Addr : ln .Addr ().String (),
146
+ Addr : ln .Addr ().String (),
147
+ Handler : h ,
136
148
}
137
149
if err := http2 .ConfigureServer (server , nil ); err != nil {
138
150
log .Fatalf ("http2.ConfigureServer: %v" , err )
@@ -155,55 +167,6 @@ func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
155
167
return tc , nil
156
168
}
157
169
158
- // hstsHandler wraps an http.HandlerFunc such that it sets the HSTS header.
159
- func hstsHandler (fn http.HandlerFunc ) http.Handler {
160
- return http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
161
- w .Header ().Set ("Strict-Transport-Security" , "max-age=31536000; preload" )
162
- fn (w , r )
163
- })
164
- }
165
-
166
- type page struct {
167
- // Content is the complete HTML of the page.
168
- Content []byte
169
- }
170
-
171
- var (
172
- pageStore = map [string ]* page {}
173
- pageStoreMu sync.Mutex
174
- )
175
-
176
- func getPage (name string ) (* page , error ) {
177
- pageStoreMu .Lock ()
178
- defer pageStoreMu .Unlock ()
179
- p , ok := pageStore [name ]
180
- if ok {
181
- return p , nil
182
- }
183
- return nil , fmt .Errorf ("page key %s not found" , name )
184
- }
185
-
186
- func writePage (pageStr string , content []byte ) error {
187
- pageStoreMu .Lock ()
188
- defer pageStoreMu .Unlock ()
189
- entity := & page {
190
- Content : content ,
191
- }
192
- pageStore [pageStr ] = entity
193
- return nil
194
- }
195
-
196
- func servePage (w http.ResponseWriter , r * http.Request , pageStr string ) {
197
- entity , err := getPage (pageStr )
198
- if err != nil {
199
- log .Printf ("getPage(%s) = %v" , pageStr , err )
200
- http .NotFound (w , r )
201
- return
202
- }
203
- w .Header ().Set ("Content-Type" , "text/html; charset=utf-8" )
204
- w .Write (entity .Content )
205
- }
206
-
207
170
type countTransport struct {
208
171
http.RoundTripper
209
172
count int64
@@ -270,11 +233,3 @@ func newTransport(ctx context.Context) http.RoundTripper {
270
233
}
271
234
return t
272
235
}
273
-
274
- // GET /favicon.ico
275
- func faviconHandler (w http.ResponseWriter , r * http.Request ) {
276
- // Need to specify content type for consistent tests, without this it's
277
- // determined from mime.types on the box the test is running on
278
- w .Header ().Set ("Content-Type" , "image/x-icon" )
279
- http .ServeFile (w , r , "./static/favicon.ico" )
280
- }
0 commit comments