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) }