package util import ( "bytes" "encoding/json" "fmt" "io" "net" "net/http" "net/url" "strings" ) func RemoteIP(r *http.Request) string { ip, _, _ := net.SplitHostPort(r.RemoteAddr) return ip } func GetClientIP(r *http.Request) string { ip := strings.TrimSpace(strings.Split(r.Header.Get("X-Forwarded-For"), ",")[0]) if ip != "" { ip2, _, err := net.SplitHostPort(ip) if err != nil { return ip } return ip2 } ip = strings.TrimSpace(r.Header.Get("X-Real-Ip")) if ip != "" { ip2, _, err := net.SplitHostPort(ip) if err != nil { return ip } return ip2 } if ip, _, err := net.SplitHostPort(strings.TrimSpace(r.RemoteAddr)); err == nil { return ip } return "" } func GetClientPublicIP(r *http.Request) string { var ip string for _, ip = range strings.Split(r.Header.Get("X-Forwarded-For"), ",") { if ip = strings.TrimSpace(ip); ip != "" && !IsLocalIPAddr(ip) { ip2, _, err := net.SplitHostPort(ip) if err != nil { return ip } return ip2 } } if ip = strings.TrimSpace(r.Header.Get("X-Real-Ip")); ip != "" && !IsLocalIPAddr(ip) { ip2, _, err := net.SplitHostPort(ip) if err != nil { return ip } return ip2 } if ip = RemoteIP(r); !IsLocalIPAddr(ip) { ip2, _, err := net.SplitHostPort(ip) if err != nil { return ip } return ip2 } return "" } func RespRedirect(w http.ResponseWriter, r *http.Request, url string) { http.Redirect(w, r, url, http.StatusMovedPermanently) } func LastPage(w http.ResponseWriter, r *http.Request) { RespRedirect(w, r, r.URL.String()[:strings.LastIndexByte(r.URL.String(), '/')]) } func Reload(w http.ResponseWriter, r *http.Request) { RespRedirect(w, r, r.URL.String()) } // HTTPRespCode Util Reserved code range (-100,100) type HTTPRespCode int const ( HTTPRespCodeOKCode HTTPRespCode = 0 HTTPRespCodeOKMsg string = "ok" HTTPRespCodeERCode HTTPRespCode = 1 HTTPRespCodeERMsg string = "failed to respond" HTTPRespCodeInvalidKeyCode HTTPRespCode = 2 HTTPRespCodeInvalidKeyMsg string = "invalid key" HTTPRespCodeProcessingFailedCode HTTPRespCode = 3 HTTPRespCodeProcessingFailedMsg string = "processing failed" HTTPRespCodeInvalidInputCode HTTPRespCode = 4 HTTPRespCodeInvalidInputMsg string = "invalid input" ) type HTTPRespAPIModel struct { Code HTTPRespCode `json:"code"` Msg string `json:"msg"` Data any `json:"data,omitempty"` } func (r *HTTPRespAPIModel) String() string { data, err := json.Marshal(r) if err != nil { return fmt.Sprintf(`{"code":%d,"msg":"%s"}`, HTTPRespCodeERCode, HTTPRespCodeERMsg) } return string(data) } func (r *HTTPRespAPIModel) Bytes() []byte { data, err := json.Marshal(r) if err != nil { return []byte(fmt.Sprintf(`{"code":%d,"msg":"%s"}`, HTTPRespCodeERCode, HTTPRespCodeERMsg)) } return data } // NewHTTPResp Util Reserved code range (-100,100) func NewHTTPResp(code HTTPRespCode, msg string, data any) *HTTPRespAPIModel { return &HTTPRespAPIModel{ Code: code, Msg: msg, Data: data, } } func ParseHTTPResp(respstr string) *HTTPRespAPIModel { resp := &HTTPRespAPIModel{} err := json.Unmarshal([]byte(respstr), resp) if err != nil { return nil } return resp } func WriteHTTPRespAPIOk(w http.ResponseWriter, data any, msg ...any) { m := HTTPRespCodeOKMsg if len(msg) > 0 { m = fmt.Sprint(msg...) } w.Header().Set("Content-Type", HTTPContentTypeJson) _, _ = w.Write(NewHTTPResp(HTTPRespCodeOKCode, m, data).Bytes()) } func WriteHTTPRespAPIFailed(w http.ResponseWriter, data any, msg ...any) { m := HTTPRespCodeERMsg if len(msg) > 0 { m = fmt.Sprint(msg...) } w.Header().Set("Content-Type", HTTPContentTypeJson) _, _ = w.Write(NewHTTPResp(HTTPRespCodeERCode, m, data).Bytes()) } func WriteHTTPRespAPIInvalidKey(w http.ResponseWriter, data any, msg ...any) { m := HTTPRespCodeInvalidKeyMsg if len(msg) > 0 { m = fmt.Sprint(msg...) } w.Header().Set("Content-Type", HTTPContentTypeJson) _, _ = w.Write(NewHTTPResp(HTTPRespCodeInvalidKeyCode, m, data).Bytes()) } func WriteHTTPRespAPIInvalidInput(w http.ResponseWriter, data any, msg ...any) { m := HTTPRespCodeInvalidInputMsg if len(msg) > 0 { m = fmt.Sprint(msg...) } w.Header().Set("Content-Type", HTTPContentTypeJson) _, _ = w.Write(NewHTTPResp(HTTPRespCodeInvalidInputCode, m, data).Bytes()) } func WriteHTTPRespAPIProcessingFailed(w http.ResponseWriter, data any, msg ...any) { m := HTTPRespCodeProcessingFailedMsg if len(msg) > 0 { m = fmt.Sprint(msg...) } w.Header().Set("Content-Type", HTTPContentTypeJson) _, _ = w.Write(NewHTTPResp(HTTPRespCodeProcessingFailedCode, m, data).Bytes()) } const ( HTTPContentTypeUrlencoded = "application/x-www-form-urlencoded" HTTPContentTypeUrlencodedUTF8 = "application/x-www-form-urlencoded; charset=utf-8" HTTPContentTypeJson = "application/json" HTTPContentTypeJsonUTF8 = "application/json; charset=UTF-8" HTTPContentTypeXml = "application/xml" HTTPContentTypeXmlUTF8 = "application/xml; charset=UTF-8" HTTPContentTypePlain = "text/plain" HTTPContentTypePlainUTF8 = "text/plain; charset=utf-8" HTTPContentTypeHtml = "text/html" HTTPContentTypeHtmlUTF8 = "text/html; charset=utf-8" HTTPContentTypeFormData = "multipart/form-data" HTTPContentTypeFormDataUTF8 = "multipart/form-data; charset=utf-8" ) func HttpGet(u string, args any, contentType string, header map[string]string) []byte { arg := NewJSON(args, false).Map() req, err := http.NewRequest("GET", u, nil) if err != nil { return nil } q := req.URL.Query() for k, v := range arg { q.Add(k, fmt.Sprint(v)) } req.URL.RawQuery = q.Encode() if header == nil { header = make(map[string]string) } header["Content-Type"] = contentType for k, v := range header { req.Header.Set(k, v) } client := &http.Client{} rsp, err := client.Do(req) if err != nil { return nil } defer rsp.Body.Close() body, err := io.ReadAll(rsp.Body) if err != nil { return nil } return body } func HttpPost(u string, args any, contentType string, header map[string]string) []byte { var req *http.Request var err error if contentType == HTTPContentTypeUrlencoded { arg := NewJSON(args, false).Map() payload := url.Values{} for k, v := range arg { payload.Set(k, fmt.Sprint(v)) } req, err = http.NewRequest("POST", u, strings.NewReader(payload.Encode())) if err != nil { return nil } } else if contentType == HTTPContentTypeJson { req, err = http.NewRequest("POST", u, bytes.NewBuffer(NewJSON(args, false).Bytes())) if err != nil { return nil } } else { return nil } if header == nil { header = make(map[string]string) } header["Content-Type"] = contentType for k, v := range header { req.Header.Set(k, v) } client := &http.Client{} rsp, err := client.Do(req) if err != nil { return nil } defer rsp.Body.Close() body, err := io.ReadAll(rsp.Body) if err != nil { return nil } return body } func HttpPostGet(u string, argsGET, argsPOST any, contentType string, header map[string]string) []byte { var req *http.Request var err error if contentType == HTTPContentTypeUrlencoded { arg := NewJSON(argsPOST, false).Map() payload := url.Values{} for k, v := range arg { payload.Set(k, fmt.Sprint(v)) } req, err = http.NewRequest("POST", u, strings.NewReader(payload.Encode())) if err != nil { return nil } } else if contentType == HTTPContentTypeJson { req, err = http.NewRequest("POST", u, bytes.NewBuffer(NewJSON(argsPOST, false).Bytes())) if err != nil { return nil } } else { return nil } if header == nil { header = make(map[string]string) } header["Content-Type"] = contentType for k, v := range header { req.Header.Set(k, v) } argGet := NewJSON(argsGET, false).Map() q := req.URL.Query() for k, v := range argGet { q.Add(k, fmt.Sprint(v)) } req.URL.RawQuery = q.Encode() client := &http.Client{} rsp, err := client.Do(req) if err != nil { return nil } defer rsp.Body.Close() body, err := io.ReadAll(rsp.Body) if err != nil { return nil } return body }