88 lines
2.0 KiB
Go
88 lines
2.0 KiB
Go
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")
|
|
}
|