Files
go-common/http/handler.go

280 lines
6.3 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 (
"context"
"encoding/json"
"io"
"net/http"
"strconv"
"git.toowon.com/jimmy/go-common/middleware"
)
// Handler HTTP处理器包装器封装ResponseWriter和Request提供简洁的API
type Handler struct {
w http.ResponseWriter
r *http.Request
}
// NewHandler 创建Handler实例
func NewHandler(w http.ResponseWriter, r *http.Request) *Handler {
return &Handler{
w: w,
r: r,
}
}
// ResponseWriter 获取原始的ResponseWriter需要时使用
func (h *Handler) ResponseWriter() http.ResponseWriter {
return h.w
}
// Request 获取原始的Request需要时使用
func (h *Handler) Request() *http.Request {
return h.r
}
// Context 获取请求的Context
func (h *Handler) Context() context.Context {
return h.r.Context()
}
// ========== 响应方法(黑盒模式) ==========
// Success 成功响应
// data: 响应数据可以为nil
func (h *Handler) Success(data interface{}) {
writeJSON(h.w, http.StatusOK, 0, "success", data)
}
// SuccessWithMessage 带消息的成功响应
func (h *Handler) SuccessWithMessage(message string, data interface{}) {
writeJSON(h.w, http.StatusOK, 0, message, data)
}
// Error 错误响应
// code: 业务错误码非0表示业务错误
// message: 错误消息
func (h *Handler) Error(code int, message string) {
writeJSON(h.w, http.StatusOK, code, message, nil)
}
// SystemError 系统错误响应返回HTTP 500
// message: 错误消息
func (h *Handler) SystemError(message string) {
writeJSON(h.w, http.StatusInternalServerError, 500, message, nil)
}
// WriteJSON 写入JSON响应自定义HTTP状态码和业务状态码
// httpCode: HTTP状态码200表示正常500表示系统错误等
// code: 业务状态码0表示成功非0表示业务错误
// message: 响应消息
// data: 响应数据
func (h *Handler) WriteJSON(httpCode, code int, message string, data interface{}) {
writeJSON(h.w, httpCode, code, message, data)
}
// SuccessPage 分页成功响应
// list: 数据列表
// total: 总记录数
// page: 当前页码
// pageSize: 每页大小
// message: 响应消息(可选,如果为空则使用默认消息 "success"
func (h *Handler) SuccessPage(list interface{}, total int64, page, pageSize int, message ...string) {
msg := "success"
if len(message) > 0 && message[0] != "" {
msg = message[0]
}
pageData := &PageData{
List: list,
Total: total,
Page: page,
PageSize: pageSize,
}
writeJSON(h.w, http.StatusOK, 0, msg, pageData)
}
// ========== 请求解析方法(黑盒模式) ==========
// ParseJSON 解析JSON请求体
// v: 目标结构体指针
func (h *Handler) ParseJSON(v interface{}) error {
body, err := io.ReadAll(h.r.Body)
if err != nil {
return err
}
defer h.r.Body.Close()
if len(body) == 0 {
return nil
}
return json.Unmarshal(body, v)
}
// GetQuery 获取查询参数
// key: 参数名
// defaultValue: 默认值
func (h *Handler) GetQuery(key, defaultValue string) string {
value := h.r.URL.Query().Get(key)
if value == "" {
return defaultValue
}
return value
}
// GetQueryInt 获取整数查询参数
// key: 参数名
// defaultValue: 默认值
func (h *Handler) GetQueryInt(key string, defaultValue int) int {
value := h.r.URL.Query().Get(key)
if value == "" {
return defaultValue
}
intValue, err := strconv.Atoi(value)
if err != nil {
return defaultValue
}
return intValue
}
// GetQueryInt64 获取int64查询参数
func (h *Handler) GetQueryInt64(key string, defaultValue int64) int64 {
value := h.r.URL.Query().Get(key)
if value == "" {
return defaultValue
}
intValue, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return defaultValue
}
return intValue
}
// GetQueryBool 获取布尔查询参数
func (h *Handler) GetQueryBool(key string, defaultValue bool) bool {
value := h.r.URL.Query().Get(key)
if value == "" {
return defaultValue
}
boolValue, err := strconv.ParseBool(value)
if err != nil {
return defaultValue
}
return boolValue
}
// GetQueryFloat64 获取float64查询参数
func (h *Handler) GetQueryFloat64(key string, defaultValue float64) float64 {
value := h.r.URL.Query().Get(key)
if value == "" {
return defaultValue
}
floatValue, err := strconv.ParseFloat(value, 64)
if err != nil {
return defaultValue
}
return floatValue
}
// GetFormValue 获取表单值
func (h *Handler) GetFormValue(key, defaultValue string) string {
value := h.r.FormValue(key)
if value == "" {
return defaultValue
}
return value
}
// GetFormInt 获取表单整数
func (h *Handler) GetFormInt(key string, defaultValue int) int {
value := h.r.FormValue(key)
if value == "" {
return defaultValue
}
intValue, err := strconv.Atoi(value)
if err != nil {
return defaultValue
}
return intValue
}
// GetFormInt64 获取表单int64
func (h *Handler) GetFormInt64(key string, defaultValue int64) int64 {
value := h.r.FormValue(key)
if value == "" {
return defaultValue
}
intValue, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return defaultValue
}
return intValue
}
// GetFormBool 获取表单布尔值
func (h *Handler) GetFormBool(key string, defaultValue bool) bool {
value := h.r.FormValue(key)
if value == "" {
return defaultValue
}
boolValue, err := strconv.ParseBool(value)
if err != nil {
return defaultValue
}
return boolValue
}
// GetHeader 获取请求头
func (h *Handler) GetHeader(key, defaultValue string) string {
value := h.r.Header.Get(key)
if value == "" {
return defaultValue
}
return value
}
// ParsePaginationRequest 从请求中解析分页参数
// 支持从查询参数和form表单中解析
// 优先级:查询参数 > form表单
func (h *Handler) ParsePaginationRequest() *PaginationRequest {
return ParsePaginationRequest(h.r)
}
// GetTimezone 从请求的context中获取时区
// 如果使用了middleware.Timezone中间件可以从context中获取时区信息
// 如果未设置,返回默认时区 AsiaShanghai
func (h *Handler) GetTimezone() string {
return middleware.GetTimezoneFromContext(h.r.Context())
}
// HandleFunc 将Handler函数转换为标准的http.HandlerFunc
// 这样可以将Handler函数直接用于http.HandleFunc
// 示例:
//
// http.HandleFunc("/users", http.HandleFunc(func(h *http.Handler) {
// h.Success(data)
// }))
func HandleFunc(fn func(*Handler)) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
h := NewHandler(w, r)
fn(h)
}
}