@@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"io"
"net/http"
"reflect"
"regexp"
@@ -69,10 +70,10 @@ func SkipMiddleware(h func(r *ghttp.Request), path string) (handler ghttp.Handle
}
func RouteRegister ( controllers [ ] interface { } ) {
//Httpserver.Group("/log", func(group *ghttp.RouterGroup) {
// group.Middleware(jaeger.NewTracer)
// group.Bind(controller.OperationLog)
//})
Httpserver . Group ( "/log" , func ( group * ghttp . RouterGroup ) {
group . Middleware ( jaeger . NewTracer )
//group.Bind(controller.OperationLog)
} )
re := regexp . MustCompile ( "[A-Z]" )
for _ , t := range controllers {
sName := reflect . ValueOf ( t ) . Elem ( ) . Type ( ) . Name ( )
@@ -80,19 +81,15 @@ func RouteRegister(controllers []interface{}) {
return fmt . Sprintf ( "/%s" , strings . ToLower ( s ) )
} )
Httpserver . Group ( convertedStr , func ( group * ghttp . RouterGroup ) {
group . Middleware ( jaeger . NewTracer )
group . Bind ( t )
} )
}
go Httpserver . Run ( )
}
// doRequest 统一HTTP请求处理(DELETE用ContentJson发送body, gconv.Struct增加err检查)
func doRequest ( ctx context . Context , method string , url string , headers map [ string ] string , target any , data ... any ) ( err error ) {
err = utils . ValidStructPtr ( target )
if err != nil {
return
}
// doRequestRaw 执行HTTP请求,返回gclient.Response,调用方需自行Close
// 统一处理:client克隆、ContentJson设置、请求头注入、GET查询参数转换
func doRequestRaw ( ctx context . Context , method string , url string , headers map [ string ] string , data ... any ) ( * gclient . Response , error ) {
client := Httpclient . Clone ( )
// POST/PUT/DELETE请求都需要显式用ContentJson序列化body
@@ -110,9 +107,9 @@ func doRequest(ctx context.Context, method string, url string, headers map[strin
// 修复:避免data...展开导致的双重包装问题
// 当只有一个元素时,直接传递该元素,避免被包装成数组
var response * gclient . Response
var err error
// 对于GET请求,将参数转换为map
if method == http . MethodGet && len ( data ) > 0 && len ( data ) % 2 == 0 {
// 构建query参数map
queryParams := make ( map [ string ] string )
for i := 0 ; i < len ( data ) ; i += 2 {
if key , ok := data [ i ] . ( string ) ; ok && i + 1 < len ( data ) {
@@ -126,17 +123,33 @@ func doRequest(ctx context.Context, method string, url string, headers map[strin
} else {
response , err = client . DoRequest ( ctx , method , url , data ... )
}
return response , err
}
// doRequest 统一HTTP请求处理(同步/异步,解析内部API响应格式并填充target)
func doRequest ( ctx context . Context , method string , url string , headers map [ string ] string , target any , respParse bool , data ... any ) ( res [ ] byte , err error ) {
if target != nil || respParse {
err = utils . ValidStructPtr ( target )
if err != nil {
return
}
}
response , err := doRequestRaw ( ctx , method , url , headers , data ... )
if err != nil {
return
}
defer response . Close ( )
result := response . ReadAll ( )
if ! respParse {
return result , nil
}
// 统一处理内部API响应格式:{code:200,message:"",data:{...}}
resultStrut := & ghttp . DefaultHandlerResponse { }
if err = gconv . Struct ( result , & resultStrut ) ; err != nil { // 修复:增加err检查
return errors . New ( "响应解析失败: " + err . Error ( ) )
return nil , errors . New ( "响应解析失败: " + err . Error ( ) )
}
// 添加调试日志:打印解析后的结构
@@ -145,7 +158,7 @@ func doRequest(ctx context.Context, method string, url string, headers map[strin
if resultStrut . Code == 200 || resultStrut . Code == 0 {
if err = gconv . Struct ( resultStrut . Data , target ) ; err != nil { // 修复:增加err检查
return errors . New ( "数据解析失败: " + err . Error ( ) )
return nil , errors . New ( "数据解析失败: " + err . Error ( ) )
}
// 添加调试日志:打印最终的target
g . Log ( ) . Debugf ( ctx , "[HTTP] 最终target: %+v" , target )
@@ -154,19 +167,52 @@ func doRequest(ctx context.Context, method string, url string, headers map[strin
}
return
}
func Get ( ctx context . Context , url string , headers map [ string ] string , target any , data ... any ) ( err error ) {
err = doRequest ( ctx , http . MethodGet , url , headers , target , data ... )
_ , err = doRequest ( ctx , http . MethodGet , url , headers , target , true , data ... )
return
}
func Post ( ctx context . Context , url string , headers map [ string ] string , target any , data ... any ) ( err error ) {
err = doRequest ( ctx , http . MethodPost , url , headers , target , data ... )
_ , err = doRequest ( ctx , http . MethodPost , url , headers , target , true , data ... )
return
}
func Put ( ctx context . Context , url string , headers map [ string ] string , target any , data ... any ) ( err error ) {
err = doRequest ( ctx , http . MethodPut , url , headers , target , data ... )
_ , err = doRequest ( ctx , http . MethodPut , url , headers , target , true , data ... )
return
}
func Delete ( ctx context . Context , url string , headers map [ string ] string , target any , data ... any ) ( err error ) {
err = doRequest ( ctx , http . MethodDelete , url , headers , target , data ... )
_ , err = doRequest ( ctx , http . MethodDelete , url , headers , target , true , data ... )
return
}
func GetNotParse ( ctx context . Context , url string , headers map [ string ] string , data ... any ) ( res [ ] byte , err error ) {
res , err = doRequest ( ctx , http . MethodGet , url , headers , nil , false , data ... )
return
}
func PostNotParse ( ctx context . Context , url string , headers map [ string ] string , data ... any ) ( res [ ] byte , err error ) {
res , err = doRequest ( ctx , http . MethodPost , url , headers , nil , false , data ... )
return
}
// DoStream 流式HTTP请求,返回响应体io.ReadCloser,由调用方自行控制读取和关闭
// 注意:返回的是原始响应流,不会解析内部API响应格式,调用方必须在使用后Close
func doStream ( ctx context . Context , method string , url string , headers map [ string ] string , data ... any ) ( io . ReadCloser , error ) {
response , err := doRequestRaw ( ctx , method , url , headers , data ... )
if err != nil {
return nil , err
}
// 检查HTTP状态码,提前返回错误
if response . StatusCode < 200 || response . StatusCode >= 300 {
bodyBytes , _ := io . ReadAll ( response . Body )
response . Close ( )
return nil , fmt . Errorf ( "[HTTP][Stream] 状态码异常: %d, body=%s" , response . StatusCode , string ( bodyBytes ) )
}
return response . Body , nil
}
// PostStream POST流式请求,返回响应体io.ReadCloser
func PostStream ( ctx context . Context , url string , headers map [ string ] string , data ... any ) ( io . ReadCloser , error ) {
return doStream ( ctx , http . MethodPost , url , headers , data ... )
}