package main import ( "context" "fmt" "github.com/kordondev/meeting/throttling" "net/http" "slices" "time" ) const burstLimit = 2 func main() { ctx := context.Background() throttles := make(map[string]context.Context) calledLastHour := make([]string, 0) http.HandleFunc("/", serveIndexFile) http.HandleFunc("/input.txt", serveInputFile) http.HandleFunc("/result", func(w http.ResponseWriter, r *http.Request) { cctxV, ok := throttles[r.RemoteAddr] if !ok { cctx, cancel := context.WithCancel(ctx) throttle := throttling.CreateThrottle(cctx, burstLimit) a := throttleWithCancel{ throttle: throttle, cancel: cancel, } cctxV = context.WithValue(ctx, "throttle", a) throttles[r.RemoteAddr] = cctxV } tryResult(cctxV, w, r, calledLastHour) }) err := http.ListenAndServe(":3333", nil) if err != nil { fmt.Printf("http.ListenAndServe() failed with %s\n", err) } } type throttleWithCancel struct { throttle <-chan time.Time cancel context.CancelFunc } func serveIndexFile(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "static/index-with-text.html") } func serveInputFile(w http.ResponseWriter, r *http.Request) { fmt.Println(r.RemoteAddr) http.ServeFile(w, r, "static/input.txt") } func tryResult(ctx context.Context, w http.ResponseWriter, r *http.Request, calledLastHour []string) { clientIP := r.RemoteAddr clientResult := r.URL.Query().Get("result") fmt.Println(clientIP, clientResult) if !slices.Contains(calledLastHour, clientIP) { calledLastHour = append(calledLastHour, clientIP) } throttle := ctx.Value("throttle").(throttleWithCancel).throttle payload := throttling.Payload{ R: r, W: w, ClientResult: clientResult, } throttling.CallFunction(ctx, &CheckResult{}, &payload, throttle) } type CheckResult struct { } func (*CheckResult) Call(payload *throttling.Payload) { w := payload.W r := payload.R fmt.Println("Serve now") if payload.ClientResult == "12" { http.ServeFile(w, r, "static/success.html") } http.ServeFile(w, r, "static/fail.html") }