package main import ( "fmt" "log" "math" "net/http" "net/http/httputil" ) func handler(p *httputil.ReverseProxy) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { //put the request inside our structure ProxyFlow.request = r probs := Classifier.Posterior(formatRequest(r)) log.Printf("Posterior Probabilities: %+v\n", probs) action := quadrant(probs) ControPlane.StatsTokens <- action switch action { case "BLOCK": w.Header().Set("Probabilities", fmt.Sprintf("%v", probs)) w.WriteHeader(403) w.Header().Set("Content-Encoding", "none") fmt.Fprintf(w, fmt.Sprintf("%s", BlockMessage)) log.Println("Request Blocked") case "BLOCKLEARN": p.ModifyResponse = classifierDecide w.Header().Set("Probabilities", fmt.Sprintf("%v ", probs)) w.WriteHeader(403) log.Println("Still Ingesting prediction") p.ServeHTTP(w, r) case "PASS": w.Header().Set("Probabilities", fmt.Sprintf("%v ", probs)) p.ServeHTTP(w, r) log.Println("Passing Request") case "PASSLEARN": p.ModifyResponse = classifierDecide w.Header().Set("Probabilities", fmt.Sprintf("%v ", probs)) p.ServeHTTP(w, r) log.Println("Passing Request and ingesting") default: log.Println("No Decision: PASS and LEARN") p.ModifyResponse = classifierDecide w.Header().Set("Probabilities", fmt.Sprintf("%v ", probs)) p.ServeHTTP(w, r) } } } func quadrant(p map[string]float64) string { sure := math.Abs(p["BAD"]-p["GOOD"]) >= ProxyFlow.sensitivity badish := p["BAD"] > p["GOOD"] goodish := p["GOOD"] > p["BAD"] if ProxyFlow.seniority < Maturity { log.Println("Seniority too low. Waiting.") return "MEH" } if sure { if goodish { return "PASS" } if badish { return "BLOCK" } } else { if goodish { return "PASSLEARN" } if badish { return "BLOCKLEARN" } } return "MEH" }