// Package loadtestorigin is the upstream host script/loadtest points pixad // at, run by cmd/loadtest-origin. It answers every request, whatever its path, // with the same generated JPEG, so each new path is a new source image for // pixad to fetch, and it logs one line per request, so its log counts pixad's // fetches. package loadtestorigin import ( "bytes" "image" "image/color" "image/jpeg" "log/slog" "math" "net/http" "os" "time" ) const ( listenAddress = ":80" readHeaderTimeout = 10 * time.Second imageWidth = 1600 imageHeight = 1200 jpegQuality = 85 ) // Run makes the image and serves it on port 80 until the server fails, then // exits the process with status 1. func Run() { photo, err := makeJPEG() if err != nil { slog.Error("cannot make the image", "error", err) os.Exit(1) } server := &http.Server{ Addr: listenAddress, Handler: newHandler(photo), ReadHeaderTimeout: readHeaderTimeout, } err = server.ListenAndServe() slog.Error("server stopped", "error", err) os.Exit(1) } // newHandler answers every request with photo and logs the request's path. func newHandler(photo []byte) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { slog.Info("request", "path", r.URL.Path) w.Header().Set("Content-Type", "image/jpeg") _, _ = w.Write(photo) }) } // makeJPEG draws colour gradients crossed with a fine pattern, so the image // has detail to decode and does not compress to almost nothing. func makeJPEG() ([]byte, error) { img := image.NewRGBA(image.Rect(0, 0, imageWidth, imageHeight)) // red and green count up from 0 to 255 and wrap around, along each row // and down the image. var green uint8 for y := range imageHeight { var red uint8 for x := range imageWidth { img.SetRGBA(x, y, color.RGBA{ R: red, G: green, B: red ^ green, A: math.MaxUint8, }) red++ } green++ } var buf bytes.Buffer err := jpeg.Encode(&buf, img, &jpeg.Options{Quality: jpegQuality}) if err != nil { return nil, err } return buf.Bytes(), nil }