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 7package main 8 9import ( 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 24var helloRequests = expvar.NewInt("hello-requests") 25 26func 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. 32type 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. 39func (ctr *Counter) String() string { 40 ctr.mu.Lock() 41 defer ctr.mu.Unlock() 42 return fmt.Sprintf("%d", ctr.n) 43} 44 45func (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 66var booleanflag = flag.Bool("boolean", true, "another flag for testing") 67 68func 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 81func 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) 88type Chan chan int 89 90func 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 100func (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 105func 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(), http.StatusInternalServerError) 111 return 112 } 113 rw.Write(date) 114} 115 116func Logger(w http.ResponseWriter, req *http.Request) { 117 log.Print(req.URL) 118 http.Error(w, "oops", http.StatusNotFound) 119} 120 121var webroot = flag.String("root", os.Getenv("HOME"), "web root directory") 122 123func 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