package main import ( "io" "net" "net/http" "strings" "time" ) // RequestData — извлечённые данные входящего запроса type RequestData struct { Time time.Time Method string Host string URL string RemoteAddr string Header http.Header Body string } func GetRemoteAddr(r *http.Request) string { if xff := r.Header.Get("X-Forwarded-For"); xff != "" { ips := strings.Split(xff, ",") if len(ips) > 0 { return strings.TrimSpace(ips[0]) } } if realIP := r.Header.Get("X-Real-IP"); realIP != "" { return realIP } host, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { return r.RemoteAddr } return host } // ExtractRequest читает запрос один раз и возвращает нейтральные данные. func ExtractRequest(r *http.Request) RequestData { var body []byte if r.ContentLength > 1024 { body = []byte("too long") } else { body, _ = io.ReadAll(r.Body) } _ = r.Body.Close() return RequestData{ Time: time.Now(), Method: r.Method, Host: r.Host, URL: r.URL.RequestURI(), RemoteAddr: GetRemoteAddr(r), Header: r.Header, Body: string(body), } }