helpers.go
1 package web 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "log" 7 "net/http" 8 "strings" 9 ) 10 11 func sendResponse(w http.ResponseWriter, payload any) { 12 // note: w.Header after this, so we can call sendError 13 b, err := json.Marshal(payload) 14 if err != nil { 15 sendErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("in json.Marshal: %s", err.Error())) 16 return 17 } 18 w.Header().Set("Content-Type", "application/json") 19 w.Header().Set("Cache-Control", "no-store") // do not cache (Browsers cache GET forever by default) 20 w.Write(b) 21 } 22 23 func sendErrorResponse(w http.ResponseWriter, code int, message string) { 24 log.Printf("[!] %d: %s\n", code, message) 25 // would prefer to use json.Marshal, but this avoids the need 26 // to handle encoding errors arising from json.Marshal itself! 27 payload := fmt.Sprintf("{\"error\":{\"code\":%q,\"message\":%q}}", code, message) 28 w.Header().Set("Content-Type", "application/json") 29 w.Header().Set("Cache-Control", "no-store") // do not cache (Browsers cache GET forever by default) 30 w.WriteHeader(code) 31 w.Write([]byte(payload)) 32 } 33 34 func getOriginIP(r *http.Request) string { 35 var originIP string 36 37 // handle proxies 38 if r.Header.Get("X-Forwarded-For") != "" { 39 // If there are multiple IPs in X-Forwarded-For, take the first one 40 originIP = strings.Split(r.Header.Get("X-Forwarded-For"), ",")[0] 41 } else { 42 // otherwise just use the remote address 43 originIP = strings.Split(r.RemoteAddr, ":")[0] 44 } 45 46 return originIP 47 }