Skip to content

Commit 749a073

Browse files
authored
Merge pull request #9 from sunjunnan79/main
feat:删除对rounter的封装,添加更多类型的响应封装
2 parents ecd3cf4 + 3004687 commit 749a073

3 files changed

Lines changed: 9 additions & 207 deletions

File tree

pkg/transport/http/ginx/handler/handler.go

Lines changed: 8 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -31,46 +31,6 @@ func Bind(ctx *gin.Context, req any) error {
3131
return nil
3232
}
3333

34-
// WrapReq 。用于处理有请求体的请求
35-
// ctx表示上下文,req表示请求结构体
36-
func WrapReq[Req any](fn func(*gin.Context, Req)) gin.HandlerFunc {
37-
return func(ctx *gin.Context) {
38-
//检查前置中间件是否存在错误,如果存在应当直接返回
39-
if len(ctx.Errors) > 0 {
40-
return
41-
}
42-
//解析参数
43-
var req Req
44-
err := Bind(ctx, &req)
45-
if err != nil {
46-
HandleResponse(ctx, t_http.Response{
47-
HttpCode: http.StatusBadRequest,
48-
Code: DefaultBindErrCode,
49-
Message: "非法的参数: " + err.Error(),
50-
Data: nil,
51-
})
52-
return
53-
}
54-
// 调用业务逻辑函数
55-
fn(ctx, req)
56-
return
57-
}
58-
}
59-
60-
// Wrap 。用于处理没有请求体的请求
61-
// ctx表示上下文
62-
func Wrap(fn func(*gin.Context)) gin.HandlerFunc {
63-
return func(ctx *gin.Context) {
64-
//检查前置中间件是否存在错误,如果存在应当直接返回
65-
if len(ctx.Errors) > 0 {
66-
return
67-
}
68-
// 调用业务逻辑函数
69-
fn(ctx)
70-
return
71-
}
72-
}
73-
7434
// HandleResponse 处理需要自定义业务码的请求
7535
func HandleResponse(ctx *gin.Context, resp t_http.Response) {
7636
finalResp := t_http.FinalResp{
@@ -91,3 +51,11 @@ func HandleSuccessResponseWithData(ctx *gin.Context, data any) {
9151
Data: data,
9252
})
9353
}
54+
55+
// HandleSuccessResponse 快速处理成功响应
56+
func HandleSuccessResponse(ctx *gin.Context) {
57+
HandleResponse(ctx, t_http.Response{
58+
Code: http.StatusOK,
59+
Message: "success",
60+
})
61+
}
Lines changed: 0 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -1,126 +1 @@
11
package handler
2-
3-
import (
4-
"bytes"
5-
"encoding/json"
6-
"errors"
7-
"net/http"
8-
"net/http/httptest"
9-
"testing"
10-
11-
"github.com/gin-gonic/gin"
12-
t_http "github.com/muxi-Infra/muxi-micro/pkg/transport/http"
13-
"github.com/stretchr/testify/assert"
14-
)
15-
16-
type demoReq struct {
17-
Name string `json:"name" form:"name" binding:"required"`
18-
}
19-
20-
func handleDemoReq(c *gin.Context, r demoReq) {
21-
HandleResponse(c, t_http.Response{
22-
HttpCode: http.StatusOK,
23-
Code: 0,
24-
Message: "ok",
25-
Data: r,
26-
})
27-
}
28-
29-
func handleNoBody(c *gin.Context) {
30-
HandleResponse(c, t_http.Response{
31-
HttpCode: http.StatusOK,
32-
Code: 0,
33-
Message: "pong",
34-
})
35-
}
36-
37-
func decodeResp[T any](body []byte) (T, error) {
38-
var resp t_http.FinalResp
39-
var t T
40-
err := json.Unmarshal(body, &resp)
41-
if err != nil {
42-
return t, err
43-
}
44-
db, _ := json.Marshal(resp.Data)
45-
err = json.Unmarshal(db, &t)
46-
return t, err
47-
}
48-
49-
func setErrorHandlerFunc() gin.HandlerFunc {
50-
return func(c *gin.Context) {
51-
c.Error(errors.New("test"))
52-
}
53-
}
54-
55-
func TestWrapReq(t *testing.T) {
56-
gin.SetMode(gin.TestMode)
57-
g := gin.New()
58-
g.POST("/demo", WrapReq(handleDemoReq))
59-
60-
tests := []struct {
61-
name string
62-
body string
63-
status int
64-
expect string
65-
}{
66-
{"非法参数", `{"foo":"bar"}`, http.StatusBadRequest, ""},
67-
{"正常参数", `{"name":"bar"}`, http.StatusOK, "bar"},
68-
}
69-
70-
for _, tt := range tests {
71-
t.Run(tt.name, func(t *testing.T) {
72-
w := httptest.NewRecorder()
73-
req, _ := http.NewRequest(http.MethodPost, "/demo", bytes.NewBufferString(tt.body))
74-
req.Header.Set("Content-Type", "application/json")
75-
g.ServeHTTP(w, req)
76-
77-
assert.Equal(t, tt.status, w.Code)
78-
if tt.status == http.StatusOK {
79-
res, err := decodeResp[demoReq](w.Body.Bytes())
80-
assert.NoError(t, err)
81-
assert.Equal(t, tt.expect, res.Name)
82-
}
83-
})
84-
}
85-
86-
t.Run("error in front Middleware", func(t *testing.T) {
87-
g.GET("/testFrontError", setErrorHandlerFunc(), WrapReq(handleDemoReq))
88-
w := httptest.NewRecorder()
89-
req, _ := http.NewRequest(http.MethodGet, "/testFrontError", bytes.NewBufferString("{\"name\":\"bar\"}"))
90-
req.Header.Set("Content-Type", "application/json")
91-
g.ServeHTTP(w, req)
92-
93-
assert.Equal(t, http.StatusOK, w.Code)
94-
95-
})
96-
}
97-
98-
func TestWrap(t *testing.T) {
99-
gin.SetMode(gin.TestMode)
100-
g := gin.New()
101-
102-
t.Run("请求正常", func(t *testing.T) {
103-
g.GET("/ping", Wrap(handleNoBody))
104-
105-
w := httptest.NewRecorder()
106-
req, _ := http.NewRequest(http.MethodGet, "/ping", nil)
107-
g.ServeHTTP(w, req)
108-
109-
assert.Equal(t, http.StatusOK, w.Code)
110-
var resp t_http.FinalResp
111-
_ = json.Unmarshal(w.Body.Bytes(), &resp)
112-
assert.Equal(t, "pong", resp.Message)
113-
})
114-
115-
t.Run("error in front Middleware", func(t *testing.T) {
116-
g.GET("/testFrontError", setErrorHandlerFunc(), Wrap(handleNoBody))
117-
w := httptest.NewRecorder()
118-
req, _ := http.NewRequest(http.MethodGet, "/testFrontError", bytes.NewBufferString("{\"name\":\"bar\"}"))
119-
req.Header.Set("Content-Type", "application/json")
120-
g.ServeHTTP(w, req)
121-
122-
assert.Equal(t, http.StatusOK, w.Code)
123-
124-
})
125-
126-
}

