package main import ( "encoding/json" "errors" "log" "net/http" "net/netip" ) // @title My IP // @version 0.1 // @description Get the requseters Real IP, based on HTTP Requests func main() { handler := http.NewServeMux() handler.HandleFunc("/", handleRoot) log.Fatal(http.ListenAndServe(":8080", handler)) } type ResponseType string const ( TEXT ResponseType = "TEXT" JSON ResponseType = "JSON" DEFAULT ResponseType = TEXT ) func (r *ResponseType) IsValid() bool { // This is pretty ugly // TODO: Comapre with ignore-case if *r == TEXT { return true } if *r == JSON { return true } return false } func handleRoot(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { w.WriteHeader(http.StatusBadRequest) return } var Type ResponseType Type = ResponseType(r.URL.Query().Get("t")) if !Type.IsValid() { // Using defualt Type = DEFAULT } log.Printf("Type: %v\n", Type) ip, err := determineRealIP(r) if err != nil { log.Println(err.Error()) w.WriteHeader(http.StatusInternalServerError) return } err = writeFormattedIP(w, Type, ip) if err != nil { log.Println(err.Error()) w.WriteHeader(http.StatusInternalServerError) return } } func determineRealIP(r *http.Request) (string, error) { ip := r.RemoteAddr xRealIP := r.Header.Get("X-Real-IP") if xRealIP != "" { ip = xRealIP } ipPort, err := netip.ParseAddrPort(ip) if err != nil { return "", err } if !ipPort.IsValid() { return "", errors.New("Zero IP") } ip = ipPort.Addr().String() return ip, nil } func writeFormattedIP(w http.ResponseWriter, Type ResponseType, ip string) error { if Type == TEXT { _, err := w.Write([]byte(ip)) if err != nil { return err } return nil } if Type == JSON { // TODO: Use MarshalIndent jsonResponse, err := json.Marshal(map[string]string{"ip": ip}) if err != nil { return err } _, err = w.Write(jsonResponse) if err != nil { return err } } return nil }