Files
go-common/http/request.go
2025-12-07 01:09:52 +08:00

339 lines
7.9 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package http
import (
"encoding/json"
"io"
"net/http"
"strconv"
"git.toowon.com/jimmy/go-common/middleware"
)
// getQueryInt 获取整数查询参数内部方法供ParsePaginationRequest使用
func getQueryInt(r *http.Request, key string, defaultValue int) int {
value := r.URL.Query().Get(key)
if value == "" {
return defaultValue
}
intValue, err := strconv.Atoi(value)
if err != nil {
return defaultValue
}
return intValue
}
// getFormInt 获取表单整数内部方法供ParsePaginationRequest使用
func getFormInt(r *http.Request, key string, defaultValue int) int {
value := r.FormValue(key)
if value == "" {
return defaultValue
}
intValue, err := strconv.Atoi(value)
if err != nil {
return defaultValue
}
return intValue
}
// PaginationRequest 分页请求结构
// 支持从JSON和form中解析分页参数
type PaginationRequest struct {
Page int `json:"page" form:"page"` // 页码默认1
Size int `json:"size" form:"size"` // 每页数量(兼容旧版本)
PageSize int `json:"page_size" form:"page_size"` // 每页数量(推荐使用)
Keyword string `json:"keyword" form:"keyword"` // 关键字
}
// GetPage 获取页码如果未设置则返回默认值1
func (p *PaginationRequest) GetPage() int {
if p.Page <= 0 {
return 1
}
return p.Page
}
// GetSize 获取每页数量如果未设置则返回默认值20最大限制100
// 优先使用 PageSize 字段,如果未设置则使用 Size 字段(兼容旧版本)
func (p *PaginationRequest) GetSize() int {
size := p.PageSize
if size <= 0 {
size = p.Size // 兼容旧版本的 Size 字段
}
if size <= 0 {
return 20 // 默认20条
}
if size > 100 {
return 100 // 最大100条
}
return size
}
// GetOffset 计算数据库查询的偏移量
func (p *PaginationRequest) GetOffset() int {
return (p.GetPage() - 1) * p.GetSize()
}
// getPaginationFromQuery 从查询参数获取分页参数(内部辅助方法)
func getPaginationFromQuery(r *http.Request) (page, size, pageSize int) {
page = getQueryInt(r, "page", 0)
size = getQueryInt(r, "size", 0)
pageSize = getQueryInt(r, "page_size", 0)
return
}
// getPaginationFromForm 从form表单获取分页参数内部辅助方法
func getPaginationFromForm(r *http.Request) (page, size, pageSize int) {
page = getFormInt(r, "page", 0)
size = getFormInt(r, "size", 0)
pageSize = getFormInt(r, "page_size", 0)
return
}
// ParsePaginationRequest 从请求中解析分页参数
// 支持从查询参数和form表单中解析
// 优先级:查询参数 > form表单
// 注意如果请求体是JSON格式且包含分页字段建议先使用ParseJSON解析完整请求体到包含PaginationRequest的结构体中
func ParsePaginationRequest(r *http.Request) *PaginationRequest {
req := &PaginationRequest{}
// 1. 从查询参数解析(优先级最高)
req.Page, req.Size, req.PageSize = getPaginationFromQuery(r)
// 2. 如果查询参数中没有尝试从form表单解析
if req.Page == 0 || (req.Size == 0 && req.PageSize == 0) {
page, size, pageSize := getPaginationFromForm(r)
if req.Page == 0 && page != 0 {
req.Page = page
}
if req.Size == 0 && size != 0 {
req.Size = size
}
if req.PageSize == 0 && pageSize != 0 {
req.PageSize = pageSize
}
}
return req
}
// ========== 请求解析公共方法 ==========
// ParseJSON 解析JSON请求体公共方法
// r: HTTP请求
// v: 目标结构体指针
func ParseJSON(r *http.Request, v interface{}) error {
body, err := io.ReadAll(r.Body)
if err != nil {
return err
}
defer r.Body.Close()
if len(body) == 0 {
return nil
}
return json.Unmarshal(body, v)
}
// GetQuery 获取查询参数(公共方法)
// r: HTTP请求
// key: 参数名
// defaultValue: 默认值
func GetQuery(r *http.Request, key, defaultValue string) string {
value := r.URL.Query().Get(key)
if value == "" {
return defaultValue
}
return value
}
// GetQueryInt 获取整数查询参数(公共方法)
// r: HTTP请求
// key: 参数名
// defaultValue: 默认值
func GetQueryInt(r *http.Request, key string, defaultValue int) int {
value := r.URL.Query().Get(key)
if value == "" {
return defaultValue
}
intValue, err := strconv.Atoi(value)
if err != nil {
return defaultValue
}
return intValue
}
// GetQueryInt64 获取int64查询参数公共方法
// r: HTTP请求
// key: 参数名
// defaultValue: 默认值
func GetQueryInt64(r *http.Request, key string, defaultValue int64) int64 {
value := r.URL.Query().Get(key)
if value == "" {
return defaultValue
}
intValue, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return defaultValue
}
return intValue
}
// GetQueryBool 获取布尔查询参数(公共方法)
// r: HTTP请求
// key: 参数名
// defaultValue: 默认值
func GetQueryBool(r *http.Request, key string, defaultValue bool) bool {
value := r.URL.Query().Get(key)
if value == "" {
return defaultValue
}
boolValue, err := strconv.ParseBool(value)
if err != nil {
return defaultValue
}
return boolValue
}
// GetQueryFloat64 获取float64查询参数公共方法
// r: HTTP请求
// key: 参数名
// defaultValue: 默认值
func GetQueryFloat64(r *http.Request, key string, defaultValue float64) float64 {
value := r.URL.Query().Get(key)
if value == "" {
return defaultValue
}
floatValue, err := strconv.ParseFloat(value, 64)
if err != nil {
return defaultValue
}
return floatValue
}
func GetQueryUint64(r *http.Request, key string, defaultValue uint64) uint64 {
value := r.URL.Query().Get(key)
if value == "" {
return defaultValue
}
uintValue, err := strconv.ParseUint(value, 10, 64)
if err != nil {
return defaultValue
}
return uintValue
}
func GetQueryUint32(r *http.Request, key string, defaultValue uint32) uint32 {
value := r.URL.Query().Get(key)
if value == "" {
return defaultValue
}
uintValue, err := strconv.ParseUint(value, 10, 32)
if err != nil {
return defaultValue
}
return uint32(uintValue)
}
// GetFormValue 获取表单值(公共方法)
// r: HTTP请求
// key: 参数名
// defaultValue: 默认值
func GetFormValue(r *http.Request, key, defaultValue string) string {
value := r.FormValue(key)
if value == "" {
return defaultValue
}
return value
}
// GetFormInt 获取表单整数(公共方法)
// r: HTTP请求
// key: 参数名
// defaultValue: 默认值
func GetFormInt(r *http.Request, key string, defaultValue int) int {
value := r.FormValue(key)
if value == "" {
return defaultValue
}
intValue, err := strconv.Atoi(value)
if err != nil {
return defaultValue
}
return intValue
}
// GetFormInt64 获取表单int64公共方法
// r: HTTP请求
// key: 参数名
// defaultValue: 默认值
func GetFormInt64(r *http.Request, key string, defaultValue int64) int64 {
value := r.FormValue(key)
if value == "" {
return defaultValue
}
intValue, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return defaultValue
}
return intValue
}
// GetFormBool 获取表单布尔值(公共方法)
// r: HTTP请求
// key: 参数名
// defaultValue: 默认值
func GetFormBool(r *http.Request, key string, defaultValue bool) bool {
value := r.FormValue(key)
if value == "" {
return defaultValue
}
boolValue, err := strconv.ParseBool(value)
if err != nil {
return defaultValue
}
return boolValue
}
// GetHeader 获取请求头(公共方法)
// r: HTTP请求
// key: 请求头名称
// defaultValue: 默认值
func GetHeader(r *http.Request, key, defaultValue string) string {
value := r.Header.Get(key)
if value == "" {
return defaultValue
}
return value
}
// GetTimezone 从请求的context中获取时区公共方法
// r: HTTP请求
// 如果使用了middleware.Timezone中间件可以从context中获取时区信息
// 如果未设置,返回默认时区 AsiaShanghai
func GetTimezone(r *http.Request) string {
return middleware.GetTimezoneFromContext(r.Context())
}