|
|
@@ -4,28 +4,31 @@ import (
|
|
4
|
4
|
"encoding/json"
|
|
5
|
5
|
"net/http"
|
|
6
|
6
|
"reflect"
|
|
|
7
|
+ "strconv"
|
|
7
|
8
|
"strings"
|
|
|
9
|
+
|
|
|
10
|
+ "git.x2erp.com/qdy/go-base/ctx"
|
|
8
|
11
|
)
|
|
9
|
12
|
|
|
10
|
13
|
// WebService 路由服务
|
|
11
|
14
|
type WebService struct {
|
|
12
|
|
- router *http.ServeMux
|
|
|
15
|
+ router *http.ServeMux
|
|
|
16
|
+ middlewares []func(http.Handler) http.Handler
|
|
13
|
17
|
}
|
|
14
|
18
|
|
|
15
|
19
|
// NewWebService 创建WebService
|
|
16
|
20
|
func NewWebService(router *http.ServeMux) *WebService {
|
|
17
|
|
- return &WebService{router: router}
|
|
|
21
|
+ ws := &WebService{
|
|
|
22
|
+ router: router,
|
|
|
23
|
+ }
|
|
|
24
|
+
|
|
|
25
|
+ return ws
|
|
18
|
26
|
}
|
|
19
|
27
|
|
|
20
|
|
-// RouteBuilder 路由构建器
|
|
21
|
|
-type RouteBuilder struct {
|
|
22
|
|
- method string
|
|
23
|
|
- path string
|
|
24
|
|
- handlerFunc reflect.Value
|
|
25
|
|
- paramNames []string
|
|
26
|
|
- paramTypes []reflect.Type
|
|
27
|
|
- middlewares []func(http.Handler) http.Handler
|
|
28
|
|
- router *http.ServeMux
|
|
|
28
|
+// Use 添加全局中间件
|
|
|
29
|
+func (ws *WebService) Use(middleware func(http.Handler) http.Handler) *WebService {
|
|
|
30
|
+ ws.middlewares = append(ws.middlewares, middleware)
|
|
|
31
|
+ return ws
|
|
29
|
32
|
}
|
|
30
|
33
|
|
|
31
|
34
|
// GET 注册GET请求
|
|
|
@@ -62,60 +65,135 @@ func (ws *WebService) handle(method, path string, handler interface{}) *RouteBui
|
|
62
|
65
|
panic("handler must be a function")
|
|
63
|
66
|
}
|
|
64
|
67
|
|
|
65
|
|
- // 获取参数类型
|
|
66
|
|
- paramTypes := make([]reflect.Type, handlerType.NumIn())
|
|
67
|
|
- for i := 0; i < handlerType.NumIn(); i++ {
|
|
68
|
|
- paramTypes[i] = handlerType.In(i)
|
|
69
|
|
- }
|
|
70
|
|
-
|
|
71
|
68
|
// 验证返回值
|
|
72
|
69
|
if handlerType.NumOut() != 2 {
|
|
73
|
70
|
panic("handler must return exactly 2 values: (T, error)")
|
|
74
|
71
|
}
|
|
75
|
72
|
|
|
76
|
73
|
return &RouteBuilder{
|
|
|
74
|
+ ws: ws,
|
|
77
|
75
|
method: method,
|
|
78
|
76
|
path: path,
|
|
79
|
77
|
handlerFunc: handlerValue,
|
|
80
|
78
|
paramNames: paramNames,
|
|
81
|
|
- paramTypes: paramTypes,
|
|
82
|
|
- router: ws.router,
|
|
83
|
79
|
}
|
|
84
|
80
|
}
|
|
85
|
81
|
|
|
86
|
|
-// Use 添加中间件
|
|
|
82
|
+// // 上下文中间件
|
|
|
83
|
+// func (ws *WebService) contextMiddleware() func(http.Handler) http.Handler {
|
|
|
84
|
+// return func(next http.Handler) http.Handler {
|
|
|
85
|
+// return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
86
|
+// // 自动创建 RequestContext
|
|
|
87
|
+// reqCtx := ws.createRequestContext(r)
|
|
|
88
|
+
|
|
|
89
|
+// // 保存到请求中
|
|
|
90
|
+// r = ctx.SaveContext(r, *reqCtx)
|
|
|
91
|
+// next.ServeHTTP(w, r)
|
|
|
92
|
+// })
|
|
|
93
|
+// }
|
|
|
94
|
+// }
|
|
|
95
|
+
|
|
|
96
|
+// // 创建 RequestContext
|
|
|
97
|
+// func (ws *WebService) createRequestContext(r *http.Request) *ctx.RequestContext {
|
|
|
98
|
+// return &ctx.RequestContext{
|
|
|
99
|
+// TraceID: generateTraceID(),
|
|
|
100
|
+// ServiceName: getServiceName(r),
|
|
|
101
|
+// InstanceName: getInstanceName(),
|
|
|
102
|
+// TenantID: r.Header.Get("X-Tenant-ID"),
|
|
|
103
|
+// UserID: extractUserID(r),
|
|
|
104
|
+// }
|
|
|
105
|
+// }
|
|
|
106
|
+
|
|
|
107
|
+// // 辅助函数
|
|
|
108
|
+// func generateTraceID() string {
|
|
|
109
|
+// return "trace-" + strconv.FormatInt(time.Now().UnixNano(), 36)
|
|
|
110
|
+// }
|
|
|
111
|
+
|
|
|
112
|
+// func getServiceName(r *http.Request) string {
|
|
|
113
|
+// if serviceName := r.Header.Get("X-Service-Name"); serviceName != "" {
|
|
|
114
|
+// return serviceName
|
|
|
115
|
+// }
|
|
|
116
|
+// return "unknown-service"
|
|
|
117
|
+// }
|
|
|
118
|
+
|
|
|
119
|
+// func getInstanceName() string {
|
|
|
120
|
+// // 获取主机名
|
|
|
121
|
+// hostname, _ := os.Hostname()
|
|
|
122
|
+// if hostname != "" {
|
|
|
123
|
+// return hostname
|
|
|
124
|
+// }
|
|
|
125
|
+// return "instance-1"
|
|
|
126
|
+// }
|
|
|
127
|
+
|
|
|
128
|
+// func extractUserID(r *http.Request) string {
|
|
|
129
|
+// if auth := r.Header.Get("Authorization"); auth != "" {
|
|
|
130
|
+// // 简单示例:从 Authorization 头提取
|
|
|
131
|
+// if strings.HasPrefix(auth, "Bearer ") {
|
|
|
132
|
+// // 这里可以解析 JWT token 获取用户ID
|
|
|
133
|
+// // 暂时返回示例值
|
|
|
134
|
+// return "user-from-token"
|
|
|
135
|
+// }
|
|
|
136
|
+// }
|
|
|
137
|
+// return ""
|
|
|
138
|
+// }
|
|
|
139
|
+
|
|
|
140
|
+// RouteBuilder 路由构建器
|
|
|
141
|
+type RouteBuilder struct {
|
|
|
142
|
+ ws *WebService
|
|
|
143
|
+ method string
|
|
|
144
|
+ path string
|
|
|
145
|
+ handlerFunc reflect.Value
|
|
|
146
|
+ paramNames []string
|
|
|
147
|
+ middlewares []func(http.Handler) http.Handler
|
|
|
148
|
+ description string
|
|
|
149
|
+}
|
|
|
150
|
+
|
|
|
151
|
+// Use 添加路由级中间件
|
|
87
|
152
|
func (rb *RouteBuilder) Use(middleware ...func(http.Handler) http.Handler) *RouteBuilder {
|
|
88
|
153
|
rb.middlewares = append(rb.middlewares, middleware...)
|
|
89
|
154
|
return rb
|
|
90
|
155
|
}
|
|
91
|
156
|
|
|
|
157
|
+// Desc 添加描述
|
|
|
158
|
+func (rb *RouteBuilder) Desc(description string) *RouteBuilder {
|
|
|
159
|
+ rb.description = description
|
|
|
160
|
+ return rb
|
|
|
161
|
+}
|
|
|
162
|
+
|
|
92
|
163
|
// Register 注册路由
|
|
93
|
164
|
func (rb *RouteBuilder) Register() {
|
|
94
|
165
|
// 创建适配器
|
|
95
|
166
|
adapter := &handlerAdapter{
|
|
|
167
|
+ ws: rb.ws,
|
|
96
|
168
|
method: rb.method,
|
|
97
|
169
|
pathPattern: rb.path,
|
|
98
|
170
|
paramNames: rb.paramNames,
|
|
99
|
|
- paramTypes: rb.paramTypes,
|
|
100
|
171
|
handlerFunc: rb.handlerFunc,
|
|
101
|
172
|
}
|
|
102
|
173
|
|
|
103
|
|
- // 应用中间件
|
|
|
174
|
+ // 构建处理链:全局中间件 → 路由中间件 → 处理器
|
|
104
|
175
|
var handler http.Handler = adapter
|
|
|
176
|
+
|
|
|
177
|
+ // 1. 应用路由级中间件(从后往前)
|
|
105
|
178
|
for i := len(rb.middlewares) - 1; i >= 0; i-- {
|
|
106
|
179
|
handler = rb.middlewares[i](handler)
|
|
107
|
180
|
}
|
|
108
|
181
|
|
|
|
182
|
+ // 2. 应用全局中间件(从后往前)
|
|
|
183
|
+ for i := len(rb.ws.middlewares) - 1; i >= 0; i-- {
|
|
|
184
|
+ handler = rb.ws.middlewares[i](handler)
|
|
|
185
|
+ }
|
|
|
186
|
+
|
|
109
|
187
|
// 注册到路由器
|
|
110
|
|
- rb.router.Handle(rb.path, handler)
|
|
|
188
|
+ rb.ws.router.Handle(rb.path, handler)
|
|
111
|
189
|
}
|
|
112
|
190
|
|
|
113
|
191
|
// handlerAdapter 处理器适配器
|
|
114
|
192
|
type handlerAdapter struct {
|
|
|
193
|
+ ws *WebService
|
|
115
|
194
|
method string
|
|
116
|
195
|
pathPattern string
|
|
117
|
196
|
paramNames []string
|
|
118
|
|
- paramTypes []reflect.Type
|
|
119
|
197
|
handlerFunc reflect.Value
|
|
120
|
198
|
}
|
|
121
|
199
|
|
|
|
@@ -130,7 +208,7 @@ func (ha *handlerAdapter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
130
|
208
|
pathParams := ha.parsePathParams(r.URL.Path)
|
|
131
|
209
|
|
|
132
|
210
|
// 2. 构建函数参数
|
|
133
|
|
- args := ha.buildArgs(r, pathParams)
|
|
|
211
|
+ args := ha.buildArgs(w, r, pathParams)
|
|
134
|
212
|
if args == nil {
|
|
135
|
213
|
http.Error(w, "Invalid parameters", http.StatusBadRequest)
|
|
136
|
214
|
return
|
|
|
@@ -147,65 +225,263 @@ func (ha *handlerAdapter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
147
|
225
|
func (ha *handlerAdapter) parsePathParams(requestPath string) map[string]string {
|
|
148
|
226
|
params := make(map[string]string)
|
|
149
|
227
|
|
|
150
|
|
- // 简单实现:按/分割,然后匹配
|
|
151
|
|
- patternParts := strings.Split(ha.pathPattern, "/")
|
|
152
|
|
- requestParts := strings.Split(requestPath, "/")
|
|
|
228
|
+ pattern := strings.Trim(ha.pathPattern, "/")
|
|
|
229
|
+ request := strings.Trim(requestPath, "/")
|
|
153
|
230
|
|
|
154
|
|
- if len(patternParts) != len(requestParts) {
|
|
155
|
|
- return params
|
|
156
|
|
- }
|
|
|
231
|
+ patternParts := strings.Split(pattern, "/")
|
|
|
232
|
+ requestParts := strings.Split(request, "/")
|
|
157
|
233
|
|
|
158
|
234
|
for i, patternPart := range patternParts {
|
|
159
|
235
|
if strings.HasPrefix(patternPart, "{") && strings.HasSuffix(patternPart, "}") {
|
|
160
|
236
|
paramName := patternPart[1 : len(patternPart)-1]
|
|
161
|
|
- params[paramName] = requestParts[i]
|
|
|
237
|
+ if i < len(requestParts) {
|
|
|
238
|
+ params[paramName] = requestParts[i]
|
|
|
239
|
+ }
|
|
162
|
240
|
}
|
|
163
|
241
|
}
|
|
164
|
242
|
|
|
165
|
243
|
return params
|
|
166
|
244
|
}
|
|
|
245
|
+func (ha *handlerAdapter) buildArgs(w http.ResponseWriter, r *http.Request, pathParams map[string]string) []reflect.Value {
|
|
|
246
|
+ handlerType := ha.handlerFunc.Type()
|
|
|
247
|
+ numIn := handlerType.NumIn()
|
|
|
248
|
+ args := make([]reflect.Value, numIn)
|
|
|
249
|
+
|
|
|
250
|
+ for i := 0; i < numIn; i++ {
|
|
|
251
|
+ paramType := handlerType.In(i)
|
|
|
252
|
+ paramName := getParamName(i, handlerType, ha.paramNames)
|
|
|
253
|
+
|
|
|
254
|
+ // 1. 检查是否是特殊类型
|
|
|
255
|
+ if arg := ha.bindSpecialType(paramType, w, r); arg.IsValid() {
|
|
|
256
|
+ args[i] = arg
|
|
|
257
|
+ continue
|
|
|
258
|
+ }
|
|
167
|
259
|
|
|
168
|
|
-// buildArgs 构建函数参数
|
|
169
|
|
-func (ha *handlerAdapter) buildArgs(r *http.Request, pathParams map[string]string) []reflect.Value {
|
|
170
|
|
- args := make([]reflect.Value, len(ha.paramTypes))
|
|
|
260
|
+ // 2. 检查是否是 *ctx.RequestContext 类型
|
|
|
261
|
+ if paramType == reflect.TypeOf((*ctx.RequestContext)(nil)) {
|
|
|
262
|
+ reqCtx := ctx.GetContext(r)
|
|
|
263
|
+ args[i] = reflect.ValueOf(reqCtx)
|
|
|
264
|
+ continue
|
|
|
265
|
+ }
|
|
171
|
266
|
|
|
172
|
|
- // 参数索引
|
|
173
|
|
- pathParamIndex := 0
|
|
|
267
|
+ // 3. 只按名称匹配路径参数
|
|
|
268
|
+ if value, ok := pathParams[paramName]; ok {
|
|
|
269
|
+ args[i] = convertToType(value, paramType)
|
|
|
270
|
+ continue
|
|
|
271
|
+ }
|
|
174
|
272
|
|
|
175
|
|
- for i, paramType := range ha.paramTypes {
|
|
176
|
|
- // 情况1:路径参数(必须是string类型)
|
|
177
|
|
- if pathParamIndex < len(ha.paramNames) && paramType.Kind() == reflect.String {
|
|
178
|
|
- paramName := ha.paramNames[pathParamIndex]
|
|
179
|
|
- if value, ok := pathParams[paramName]; ok {
|
|
180
|
|
- args[i] = reflect.ValueOf(value)
|
|
181
|
|
- pathParamIndex++
|
|
182
|
|
- continue
|
|
183
|
|
- }
|
|
|
273
|
+ // 4. 尝试从查询参数获取
|
|
|
274
|
+ if queryValue := r.URL.Query().Get(paramName); queryValue != "" {
|
|
|
275
|
+ args[i] = convertToType(queryValue, paramType)
|
|
|
276
|
+ continue
|
|
184
|
277
|
}
|
|
185
|
278
|
|
|
186
|
|
- // 情况2:Body参数(POST/PUT等请求的结构体)
|
|
187
|
|
- if r.Method == "POST" || r.Method == "PUT" || r.Method == "PATCH" {
|
|
188
|
|
- // 检查是否是结构体类型
|
|
189
|
|
- if paramType.Kind() == reflect.Struct ||
|
|
190
|
|
- (paramType.Kind() == reflect.Ptr && paramType.Elem().Kind() == reflect.Struct) {
|
|
191
|
|
- bodyParam, err := ha.parseBody(r, paramType)
|
|
192
|
|
- if err != nil {
|
|
193
|
|
- return nil
|
|
194
|
|
- }
|
|
195
|
|
- args[i] = bodyParam
|
|
|
279
|
+ // 5. 尝试从JSON body获取(POST/PUT请求)
|
|
|
280
|
+ if (r.Method == "POST" || r.Method == "PUT" || r.Method == "PATCH") &&
|
|
|
281
|
+ (paramType.Kind() == reflect.Struct ||
|
|
|
282
|
+ (paramType.Kind() == reflect.Ptr && paramType.Elem().Kind() == reflect.Struct)) {
|
|
|
283
|
+ if arg := ha.parseBody(r, paramType); arg.IsValid() {
|
|
|
284
|
+ args[i] = arg
|
|
196
|
285
|
continue
|
|
197
|
286
|
}
|
|
198
|
287
|
}
|
|
199
|
288
|
|
|
200
|
|
- // 无法处理的参数类型
|
|
201
|
|
- return nil
|
|
|
289
|
+ // 6. 返回零值
|
|
|
290
|
+ args[i] = reflect.Zero(paramType)
|
|
202
|
291
|
}
|
|
203
|
292
|
|
|
204
|
293
|
return args
|
|
205
|
294
|
}
|
|
206
|
295
|
|
|
|
296
|
+// func (ha *handlerAdapter) buildArgs(w http.ResponseWriter, r *http.Request, pathParams map[string]string) []reflect.Value {
|
|
|
297
|
+// handlerType := ha.handlerFunc.Type()
|
|
|
298
|
+// numIn := handlerType.NumIn()
|
|
|
299
|
+// args := make([]reflect.Value, numIn)
|
|
|
300
|
+
|
|
|
301
|
+// // 收集所有 string 类型的参数索引
|
|
|
302
|
+// var stringParamIndices []int
|
|
|
303
|
+// for i := 0; i < numIn; i++ {
|
|
|
304
|
+// paramType := handlerType.In(i)
|
|
|
305
|
+// if paramType.Kind() == reflect.String &&
|
|
|
306
|
+// paramType != reflect.TypeOf((*ctx.RequestContext)(nil)) {
|
|
|
307
|
+// stringParamIndices = append(stringParamIndices, i)
|
|
|
308
|
+// }
|
|
|
309
|
+// }
|
|
|
310
|
+
|
|
|
311
|
+// // 处理每个参数
|
|
|
312
|
+// stringParamIndex := 0
|
|
|
313
|
+// for i := 0; i < numIn; i++ {
|
|
|
314
|
+// paramType := handlerType.In(i)
|
|
|
315
|
+// paramName := getParamName(i, handlerType, ha.paramNames)
|
|
|
316
|
+
|
|
|
317
|
+// // 1. 检查是否是特殊类型
|
|
|
318
|
+// if arg := ha.bindSpecialType(paramType, w, r); arg.IsValid() {
|
|
|
319
|
+// args[i] = arg
|
|
|
320
|
+// continue
|
|
|
321
|
+// }
|
|
|
322
|
+
|
|
|
323
|
+// // 2. 检查是否是 *ctx.RequestContext 类型
|
|
|
324
|
+// if paramType == reflect.TypeOf((*ctx.RequestContext)(nil)) {
|
|
|
325
|
+// reqCtx := ctx.GetContext(r)
|
|
|
326
|
+// args[i] = reflect.ValueOf(reqCtx)
|
|
|
327
|
+// continue
|
|
|
328
|
+// }
|
|
|
329
|
+
|
|
|
330
|
+// // 3. 处理路径参数
|
|
|
331
|
+// matched := false
|
|
|
332
|
+
|
|
|
333
|
+// // 如果有对应的路径参数名,直接匹配
|
|
|
334
|
+// if value, ok := pathParams[paramName]; ok && paramType.Kind() == reflect.String {
|
|
|
335
|
+// args[i] = convertToType(value, paramType)
|
|
|
336
|
+// matched = true
|
|
|
337
|
+// }
|
|
|
338
|
+
|
|
|
339
|
+// // 如果是 string 类型但没有匹配到名称,按顺序分配路径参数
|
|
|
340
|
+// if !matched && paramType.Kind() == reflect.String {
|
|
|
341
|
+// // 使用 stringParamIndices 中的位置来匹配 pathParamNames
|
|
|
342
|
+// if stringParamIndex < len(ha.paramNames) && stringParamIndex < len(stringParamIndices) {
|
|
|
343
|
+// paramName := ha.paramNames[stringParamIndex]
|
|
|
344
|
+// if value, ok := pathParams[paramName]; ok {
|
|
|
345
|
+// args[i] = convertToType(value, paramType)
|
|
|
346
|
+// matched = true
|
|
|
347
|
+// stringParamIndex++
|
|
|
348
|
+// }
|
|
|
349
|
+// }
|
|
|
350
|
+// }
|
|
|
351
|
+
|
|
|
352
|
+// if matched {
|
|
|
353
|
+// continue
|
|
|
354
|
+// }
|
|
|
355
|
+
|
|
|
356
|
+// // 4. 其他绑定逻辑...
|
|
|
357
|
+// // 查询参数、JSON body 等
|
|
|
358
|
+// }
|
|
|
359
|
+
|
|
|
360
|
+// return args
|
|
|
361
|
+// }
|
|
|
362
|
+
|
|
|
363
|
+// // buildArgs 构建函数参数
|
|
|
364
|
+// func (ha *handlerAdapter) buildArgs(w http.ResponseWriter, r *http.Request, pathParams map[string]string) []reflect.Value {
|
|
|
365
|
+// handlerType := ha.handlerFunc.Type()
|
|
|
366
|
+// numIn := handlerType.NumIn()
|
|
|
367
|
+// args := make([]reflect.Value, numIn)
|
|
|
368
|
+
|
|
|
369
|
+// for i := 0; i < numIn; i++ {
|
|
|
370
|
+// paramType := handlerType.In(i)
|
|
|
371
|
+// paramName := getParamName(i, handlerType, ha.paramNames)
|
|
|
372
|
+
|
|
|
373
|
+// // 1. 检查是否是特殊类型
|
|
|
374
|
+// if arg := ha.bindSpecialType(paramType, w, r); arg.IsValid() {
|
|
|
375
|
+// args[i] = arg
|
|
|
376
|
+// continue
|
|
|
377
|
+// }
|
|
|
378
|
+
|
|
|
379
|
+// // 2. 检查是否是 *ctx.RequestContext 类型
|
|
|
380
|
+// if paramType == reflect.TypeOf((*ctx.RequestContext)(nil)) {
|
|
|
381
|
+// reqCtx := ctx.GetContext(r)
|
|
|
382
|
+// if logger.IsDebug() {
|
|
|
383
|
+// logger.DebugC(reqCtx, "requestContext: %+v", reqCtx)
|
|
|
384
|
+// }
|
|
|
385
|
+// args[i] = reflect.ValueOf(reqCtx)
|
|
|
386
|
+// continue
|
|
|
387
|
+// }
|
|
|
388
|
+
|
|
|
389
|
+// // 3. 尝试从路径参数获取
|
|
|
390
|
+// if value, ok := pathParams[paramName]; ok {
|
|
|
391
|
+// if arg := convertToType(value, paramType); arg.IsValid() {
|
|
|
392
|
+// args[i] = arg
|
|
|
393
|
+// continue
|
|
|
394
|
+// }
|
|
|
395
|
+// }
|
|
|
396
|
+
|
|
|
397
|
+// // 4. 尝试从查询参数获取
|
|
|
398
|
+// if queryValue := r.URL.Query().Get(paramName); queryValue != "" {
|
|
|
399
|
+// if arg := convertToType(queryValue, paramType); arg.IsValid() {
|
|
|
400
|
+// args[i] = arg
|
|
|
401
|
+// continue
|
|
|
402
|
+// }
|
|
|
403
|
+// }
|
|
|
404
|
+
|
|
|
405
|
+// // 5. 尝试从JSON body获取
|
|
|
406
|
+// if (r.Method == "POST" || r.Method == "PUT" || r.Method == "PATCH") &&
|
|
|
407
|
+// (paramType.Kind() == reflect.Struct ||
|
|
|
408
|
+// (paramType.Kind() == reflect.Ptr && paramType.Elem().Kind() == reflect.Struct)) {
|
|
|
409
|
+// if arg := ha.parseBody(r, paramType); arg.IsValid() {
|
|
|
410
|
+// args[i] = arg
|
|
|
411
|
+// continue
|
|
|
412
|
+// }
|
|
|
413
|
+// }
|
|
|
414
|
+
|
|
|
415
|
+// // 6. 返回零值
|
|
|
416
|
+// args[i] = reflect.Zero(paramType)
|
|
|
417
|
+// }
|
|
|
418
|
+
|
|
|
419
|
+// return args
|
|
|
420
|
+// }
|
|
|
421
|
+
|
|
|
422
|
+// bindSpecialType 绑定特殊类型
|
|
|
423
|
+func (ha *handlerAdapter) bindSpecialType(paramType reflect.Type, w http.ResponseWriter, r *http.Request) reflect.Value {
|
|
|
424
|
+ switch paramType {
|
|
|
425
|
+ case reflect.TypeOf((*http.ResponseWriter)(nil)).Elem():
|
|
|
426
|
+ return reflect.ValueOf(w)
|
|
|
427
|
+ case reflect.TypeOf((*http.Request)(nil)):
|
|
|
428
|
+ return reflect.ValueOf(r)
|
|
|
429
|
+ }
|
|
|
430
|
+ return reflect.Value{}
|
|
|
431
|
+}
|
|
|
432
|
+
|
|
|
433
|
+// getParamName 获取参数名
|
|
|
434
|
+func getParamName(index int, handlerType reflect.Type, pathParamNames []string) string {
|
|
|
435
|
+ // 如果有路径参数名,优先使用
|
|
|
436
|
+ if index < len(pathParamNames) {
|
|
|
437
|
+ return pathParamNames[index]
|
|
|
438
|
+ }
|
|
|
439
|
+
|
|
|
440
|
+ // 使用类型名的蛇形格式
|
|
|
441
|
+ paramType := handlerType.In(index)
|
|
|
442
|
+ typeName := paramType.Name()
|
|
|
443
|
+ if typeName == "" {
|
|
|
444
|
+ return strconv.Itoa(index)
|
|
|
445
|
+ }
|
|
|
446
|
+
|
|
|
447
|
+ // 转换为蛇形格式:MyInterface -> my_interface
|
|
|
448
|
+ var result []rune
|
|
|
449
|
+ for i, r := range typeName {
|
|
|
450
|
+ if i > 0 && 'A' <= r && r <= 'Z' {
|
|
|
451
|
+ result = append(result, '_')
|
|
|
452
|
+ }
|
|
|
453
|
+ result = append(result, r)
|
|
|
454
|
+ }
|
|
|
455
|
+ return strings.ToLower(string(result))
|
|
|
456
|
+}
|
|
|
457
|
+
|
|
|
458
|
+// convertToType 字符串转换为指定类型
|
|
|
459
|
+func convertToType(str string, targetType reflect.Type) reflect.Value {
|
|
|
460
|
+ switch targetType.Kind() {
|
|
|
461
|
+ case reflect.String:
|
|
|
462
|
+ return reflect.ValueOf(str)
|
|
|
463
|
+ case reflect.Int:
|
|
|
464
|
+ if i, err := strconv.Atoi(str); err == nil {
|
|
|
465
|
+ return reflect.ValueOf(i)
|
|
|
466
|
+ }
|
|
|
467
|
+ case reflect.Int64:
|
|
|
468
|
+ if i, err := strconv.ParseInt(str, 10, 64); err == nil {
|
|
|
469
|
+ return reflect.ValueOf(i)
|
|
|
470
|
+ }
|
|
|
471
|
+ case reflect.Bool:
|
|
|
472
|
+ if b, err := strconv.ParseBool(str); err == nil {
|
|
|
473
|
+ return reflect.ValueOf(b)
|
|
|
474
|
+ }
|
|
|
475
|
+ case reflect.Float64:
|
|
|
476
|
+ if f, err := strconv.ParseFloat(str, 64); err == nil {
|
|
|
477
|
+ return reflect.ValueOf(f)
|
|
|
478
|
+ }
|
|
|
479
|
+ }
|
|
|
480
|
+ return reflect.Value{}
|
|
|
481
|
+}
|
|
|
482
|
+
|
|
207
|
483
|
// parseBody 解析请求体
|
|
208
|
|
-func (ha *handlerAdapter) parseBody(r *http.Request, paramType reflect.Type) (reflect.Value, error) {
|
|
|
484
|
+func (ha *handlerAdapter) parseBody(r *http.Request, paramType reflect.Type) reflect.Value {
|
|
209
|
485
|
// 创建参数实例
|
|
210
|
486
|
var paramValue reflect.Value
|
|
211
|
487
|
if paramType.Kind() == reflect.Ptr {
|
|
|
@@ -216,15 +492,16 @@ func (ha *handlerAdapter) parseBody(r *http.Request, paramType reflect.Type) (re
|
|
216
|
492
|
|
|
217
|
493
|
// 解析JSON
|
|
218
|
494
|
if err := json.NewDecoder(r.Body).Decode(paramValue.Interface()); err != nil {
|
|
219
|
|
- return reflect.Value{}, err
|
|
|
495
|
+ return reflect.Value{}
|
|
220
|
496
|
}
|
|
|
497
|
+ defer r.Body.Close()
|
|
221
|
498
|
|
|
222
|
499
|
// 如果是非指针类型,需要解引用
|
|
223
|
500
|
if paramType.Kind() != reflect.Ptr {
|
|
224
|
501
|
paramValue = paramValue.Elem()
|
|
225
|
502
|
}
|
|
226
|
503
|
|
|
227
|
|
- return paramValue, nil
|
|
|
504
|
+ return paramValue
|
|
228
|
505
|
}
|
|
229
|
506
|
|
|
230
|
507
|
// handleResponse 处理响应
|
|
|
@@ -248,7 +525,7 @@ func (ha *handlerAdapter) handleResponse(w http.ResponseWriter, results []reflec
|
|
248
|
525
|
// extractPathParams 从路径中提取参数名
|
|
249
|
526
|
func extractPathParams(path string) []string {
|
|
250
|
527
|
var params []string
|
|
251
|
|
- parts := strings.Split(path, "/")
|
|
|
528
|
+ parts := strings.Split(strings.Trim(path, "/"), "/")
|
|
252
|
529
|
|
|
253
|
530
|
for _, part := range parts {
|
|
254
|
531
|
if strings.HasPrefix(part, "{") && strings.HasSuffix(part, "}") {
|