331 lines
8.0 KiB
Go
331 lines
8.0 KiB
Go
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
|
|
}
|