Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save scottfrazer/16f7610f9738965d72dc32fe56aaeb83 to your computer and use it in GitHub Desktop.
Save scottfrazer/16f7610f9738965d72dc32fe56aaeb83 to your computer and use it in GitHub Desktop.
package main
import (
"net/http"
"fmt"
"io/ioutil"
"strconv"
"strings"
"os"
"bufio"
"regexp"
"bytes"
"time"
"math/rand"
)
var port int
func thisHost() string {
return fmt.Sprintf("localhost:%d", port)
}
type timeHandler struct {
format string
}
func (th *timeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
tm := time.Now().Format(th.format)
w.Write([]byte("The time is: " + tm))
}
func handler(w http.ResponseWriter, r *http.Request) {
body, _ := ioutil.ReadAll(r.Body)
stringBody := string(body)
fmt.Printf("handler() %s\n", r.URL.String())
for k, v := range r.Header {
fmt.Printf("[%s] %s: %s\n", stringBody, k, v)
}
fmt.Printf("\n[%s] %s\n", stringBody, stringBody)
fmt.Fprintf(w, fmt.Sprintf("response to %s", stringBody))
}
func ping(w http.ResponseWriter, r *http.Request) {
respondTo := r.Header["X-Ping-Sendto"][0]
count, _ := strconv.Atoi(r.Header["X-Ping"][0])
sleepTime, _ := strconv.Atoi(r.Header["X-Ping-Slept"][0])
fmt.Printf("[ping] addr=%s, count=%d, slept=%d START\n", respondTo, count, sleepTime)
if count > 0 {
var sleepMs int64 = int64(rand.Int() % 1000)
fmt.Printf("[ping] sleep for %d\n", sleepMs)
time.Sleep(time.Duration(sleepMs) * time.Millisecond)
go sendping(respondTo, count - 1, sleepTime + int(sleepMs))
} else if count == 0 {
fmt.Printf("%s slept %dms\n", green("!!! DONE"), sleepTime)
}
fmt.Printf("[ping] addr=%s, count=%d, slept=%d END\n", respondTo, count, sleepTime)
}
func red(s string) string { return fmt.Sprintf("\033[38;5;1m%s\033[0m", s) }
func green(s string) string { return fmt.Sprintf("\033[38;5;2m%s\033[0m", s) }
func yellow(s string) string { return fmt.Sprintf("\033[38;5;3m%s\033[0m", s) }
func sendping(toHost string, i int, sleptTime int) {
url := fmt.Sprintf("http://%s/ping/", toHost)
fmt.Printf("[sendping addr=%s count=%d] start\n", url, i)
req, err := http.NewRequest("POST", url, bytes.NewBuffer([]byte{}))
req.Header.Set("X-Ping", fmt.Sprintf("%d", i))
req.Header.Set("X-Ping-Sendto", thisHost())
req.Header.Set("X-Ping-Slept", fmt.Sprintf("%d", sleptTime))
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Println(err)
sleepMs := int64(rand.Int() % 1000)
fmt.Printf("%s after %dms URL=%s count=%d\n", red("!!! RETRYING"), sleepMs, url, i)
time.Sleep(time.Duration(sleepMs) * time.Millisecond)
sendping(toHost, i, sleptTime + int(sleepMs))
return
}
defer resp.Body.Close()
fmt.Printf("[sendping addr=%s count=%d] %s\n", url, i, resp.Status)
}
func repl() {
reader := bufio.NewReader(os.Stdin)
cmdRegex := regexp.MustCompile(`([a-z]+) (\d+)`)
for {
fmt.Print("> ")
cmd, _ := reader.ReadString('\n')
res := cmdRegex.FindStringSubmatch(cmd)
if len(res) == 3 {
command := strings.TrimSpace(res[1])
port, _ := strconv.Atoi(res[2])
if command == "sendping" {
for i := 0; i < 100; i++ {
go sendping(fmt.Sprintf("localhost:%d", port), 100, 0)
}
}
}
}
}
func main() {
args := os.Args[1:]
if len(args) == 0 {
fmt.Printf("Usage: %s <port>\n", os.Args[0])
return
}
port, _ = strconv.Atoi(os.Args[1])
mux := http.NewServeMux()
mux.HandleFunc("/ping/", ping)
mux.HandleFunc("/", handler)
mux.Handle("/time", &timeHandler{format: time.RFC1123})
mux.Handle("/time2", &timeHandler{format: time.RFC3339})
s := &http.Server{
Addr: fmt.Sprintf(":%d", port),
Handler: mux,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
go repl()
fmt.Printf("Listening on %s...\n", s.Addr)
s.ListenAndServe()
fmt.Printf("exit")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment