1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build ignore 6 7 package main 8 9 import ( 10 "bytes" 11 "expvar" 12 "flag" 13 "fmt" 14 "io" 15 "log" 16 "net/http" 17 "os" 18 "os/exec" 19 "strconv" 20 "sync" 21 ) 22 23 // hello world, the web server 24 var helloRequests = expvar.NewInt("hello-requests") 25 26 func HelloServer(w http.ResponseWriter, req *http.Request) { 27 helloRequests.Add(1) 28 io.WriteString(w, "hello, world!\n") 29 } 30 31 // Simple counter server. POSTing to it will set the value. 32 type Counter struct { 33 mu sync.Mutex // protects n 34 n int 35 } 36 37 // This makes Counter satisfy the expvar.Var interface, so we can export 38 // it directly. 39 func (ctr *Counter) String() string { 40 ctr.mu.Lock() 41 defer ctr.mu.Unlock() 42 return fmt.Sprintf("%d", ctr.n) 43 } 44 45 func (ctr *Counter) ServeHTTP(w http.ResponseWriter, req *http.Request) { 46 ctr.mu.Lock() 47 defer ctr.mu.Unlock() 48 switch req.Method { 49 case "GET": 50 ctr.n++ 51 case "POST": 52 buf := new(bytes.Buffer) 53 io.Copy(buf, req.Body) 54 body := buf.String() 55 if n, err := strconv.Atoi(body); err != nil { 56 fmt.Fprintf(w, "bad POST: %v\nbody: [%v]\n", err, body) 57 } else { 58 ctr.n = n 59 fmt.Fprint(w, "counter reset\n") 60 } 61 } 62 fmt.Fprintf(w, "counter = %d\n", ctr.n) 63 } 64 65 // simple flag server 66 var booleanflag = flag.Bool("boolean", true, "another flag for testing") 67 68 func FlagServer(w http.ResponseWriter, req *http.Request) { 69 w.Header().Set("Content-Type", "text/plain; charset=utf-8") 70 fmt.Fprint(w, "Flags:\n") 71 flag.VisitAll(func(f *flag.Flag) { 72 if f.Value.String() != f.DefValue { 73 fmt.Fprintf(w, "%s = %s [default = %s]\n", f.Name, f.Value.String(), f.DefValue) 74 } else { 75 fmt.Fprintf(w, "%s = %s\n", f.Name, f.Value.String()) 76 } 77 }) 78 } 79 80 // simple argument server 81 func ArgServer(w http.ResponseWriter, req *http.Request) { 82 for _, s := range os.Args { 83 fmt.Fprint(w, s, " ") 84 } 85 } 86 87 // a channel (just for the fun of it) 88 type Chan chan int 89 90 func ChanCreate() Chan { 91 c := make(Chan) 92 go func(c Chan) { 93 for x := 0; ; x++ { 94 c <- x 95 } 96 }(c) 97 return c 98 } 99 100 func (ch Chan) ServeHTTP(w http.ResponseWriter, req *http.Request) { 101 io.WriteString(w, fmt.Sprintf("channel send #%d\n", <-ch)) 102 } 103 104 // exec a program, redirecting output 105 func DateServer(rw http.ResponseWriter, req *http.Request) { 106 rw.Header().Set("Content-Type", "text/plain; charset=utf-8") 107 108 date, err := exec.Command("/bin/date").Output() 109 if err != nil { 110 http.Error(rw, err.Error(), 500) 111 return 112 } 113 rw.Write(date) 114 } 115 116 func Logger(w http.ResponseWriter, req *http.Request) { 117 log.Print(req.URL) 118 http.Error(w, "oops", 404) 119 } 120 121 var webroot = flag.String("root", os.Getenv("HOME"), "web root directory") 122 123 func main() { 124 flag.Parse() 125 126 // The counter is published as a variable directly. 127 ctr := new(Counter) 128 expvar.Publish("counter", ctr) 129 http.Handle("/counter", ctr) 130 http.Handle("/", http.HandlerFunc(Logger)) 131 http.Handle("/go/", http.StripPrefix("/go/", http.FileServer(http.Dir(*webroot)))) 132 http.Handle("/chan", ChanCreate()) 133 http.HandleFunc("/flags", FlagServer) 134 http.HandleFunc("/args", ArgServer) 135 http.HandleFunc("/go/hello", HelloServer) 136 http.HandleFunc("/date", DateServer) 137 log.Fatal(http.ListenAndServe(":12345", nil)) 138 } 139