package main import ( "fmt" "io" "math/rand" "net/http" "strconv" "time" ) const ( randomPoolSize = 4 * 1024 * 1024 // 4MB pool of random data, read-only after init uploadBufSize = 32 * 1024 // per-request local buffer ) var randomPool []byte func init() { rng := rand.New(rand.NewSource(time.Now().UnixNano())) randomPool = make([]byte, randomPoolSize) rng.Read(randomPool) } func main() { http.HandleFunc("/download", downloadHandler) http.HandleFunc("/upload", uploadHandler) port := ":8080" fmt.Printf("Speedtest server starting on http://localhost%s\n", port) fmt.Printf("Download endpoint: GET /download?bytes=\n") fmt.Printf("Upload endpoint: POST /upload\n") if err := http.ListenAndServe(port, nil); err != nil { fmt.Printf("Server error: %v\n", err) } } func downloadHandler(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } bytesParam := r.URL.Query().Get("bytes") if bytesParam == "" { http.Error(w, "Missing 'bytes' parameter", http.StatusBadRequest) return } numBytes, err := strconv.ParseInt(bytesParam, 10, 64) if err != nil || numBytes <= 0 { http.Error(w, "Invalid 'bytes' parameter", http.StatusBadRequest) return } w.Header().Set("Content-Type", "application/octet-stream") w.Header().Set("Content-Length", strconv.FormatInt(numBytes, 10)) poolLen := int64(len(randomPool)) offset := int64(0) remaining := numBytes for remaining > 0 { start := offset % poolLen end := start + remaining if end > poolLen { end = poolLen } n, writeErr := w.Write(randomPool[start:end]) if writeErr != nil { return } written := int64(n) remaining -= written offset += written } } func uploadHandler(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } defer r.Body.Close() buf := make([]byte, uploadBufSize) for { _, err := r.Body.Read(buf) if err == io.EOF { break } if err != nil { http.Error(w, "Error reading body", http.StatusInternalServerError) return } } w.WriteHeader(http.StatusOK) w.Write([]byte("Upload complete")) }