Skip to content

Instantly share code, notes, and snippets.

@olix0r
Last active June 17, 2016 20:35
Show Gist options
  • Save olix0r/872f206ed22fce058fcd67c7fdc52e65 to your computer and use it in GitHub Desktop.
Save olix0r/872f206ed22fce058fcd67c7fdc52e65 to your computer and use it in GitHub Desktop.
A web server that occasionally closes connections (after serving 400).
package main
import (
"flag"
"fmt"
"math/rand"
"net/http"
"os"
)
type (
shutter struct {
// rate of terminal requests, on [0.0, 1.0]
TerminalRate float64
}
)
func (srv *shutter) ShouldTerminate() bool {
return (1.0 - rand.Float64()) <= srv.TerminalRate
}
func (srv *shutter) serveTerminal(w http.ResponseWriter) {
hj, ok := w.(http.Hijacker)
if !ok {
fmt.Fprintln(os.Stderr, "unhijackale")
http.Error(w, "webserver doesn't support hijacking", http.StatusInternalServerError)
return
}
conn, bufrw, err := hj.Hijack()
if err != nil {
fmt.Fprintln(os.Stderr, err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
bufrw.WriteString("HTTP/1.1 400 Ugly Request\r\n")
bufrw.WriteString("Connection: close\r\n")
bufrw.WriteString("Transfer-encoding: chunked\r\n")
bufrw.WriteString("\r\n")
bufrw.Flush()
bufrw.WriteString("0\r\n")
bufrw.WriteString("\r\n")
bufrw.Flush()
conn.Close()
}
func (srv *shutter) serveTypical(w http.ResponseWriter) {
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
w.WriteHeader(http.StatusOK)
}
func (srv *shutter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
req.Body.Close()
if srv.ShouldTerminate() {
fmt.Printf("* %s %s%s \n", req.Method, req.Host, req.URL)
srv.serveTerminal(w)
} else {
fmt.Printf("- %s %s%s \n", req.Method, req.Host, req.URL)
srv.serveTypical(w)
}
}
//
// main
//
func dieIf(err error) {
if err == nil {
return
}
fmt.Fprintf(os.Stderr, "Error: %s. Try --help for help.\n", err)
os.Exit(-1)
}
func main() {
addr := flag.String("srv", ":8080", "TCP address to listen on (in host:port form)")
flag.Parse()
if flag.NArg() != 0 {
dieIf(fmt.Errorf("expecting zero arguments but got %d", flag.NArg()))
}
server := &http.Server{
Addr: *addr,
Handler: &shutter{0.1},
}
dieIf(server.ListenAndServe())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment