elaborated_webserver.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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. package main
  5. import (
  6. "bytes"
  7. "expvar"
  8. "flag"
  9. "fmt"
  10. "net/http"
  11. "io"
  12. "log"
  13. "os"
  14. "strconv"
  15. )
  16. // hello world, the web server
  17. var helloRequests = expvar.NewInt("hello-requests")
  18. // flags:
  19. var webroot = flag.String("root", "/home/user", "web root directory")
  20. // simple flag server
  21. var booleanflag = flag.Bool("boolean", true, "another flag for testing")
  22. // Simple counter server. POSTing to it will set the value.
  23. type Counter struct {
  24. n int
  25. }
  26. // a channel
  27. type Chan chan int
  28. func main() {
  29. flag.Parse()
  30. http.Handle("/", http.HandlerFunc(Logger))
  31. http.Handle("/go/hello", http.HandlerFunc(HelloServer))
  32. // The counter is published as a variable directly.
  33. ctr := new(Counter)
  34. expvar.Publish("counter", ctr)
  35. http.Handle("/counter", ctr)
  36. // http.Handle("/go/", http.FileServer(http.Dir("/tmp"))) // uses the OS filesystem
  37. http.Handle("/go/", http.StripPrefix("/go/", http.FileServer(http.Dir(*webroot))))
  38. http.Handle("/flags", http.HandlerFunc(FlagServer))
  39. http.Handle("/args", http.HandlerFunc(ArgServer))
  40. http.Handle("/chan", ChanCreate())
  41. http.Handle("/date", http.HandlerFunc(DateServer))
  42. err := http.ListenAndServe(":12345", nil)
  43. if err != nil {
  44. log.Panicln("ListenAndServe:", err)
  45. }
  46. }
  47. func Logger(w http.ResponseWriter, req *http.Request) {
  48. log.Print(req.URL.String())
  49. w.WriteHeader(404)
  50. w.Write([]byte("oops"))
  51. }
  52. func HelloServer(w http.ResponseWriter, req *http.Request) {
  53. helloRequests.Add(1)
  54. io.WriteString(w, "hello, world!\n")
  55. }
  56. // This makes Counter satisfy the expvar.Var interface, so we can export
  57. // it directly.
  58. func (ctr *Counter) String() string { return fmt.Sprintf("%d", ctr.n) }
  59. func (ctr *Counter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
  60. switch req.Method {
  61. case "GET": // increment n
  62. ctr.n++
  63. case "POST": // set n to posted value
  64. buf := new(bytes.Buffer)
  65. io.Copy(buf, req.Body)
  66. body := buf.String()
  67. if n, err := strconv.Atoi(body); err != nil {
  68. fmt.Fprintf(w, "bad POST: %v\nbody: [%v]\n", err, body)
  69. } else {
  70. ctr.n = n
  71. fmt.Fprint(w, "counter reset\n")
  72. }
  73. }
  74. fmt.Fprintf(w, "counter = %d\n", ctr.n)
  75. }
  76. func FlagServer(w http.ResponseWriter, req *http.Request) {
  77. w.Header().Set("Content-Type", "text/plain; charset=utf-8")
  78. fmt.Fprint(w, "Flags:\n")
  79. flag.VisitAll(func(f *flag.Flag) {
  80. if f.Value.String() != f.DefValue {
  81. fmt.Fprintf(w, "%s = %s [default = %s]\n", f.Name, f.Value.String(), f.DefValue)
  82. } else {
  83. fmt.Fprintf(w, "%s = %s\n", f.Name, f.Value.String())
  84. }
  85. })
  86. }
  87. // simple argument server
  88. func ArgServer(w http.ResponseWriter, req *http.Request) {
  89. for _, s := range os.Args {
  90. fmt.Fprint(w, s, " ")
  91. }
  92. }
  93. func ChanCreate() Chan {
  94. c := make(Chan)
  95. go func(c Chan) {
  96. for x := 0; ; x++ {
  97. c <- x
  98. }
  99. }(c)
  100. return c
  101. }
  102. func (ch Chan) ServeHTTP(w http.ResponseWriter, req *http.Request) {
  103. io.WriteString(w, fmt.Sprintf("channel send #%d\n", <-ch))
  104. }
  105. // exec a program, redirecting output
  106. func DateServer(rw http.ResponseWriter, req *http.Request) {
  107. rw.Header().Set("Content-Type", "text/plain; charset=utf-8")
  108. r, w, err := os.Pipe()
  109. if err != nil {
  110. fmt.Fprintf(rw, "pipe: %s\n", err)
  111. return
  112. }
  113. p, err := os.StartProcess("/bin/date", []string{"date"}, &os.ProcAttr{Files: []*os.File{nil, w, w}})
  114. defer r.Close()
  115. w.Close()
  116. if err != nil {
  117. fmt.Fprintf(rw, "fork/exec: %s\n", err)
  118. return
  119. }
  120. defer p.Release()
  121. io.Copy(rw, r)
  122. wait, err := p.Wait()
  123. if err != nil {
  124. fmt.Fprintf(rw, "wait: %s\n", err)
  125. return
  126. }
  127. if !wait.Exited() {
  128. fmt.Fprintf(rw, "date: %v\n", wait)
  129. return
  130. }
  131. }