Home | History | Annotate | Download | only in http
      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