LEFT | RIGHT |
1 // Copyright 2011 The Go Authors. All rights reserved. | 1 // Copyright 2011 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package main | 5 package main |
6 | 6 |
7 import ( | 7 import ( |
8 "bytes" | 8 "bytes" |
9 "flag" | 9 "flag" |
10 "fmt" | 10 "fmt" |
11 "go/build" | 11 "go/build" |
12 "io/ioutil" | 12 "io/ioutil" |
13 "log" | 13 "log" |
| 14 "net" |
14 "net/http" | 15 "net/http" |
15 "os" | 16 "os" |
16 "os/exec" | 17 "os/exec" |
17 "path/filepath" | 18 "path/filepath" |
18 "regexp" | 19 "regexp" |
19 "runtime" | 20 "runtime" |
20 "strconv" | 21 "strconv" |
21 "strings" | |
22 "sync" | 22 "sync" |
23 "time" | 23 "time" |
24 | 24 |
25 // Imports so that go build/install automatically installs them. | 25 // Imports so that go build/install automatically installs them. |
26 _ "code.google.com/p/go-tour/pic" | 26 _ "code.google.com/p/go-tour/pic" |
27 _ "code.google.com/p/go-tour/tree" | 27 _ "code.google.com/p/go-tour/tree" |
28 _ "code.google.com/p/go-tour/wc" | 28 _ "code.google.com/p/go-tour/wc" |
29 ) | 29 ) |
30 | 30 |
31 const basePkg = "code.google.com/p/go-tour/" | 31 const basePkg = "code.google.com/p/go-tour/" |
32 | 32 |
33 var ( | 33 var ( |
34 » httpListen = flag.String("http", "127.0.0.1:3999", "host:port to listen
on") | 34 » httpListen = flag.String("http", "127.0.0.1:3999", "host:port to listen
on") |
35 » htmlOutput = flag.Bool("html", false, "render program output as HTML") | 35 » htmlOutput = flag.Bool("html", false, "render program output as HTML") |
| 36 » openBrowser = flag.Bool("openbrowser", true, "open browser automatically
") |
36 ) | 37 ) |
37 | 38 |
38 var ( | 39 var ( |
39 // a source of numbers, for naming temporary files | 40 // a source of numbers, for naming temporary files |
40 uniq = make(chan int) | 41 uniq = make(chan int) |
41 ) | 42 ) |
42 | 43 |
43 func main() { | 44 func main() { |
44 flag.Parse() | 45 flag.Parse() |
45 | 46 |
(...skipping 16 matching lines...) Expand all Loading... |
62 fn := filepath.Join(root, "static", r.URL.Path[1:]) | 63 fn := filepath.Join(root, "static", r.URL.Path[1:]) |
63 http.ServeFile(w, r, fn) | 64 http.ServeFile(w, r, fn) |
64 return | 65 return |
65 } | 66 } |
66 http.Error(w, "not found", 404) | 67 http.Error(w, "not found", 404) |
67 }) | 68 }) |
68 http.Handle("/static/", http.FileServer(http.Dir(root))) | 69 http.Handle("/static/", http.FileServer(http.Dir(root))) |
69 http.Handle("/talks/", http.FileServer(http.Dir(root))) | 70 http.Handle("/talks/", http.FileServer(http.Dir(root))) |
70 http.HandleFunc("/kill", kill) | 71 http.HandleFunc("/kill", kill) |
71 | 72 |
72 » if !strings.HasPrefix(*httpListen, "127.0.0.1") && | 73 » host, port, err := net.SplitHostPort(*httpListen) |
73 » » !strings.HasPrefix(*httpListen, "localhost") { | 74 » if err != nil { |
| 75 » » log.Fatal(err) |
| 76 » } |
| 77 » if host == "" { |
| 78 » » host = "localhost" |
| 79 » } |
| 80 » if host != "127.0.0.1" && host != "localhost" { |
74 log.Print(localhostWarning) | 81 log.Print(localhostWarning) |
75 } | 82 } |
76 | 83 |
77 » go startBrowser("http://" + *httpListen) | 84 » httpAddr := host + ":" + port |
78 » log.Fatal(http.ListenAndServe(*httpListen, nil)) | 85 » go func() { |
| 86 » » url := "http://" + httpAddr |
| 87 » » if waitServer(url) && *openBrowser && startBrowser(url) { |
| 88 » » » log.Printf("A browser window should open. If not, please
visit %s", url) |
| 89 » » } else { |
| 90 » » » log.Printf("Please open your web browser and visit %s",
url) |
| 91 » » } |
| 92 » }() |
| 93 » log.Fatal(http.ListenAndServe(httpAddr, nil)) |
79 } | 94 } |
80 | 95 |
81 const localhostWarning = ` | 96 const localhostWarning = ` |
82 WARNING! WARNING! WARNING! | 97 WARNING! WARNING! WARNING! |
83 | 98 |
84 I appear to be listening on an address that is not localhost. | 99 I appear to be listening on an address that is not localhost. |
85 Anyone with access to this address and port will have access | 100 Anyone with access to this address and port will have access |
86 to this machine as the user running gotour. | 101 to this machine as the user running gotour. |
87 | 102 |
88 If you don't understand this message, hit Control-C to terminate this process. | 103 If you don't understand this message, hit Control-C to terminate this process. |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 // Wait for the command. Clean up, | 200 // Wait for the command. Clean up, |
186 err := cmd.Wait() | 201 err := cmd.Wait() |
187 running.Lock() | 202 running.Lock() |
188 if running.cmd == cmd { | 203 if running.cmd == cmd { |
189 running.cmd = nil | 204 running.cmd = nil |
190 } | 205 } |
191 running.Unlock() | 206 running.Unlock() |
192 return buf.Bytes(), err | 207 return buf.Bytes(), err |
193 } | 208 } |
194 | 209 |
195 // startBrowser tries to open the URL in a browser after verifying | 210 // waitServer waits some time for the http Server to start |
196 // the http severs starts serving | 211 // serving url and returns whether it starts |
197 func startBrowser(url string) { | 212 func waitServer(url string) bool { |
198 » // wait for the server start | 213 » tries := 20 |
199 » for { | 214 » for tries > 0 { |
200 resp, err := http.Get(url) | 215 resp, err := http.Get(url) |
201 if err == nil { | 216 if err == nil { |
202 resp.Body.Close() | 217 resp.Body.Close() |
203 » » » break | 218 » » » return true |
204 » » } | 219 » » } |
205 » » time.Sleep(10 * time.Millisecond) | 220 » » time.Sleep(100 * time.Millisecond) |
206 » } | 221 » » tries-- |
| 222 » } |
| 223 » return false |
| 224 } |
| 225 |
| 226 // startBrowser tries to open the URL in a browser, and returns |
| 227 // whether it succeed. |
| 228 func startBrowser(url string) bool { |
207 // try to start the browser | 229 // try to start the browser |
208 » prog := "" | 230 » var args []string |
209 switch runtime.GOOS { | 231 switch runtime.GOOS { |
210 case "darwin": | 232 case "darwin": |
211 » » prog = "open" | 233 » » args = []string{"open"} |
212 case "windows": | 234 case "windows": |
213 » » prog = "start" | 235 » » args = []string{"cmd", "/c", "start"} |
214 default: | 236 default: |
215 » » prog = "xdg-open" | 237 » » args = []string{"xdg-open"} |
216 » } | 238 » } |
217 » cmd := exec.Command(prog, url) | 239 » cmd := exec.Command(args[0], append(args[1:], url)...) |
218 » if err := cmd.Start(); err != nil { | 240 » return cmd.Start() == nil |
219 » » log.Printf("Please open your web browser and visit %s", url) | 241 } |
220 » } else { | |
221 » » log.Printf("A browser window should open for the tour, if not, p
lease visit %s manually.", url) | |
222 » } | |
223 } | |
LEFT | RIGHT |