115 lines
2.0 KiB
Go
115 lines
2.0 KiB
Go
package httputil
|
||
|
||
import (
|
||
"encoding/json"
|
||
"errors"
|
||
"io"
|
||
"net"
|
||
"net/http"
|
||
"net/url"
|
||
"server/internal/config"
|
||
"server/internal/model/common"
|
||
"server/internal/pkg/errs"
|
||
"server/internal/pkg/validator"
|
||
"strconv"
|
||
"strings"
|
||
|
||
"github.com/go-chi/chi/v5"
|
||
)
|
||
|
||
// Pagination 分页请求参数
|
||
func Pagination(r *http.Request) *common.Pagination {
|
||
q := r.URL.Query()
|
||
|
||
// page 默认 1
|
||
page := int32(1)
|
||
if p := q.Get("page"); p != "" {
|
||
if v, err := strconv.Atoi(p); err == nil && v >= 1 {
|
||
page = int32(v)
|
||
}
|
||
}
|
||
|
||
// pageSize 默认 10
|
||
pageSize := int32(10)
|
||
if ps := q.Get("page_size"); ps != "" {
|
||
if v, err := strconv.Atoi(ps); err == nil && v >= 1 && v <= 100 {
|
||
pageSize = int32(v)
|
||
}
|
||
}
|
||
|
||
return &common.Pagination{
|
||
Page: page,
|
||
PageSize: pageSize,
|
||
}
|
||
}
|
||
|
||
func URLParamInt32(r *http.Request, key string) (int32, error) {
|
||
v := chi.URLParam(r, key)
|
||
|
||
if v == "" {
|
||
return 0, errs.ErrIDRequired
|
||
}
|
||
|
||
n, err := strconv.ParseInt(v, 10, 32)
|
||
if err != nil {
|
||
return 0, errs.ErrInvalidID
|
||
}
|
||
|
||
return int32(n), nil
|
||
}
|
||
|
||
func BindJson(r *http.Request, dest any) error {
|
||
if err := json.NewDecoder(r.Body).Decode(dest); err != nil {
|
||
if errors.Is(err, io.EOF) {
|
||
return errs.ErrEmptyBody
|
||
}
|
||
return errs.ErrInvalidJSON
|
||
}
|
||
|
||
if err := validator.Struct(dest); err != nil {
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// ClientIP 获取客户端 IP,依次从 X-Forwarded-For、X-Real-IP、RemoteAddr 取值
|
||
func ClientIP(r *http.Request) string {
|
||
if xff := r.Header.Get("X-Forwarded-For"); xff != "" {
|
||
parts := strings.Split(xff, ",")
|
||
if len(parts) > 0 {
|
||
return strings.TrimSpace(parts[0])
|
||
}
|
||
}
|
||
|
||
if ip := r.Header.Get("X-Real-IP"); ip != "" {
|
||
return ip
|
||
}
|
||
|
||
// RemoteAddr: IP:port
|
||
host, _, err := net.SplitHostPort(r.RemoteAddr)
|
||
if err == nil {
|
||
return host
|
||
}
|
||
|
||
return r.RemoteAddr
|
||
}
|
||
|
||
func BuildFileUrl(path *string) string {
|
||
if path == nil || *path == "" {
|
||
return ""
|
||
}
|
||
|
||
baseURL := config.GetString("file.base_url")
|
||
if baseURL == "" {
|
||
return ""
|
||
}
|
||
|
||
result, err := url.JoinPath(baseURL, *path)
|
||
if err != nil {
|
||
return ""
|
||
}
|
||
|
||
return result
|
||
}
|