package main import ( "fmt" "log" "math/rand" "net/http" "os" "strconv" "time" "golang.org/x/net/http2" "golang.org/x/net/http2/h2c" ) const defaultPort = "8080" // This is a simple HTTP server that supports cleartext HTTP1.1 and HTTP2 // requests as well as upgrading to HTTP2 via h2c // Example: // $ COLOR=red PORT=8080 go run main.go // $ curl --http2-prior-knowledge -i localhost:8080 func main() { color := os.Getenv("COLOR") if color == "" { log.Fatalf("no COLOR defined") } port := os.Getenv("PORT") if port == "" { port = defaultPort } log.Printf("COLOR is: %v", color) log.Printf("PORT is: %v", port) flakeRate := float32(0.0) flakeCode := 200 mux := http.NewServeMux() mux.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) {}) mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { log.Printf("Received request: %v", r) if rand.Float32() < flakeRate { http.Error(w, "flaky server", flakeCode) return } fmt.Fprintf(w, "%s", color) }) mux.HandleFunc("/setFlake", func(w http.ResponseWriter, r *http.Request) { log.Printf("Received request: %v", r) query := r.URL.Query() rates, ok := query["rate"] if !ok { http.Error(w, "rate must be specified", 400) log.Printf("Could not read rate parameter") return } rate, err := strconv.ParseFloat(rates[0], 32) if err != nil { http.Error(w, err.Error(), 400) log.Printf("Could not parse rate parameter: %v", err) return } if rate < 0.0 || rate > 1.0 { http.Error(w, "rate must be between 0.0 and 1.0", 400) log.Printf("Invalid rate parameter: %v", rate) return } codes, ok := query["code"] if !ok { http.Error(w, "code must be specified", 400) log.Printf("Could not read code parameter: %v", err) return } code, err := strconv.ParseInt(codes[0], 10, 32) if err != nil { http.Error(w, err.Error(), 400) log.Printf("Could not parse code parameter: %v", err) return } fmt.Fprintf(w, "rate: %g, code: %d", flakeRate, flakeCode) flakeRate = float32(rate) flakeCode = int(code) }) h2s := &http2.Server{} h1s := &http.Server{ Addr: "0.0.0.0:" + port, Handler: h2c.NewHandler(mux, h2s), ReadTimeout: 5 * time.Second, WriteTimeout: 5 * time.Second, } log.Fatal(h1s.ListenAndServe()) }