Nenhuma descrição
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

web_binder.go 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. package webx
  2. import (
  3. "context"
  4. "encoding/json"
  5. "net/http"
  6. "reflect"
  7. "strconv"
  8. "strings"
  9. )
  10. // invokeHandler 调用处理器函数
  11. func (rb *routeBuilder) invokeHandler(ctx context.Context, w http.ResponseWriter, req *http.Request) {
  12. handlerType := reflect.TypeOf(rb.handler)
  13. handlerValue := reflect.ValueOf(rb.handler)
  14. // 获取参数数量
  15. numIn := handlerType.NumIn()
  16. args := make([]reflect.Value, numIn)
  17. // 绑定每个参数
  18. for i := 0; i < numIn; i++ {
  19. paramType := handlerType.In(i)
  20. args[i] = rb.bindParam(i, paramType, ctx, w, req)
  21. }
  22. // 调用处理器函数
  23. results := handlerValue.Call(args)
  24. // 处理返回值
  25. rb.handleResults(results, w)
  26. }
  27. // bindParam 绑定单个参数
  28. func (rb *routeBuilder) bindParam(index int, paramType reflect.Type, ctx context.Context, w http.ResponseWriter, req *http.Request) reflect.Value {
  29. // 特殊类型绑定
  30. switch paramType {
  31. case reflect.TypeOf((*http.ResponseWriter)(nil)).Elem():
  32. return reflect.ValueOf(w)
  33. case reflect.TypeOf((*http.Request)(nil)):
  34. return reflect.ValueOf(req)
  35. case reflect.TypeOf((*context.Context)(nil)).Elem():
  36. return reflect.ValueOf(ctx)
  37. }
  38. // 基本类型 - 尝试从路径参数绑定
  39. if paramType.Kind() == reflect.String || paramType.Kind() == reflect.Int || paramType.Kind() == reflect.Int64 {
  40. // 尝试从路径中提取参数
  41. if pathParam := extractPathParam(rb.path, req.URL.Path, index); pathParam != "" {
  42. return convertToType(pathParam, paramType)
  43. }
  44. // 尝试从查询参数绑定
  45. if queryParam := extractQueryParam(paramType.Name(), req); queryParam != "" {
  46. return convertToType(queryParam, paramType)
  47. }
  48. }
  49. // 结构体 - 从 JSON 请求体绑定
  50. if paramType.Kind() == reflect.Struct || (paramType.Kind() == reflect.Ptr && paramType.Elem().Kind() == reflect.Struct) {
  51. return rb.bindFromJSON(paramType, req)
  52. }
  53. // 返回零值
  54. return reflect.Zero(paramType)
  55. }
  56. // extractPathParam 从路径提取参数
  57. func extractPathParam(pattern, actualPath string, index int) string {
  58. patternParts := strings.Split(strings.Trim(pattern, "/"), "/")
  59. actualParts := strings.Split(strings.Trim(actualPath, "/"), "/")
  60. for i, part := range patternParts {
  61. if strings.HasPrefix(part, "{") && strings.HasSuffix(part, "}") {
  62. if i < len(actualParts) {
  63. return actualParts[i]
  64. }
  65. }
  66. }
  67. // 如果路径中没有参数,尝试最后一个部分
  68. if len(actualParts) > 0 {
  69. return actualParts[len(actualParts)-1]
  70. }
  71. return ""
  72. }
  73. // extractQueryParam 从查询参数提取
  74. func extractQueryParam(paramName string, req *http.Request) string {
  75. // 转换为小写查找
  76. key := strings.ToLower(paramName)
  77. return req.URL.Query().Get(key)
  78. }
  79. // bindFromJSON 从 JSON 绑定
  80. func (rb *routeBuilder) bindFromJSON(paramType reflect.Type, req *http.Request) reflect.Value {
  81. var val reflect.Value
  82. if paramType.Kind() == reflect.Ptr {
  83. val = reflect.New(paramType.Elem())
  84. } else {
  85. val = reflect.New(paramType)
  86. }
  87. if req.Body != nil {
  88. defer req.Body.Close()
  89. json.NewDecoder(req.Body).Decode(val.Interface())
  90. }
  91. if paramType.Kind() == reflect.Ptr {
  92. return val
  93. }
  94. return val.Elem()
  95. }
  96. // convertToType 字符串转换为指定类型
  97. func convertToType(str string, targetType reflect.Type) reflect.Value {
  98. switch targetType.Kind() {
  99. case reflect.String:
  100. return reflect.ValueOf(str)
  101. case reflect.Int:
  102. if i, err := strconv.Atoi(str); err == nil {
  103. return reflect.ValueOf(i)
  104. }
  105. case reflect.Int64:
  106. if i, err := strconv.ParseInt(str, 10, 64); err == nil {
  107. return reflect.ValueOf(i)
  108. }
  109. case reflect.Bool:
  110. if b, err := strconv.ParseBool(str); err == nil {
  111. return reflect.ValueOf(b)
  112. }
  113. }
  114. return reflect.Zero(targetType)
  115. }
  116. // handleResults 处理返回值
  117. func (rb *routeBuilder) handleResults(results []reflect.Value, w http.ResponseWriter) {
  118. if len(results) == 0 {
  119. return
  120. }
  121. // 第一个返回值处理
  122. firstResult := results[0].Interface()
  123. // 如果是错误
  124. if err, ok := firstResult.(error); ok {
  125. w.WriteHeader(http.StatusInternalServerError)
  126. json.NewEncoder(w).Encode(map[string]interface{}{
  127. "error": err.Error(),
  128. })
  129. return
  130. }
  131. // 如果是其他类型,返回 JSON
  132. w.Header().Set("Content-Type", "application/json")
  133. json.NewEncoder(w).Encode(firstResult)
  134. }