| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- package webx
-
- import (
- "context"
- "encoding/json"
- "net/http"
- "reflect"
- "strconv"
- "strings"
- )
-
- // invokeHandler 调用处理器函数
- func (rb *routeBuilder) invokeHandler(ctx context.Context, w http.ResponseWriter, req *http.Request) {
- handlerType := reflect.TypeOf(rb.handler)
- handlerValue := reflect.ValueOf(rb.handler)
-
- // 获取参数数量
- numIn := handlerType.NumIn()
- args := make([]reflect.Value, numIn)
-
- // 绑定每个参数
- for i := 0; i < numIn; i++ {
- paramType := handlerType.In(i)
- args[i] = rb.bindParam(i, paramType, ctx, w, req)
- }
-
- // 调用处理器函数
- results := handlerValue.Call(args)
-
- // 处理返回值
- rb.handleResults(results, w)
- }
-
- // bindParam 绑定单个参数
- func (rb *routeBuilder) bindParam(index int, paramType reflect.Type, ctx context.Context, w http.ResponseWriter, req *http.Request) reflect.Value {
- // 特殊类型绑定
- switch paramType {
- case reflect.TypeOf((*http.ResponseWriter)(nil)).Elem():
- return reflect.ValueOf(w)
- case reflect.TypeOf((*http.Request)(nil)):
- return reflect.ValueOf(req)
- case reflect.TypeOf((*context.Context)(nil)).Elem():
- return reflect.ValueOf(ctx)
- }
-
- // 基本类型 - 尝试从路径参数绑定
- if paramType.Kind() == reflect.String || paramType.Kind() == reflect.Int || paramType.Kind() == reflect.Int64 {
- // 尝试从路径中提取参数
- if pathParam := extractPathParam(rb.path, req.URL.Path, index); pathParam != "" {
- return convertToType(pathParam, paramType)
- }
-
- // 尝试从查询参数绑定
- if queryParam := extractQueryParam(paramType.Name(), req); queryParam != "" {
- return convertToType(queryParam, paramType)
- }
- }
-
- // 结构体 - 从 JSON 请求体绑定
- if paramType.Kind() == reflect.Struct || (paramType.Kind() == reflect.Ptr && paramType.Elem().Kind() == reflect.Struct) {
- return rb.bindFromJSON(paramType, req)
- }
-
- // 返回零值
- return reflect.Zero(paramType)
- }
-
- // extractPathParam 从路径提取参数
- func extractPathParam(pattern, actualPath string, index int) string {
- patternParts := strings.Split(strings.Trim(pattern, "/"), "/")
- actualParts := strings.Split(strings.Trim(actualPath, "/"), "/")
-
- for i, part := range patternParts {
- if strings.HasPrefix(part, "{") && strings.HasSuffix(part, "}") {
- if i < len(actualParts) {
- return actualParts[i]
- }
- }
- }
-
- // 如果路径中没有参数,尝试最后一个部分
- if len(actualParts) > 0 {
- return actualParts[len(actualParts)-1]
- }
-
- return ""
- }
-
- // extractQueryParam 从查询参数提取
- func extractQueryParam(paramName string, req *http.Request) string {
- // 转换为小写查找
- key := strings.ToLower(paramName)
- return req.URL.Query().Get(key)
- }
-
- // bindFromJSON 从 JSON 绑定
- func (rb *routeBuilder) bindFromJSON(paramType reflect.Type, req *http.Request) reflect.Value {
- var val reflect.Value
-
- if paramType.Kind() == reflect.Ptr {
- val = reflect.New(paramType.Elem())
- } else {
- val = reflect.New(paramType)
- }
-
- if req.Body != nil {
- defer req.Body.Close()
- json.NewDecoder(req.Body).Decode(val.Interface())
- }
-
- if paramType.Kind() == reflect.Ptr {
- return val
- }
- return val.Elem()
- }
-
- // convertToType 字符串转换为指定类型
- func convertToType(str string, targetType reflect.Type) reflect.Value {
- switch targetType.Kind() {
- case reflect.String:
- return reflect.ValueOf(str)
- case reflect.Int:
- if i, err := strconv.Atoi(str); err == nil {
- return reflect.ValueOf(i)
- }
- case reflect.Int64:
- if i, err := strconv.ParseInt(str, 10, 64); err == nil {
- return reflect.ValueOf(i)
- }
- case reflect.Bool:
- if b, err := strconv.ParseBool(str); err == nil {
- return reflect.ValueOf(b)
- }
- }
- return reflect.Zero(targetType)
- }
-
- // handleResults 处理返回值
- func (rb *routeBuilder) handleResults(results []reflect.Value, w http.ResponseWriter) {
- if len(results) == 0 {
- return
- }
-
- // 第一个返回值处理
- firstResult := results[0].Interface()
-
- // 如果是错误
- if err, ok := firstResult.(error); ok {
- w.WriteHeader(http.StatusInternalServerError)
- json.NewEncoder(w).Encode(map[string]interface{}{
- "error": err.Error(),
- })
- return
- }
-
- // 如果是其他类型,返回 JSON
- w.Header().Set("Content-Type", "application/json")
- json.NewEncoder(w).Encode(firstResult)
- }
|