tool/gin/example/main.go

Lines changed: 1 addition & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,17 @@
11
package main
22

33
import (
4+
"github.com/gin-gonic/gin"
45
"github.com/muxi-Infra/muxi-micro/pkg/transport/http/ginx/engine"
5-
"github.com/muxi-Infra/muxi-micro/pkg/transport/http/ginx/handler"
66
"github.com/muxi-Infra/muxi-micro/static"
7-
"net/http"
8-
9-
"github.com/gin-gonic/gin"
10-
t_http "github.com/muxi-Infra/muxi-micro/pkg/transport/http"
117
)
128

13-
// 定义请求和响应结构体
14-
type LoginRequest struct {
15-
Username string `json:"username" binding:"required"`
16-
Password string `json:"password" binding:"required"`
17-
}
18-
199
func main() {
2010
g := gin.Default()
2111
engine.UseDefaultMiddleware(g)
2212
router := engine.NewEngine(
2313
engine.WithEnv(static.EnvDev),
2414
)
2515

26-
// 1. 注册不需要请求体
27-
router.GET("/ping", handler.Wrap(func(ctx *gin.Context) {
28-
29-
handler.HandleResponse(ctx, t_http.Response{
30-
HttpCode: http.StatusOK,
31-
Code: 0,
32-
Message: "pong",
33-
Data: nil,
34-
})
35-
}))
36-
37-
// 2. 注册需要请求体
38-
router.POST("/login", handler.WrapReq(func(ctx *gin.Context, req LoginRequest) {
39-
// 模拟登录逻辑
40-
if req.Username == "admin" && req.Password == "123456" {
41-
handler.HandleResponse(ctx, t_http.Response{
42-
HttpCode: http.StatusOK,
43-
Message: "登录成功",
44-
Data: "token-string",
45-
})
46-
return
47-
}
48-
handler.HandleResponse(ctx, t_http.Response{
49-
HttpCode: http.StatusUnauthorized,
50-
Code: 40100,
51-
Message: "用户名或密码错误",
52-
Data: nil,
53-
})
54-
return
55-
}))
56-
5716
router.Run("0.0.0.0:8080")
5817
}

0 commit comments

Comments
 (0)