diff --git a/.gitignore b/.gitignore index c7a3858..437bebe 100644 --- a/.gitignore +++ b/.gitignore @@ -78,3 +78,4 @@ $RECYCLE.BIN/ *.code-workspace vendor/ +.idea diff --git a/core/README.md b/core/README.md index f8f786c..c0ce02f 100644 --- a/core/README.md +++ b/core/README.md @@ -21,30 +21,96 @@ go get -u github.com/TencentBlueKing/bk-apigateway-sdks/core@latest | bkapi.*ResultProvider | 结构 | 提供响应体反序列化封装的接口 | json.go | ### 快速使用 -以下基于 [demo](./demo/) 包中的示例: +以下基于 [demo](../demo/) 包中的部分示例(具体见: [example.go](../demo/example.go)): ```golang +package demo + import ( "fmt" + "log" + "github.com/TencentBlueKing/bk-apigateway-sdks/core/bkapi" - "github.com/TencentBlueKing/bk-apigateway-sdks/demo" + "github.com/TencentBlueKing/bk-apigateway-sdks/core/define" ) -// 创建客户端,并声明所有结果都使用 Json 格式 -client, _ := demo.New(bkapi.ClientConfig{ - Endpoint: "https://httpbin.org/", -}, bkapi.OptJsonResultProvider()) +type QueryUserDemoBodyRequest struct { + Name string `json:"name"` + Age int `json:"age"` +} -// 创建结果变量 -var result demo.AnythingResponse +type QueryUserDemoResponse struct { + Name string `json:"name"` + Age int `json:"age"` + Address string `json:"address"` + Gender string `json:"gender"` +} -// 调用接口 -_, _ = client.Anything(). - SetResult(&result). - Request() +func clientExample() { -// 结果将自动填充到 result 中 -fmt.Printf("%#v", result) + // 初始化client + + client, err := bkapi.NewBkApiClient("demo", bkapi.ClientConfig{ + Endpoint: "http://special-api.example.com/prod",// 具体某个网关地址 + ClientOptions: []define.BkApiClientOption{ + // 设置一些通用的client配置,eg: + bkapi.OptSetRequestHeader("X-Api-Key", "123456"),// 设置统一的header + bkapi.OptJsonResultProvider(),// 声明这个网关的所有响应都是JSON + bkapi.OptJsonBodyProvider(), // 声明这个网关的body请求都是JSON + }, + }) + if err != nil { + log.Printf("client init error: %v", err) + return + } + + + + // 创建 api operation + apiOperation := client.NewOperation( + // 填充接口配置 + bkapi.OperationConfig{ + Name: "query_team_user_demo", + Method: "GET", + Path: "/get/{team_id}/user/", + }, + // 设置header参数 + bkapi.OptSetRequestHeader("X-Bkapi-Header", "demo"), + // 设置path参数 + bkapi.OptSetRequestPathParams( + map[string]string{ + "team_id": `1`, + }, + ), + // 设置query参数 + bkapi.OptSetRequestQueryParam("name", "demo"), + // 设置body参数: 自定义struct + bkapi.OptSetRequestBody(QueryUserDemoBodyRequest{Name: "demo"}), + // 设置body参数: map[string]string + bkapi.OptSetRequestBody(map[string]string{"name": "demo"}), + ) + + // 创建结果变量 + var result QueryUserDemoResponse + + // 调用接口(Request()的返回值是:*http.Response,err,看具体情况是否需要处理) + + //// 直接通过 api operation传参 + //_,_=apiOperation.SetHeaders(map[string]string{"X-Bkapi-Header": "demo"}). + // SetPathParams(map[string]string{"team_id": `1`}). + // SetBody(QueryUserDemoBodyRequest{Name: "demo"}). + // SetQueryParams(map[string]string{"name": "demo"}). + // SetResult(&result).Request() + + //_, _ = client.StatusCode(bkapi.OptSetRequestQueryParams(map[string]string{ + // "code": `200`, + //})).SetResult(&result).Request() + + _, _ = apiOperation.SetResult(&result).Request() + // 结果将自动填充到 result 中 + fmt.Printf("%#v", result) + +} ``` ## 进阶用法 @@ -58,23 +124,51 @@ fmt.Printf("%#v", result) 可以使用 `ClientConfigRegistry` 简化每次初始化客户端时都需要传递网关地址,认证信息等重复性工作,`ClientConfigRegistry` 本身已实现成 `ClientConfigProvider`,可直接替代 `ClientConfig` 来使用: ```golang -// 获取默认的配置中心 -registry := bkapi.GetGlobalClientConfigRegistry() +// 通过ClientConfigRegistry初始化client -// 注册默认的配置(不区分网关) -registry.RegisterDefaultConfig(bkapi.ClientConfig{ - BkApiUrlTmpl: "http://{api_name}.example.com/", - Stage: "prod", -}) +// 使用默认的全局的配置中心来初始化 +registry: = bkapi.GetGlobalClientConfigRegistry() -// 注册指定网关配置 -registry.RegisterDefaultConfig("my-gateway", bkapi.ClientConfig{ - Endpoint: "http://special-api.example.com/", - ClientOptions: []define.BkApiClientOption{bkapi.OptJsonResultProvider()}, // 声明这个网关的所有响应都是 JSON +// 方式一:注册默认的配置(不区分网关) +err: = registry.RegisterDefaultConfig(bkapi.ClientConfig { + BkApiUrlTmpl: "http://{api_name}.example.com/", //网关通用地址 + Stage: "prod", }) +if err != nil { + log.Printf("registry default config error: %v", err) + return +} +// 使用默认的配置,在创建client的时候再指定网关 +client, err: = bkapi.NewBkApiClient("my-gateway", registry) +if err != nil { + log.Fatalf("create bkapi client error: %v", err) + return +} -// 可直接使用配置中心来初始化客户端 -client, _ := New(registry) + + +// 方式二:注册指定的网关配置 +err = registry.RegisterClientConfig("my-gateway", bkapi.ClientConfig { + Endpoint: "http://special-api.example.com/prod", // 具体某个网关地址 + ClientOptions: [] define.BkApiClientOption { + // 设置一些通用的client配置,eg: + bkapi.OptSetRequestHeader("X-Api-Key", "123456"), // 设置统一的header + bkapi.OptJsonResultProvider(), // 声明这个网关的所有响应都是JSON + bkapi.OptJsonBodyProvider(), // 声明这个网关的body请求都是JSON + }, + }) + +if err != nil { + log.Fatalf("set bkapi client config error: %v", err) + return +} + + +client, err = bkapi.NewBkApiClient("my-gateway", registry) +if err != nil { + log.Fatalf("create bkapi client error: %v", err) + return +} ``` ### Prometheus 指标 @@ -118,6 +212,48 @@ Operation 表示一个网关资源封装,方法定义: | Apply | 增加额外选项 | | Request | 发送请求 | + +```go +// 创建 api operation +apiOperation := client.NewOperation( + // 填充接口配置 + bkapi.OperationConfig{ + Name: "query_team_user_demo", + Method: "GET", + Path: "/get/{team_id}/user/", + }, + // 设置header参数 + bkapi.OptSetRequestHeader("X-Bkapi-Header", "demo"), + // 设置path参数 + bkapi.OptSetRequestPathParams( + map[string]string{ + "team_id": `1`, + }, + ), + // 设置query参数 + bkapi.OptSetRequestQueryParam("name", "demo"), + // 设置body参数: 自定义struct + bkapi.OptSetRequestBody(QueryUserDemoBodyRequest{Name: "demo"}), + // 设置body参数: map[string]string + bkapi.OptSetRequestBody(map[string]string{"name": "demo"}), +) + +// 创建结果变量 +var result QueryUserDemoResponse + +// 调用接口(Request()的返回值是:*http.Response,err,看具体情况是否需要处理) + +//// 直接通过 api operation传参 +//_,_=apiOperation.SetHeaders(map[string]string{"X-Bkapi-Header": "demo"}). +// SetPathParams(map[string]string{"team_id": `1`}). +// SetBody(QueryUserDemoBodyRequest{Name: "demo"}). +// SetQueryParams(map[string]string{"name": "demo"}). +// SetResult(&result).Request() + +_, _ = apiOperation.SetResult(&result).Request() +// 结果将自动填充到 result 中 +fmt.Printf("%#v", result) +``` ### 客户端封装 BkApiClient 表示一个网关封装,方法定义: diff --git a/demo/example.go b/demo/example.go new file mode 100644 index 0000000..f413ca1 --- /dev/null +++ b/demo/example.go @@ -0,0 +1,122 @@ +package demo + +import ( + "fmt" + "log" + + "github.com/TencentBlueKing/bk-apigateway-sdks/core/bkapi" + "github.com/TencentBlueKing/bk-apigateway-sdks/core/define" +) + +type QueryUserDemoBodyRequest struct { + Name string `json:"name"` + Age int `json:"age"` +} + +type QueryUserDemoResponse struct { + Name string `json:"name"` + Age int `json:"age"` + Address string `json:"address"` + Gender string `json:"gender"` +} + +func clientExample() { + + // 初始化client + + // 使用默认的全局的注册配置来初始化 + registry := bkapi.GetGlobalClientConfigRegistry() + + // 方式一:注册默认的配置(不区分网关) + err := registry.RegisterDefaultConfig(bkapi.ClientConfig{ + BkApiUrlTmpl: "http://{api_name}.example.com/", //网关通用地址 + Stage: "prod", + }) + if err != nil { + log.Printf("registry default config error: %v", err) + return + } + // 使用默认的配置,在创建client的时候再指定网关 + client, err := bkapi.NewBkApiClient("my-gateway", registry) + if err != nil { + log.Fatalf("create bkapi client error: %v", err) + return + } + + // 方式二:注册指定的网关配置 + err = registry.RegisterClientConfig("my-gateway", bkapi.ClientConfig{ + Endpoint: "http://special-api.example.com/prod", // 具体某个网关地址 + ClientOptions: []define.BkApiClientOption{ + // 设置一些通用的client配置,eg: + bkapi.OptJsonResultProvider(), // 声明这个网关的所有响应都是JSON + bkapi.OptJsonBodyProvider(), // 声明这个网关的body请求都是JSON + bkapi.OptSetRequestHeader("X-Api-Key", "123456"), // 设置统一的header + }, + }) + if err != nil { + log.Fatalf("set bkapi client config error: %v", err) + return + } + + client, err = bkapi.NewBkApiClient("my-gateway", registry) + if err != nil { + log.Fatalf("create bkapi client error: %v", err) + return + } + + // 直接使用自定义的配置来创建 + client, err = bkapi.NewBkApiClient("demo", bkapi.ClientConfig{ + Endpoint: "http://special-api.example.com/prod", // 具体某个网关地址 + ClientOptions: []define.BkApiClientOption{ + // 设置一些通用的client配置,eg: + bkapi.OptJsonResultProvider(), // 声明这个网关的所有响应都是JSON + bkapi.OptJsonBodyProvider(), // 声明这个网关的body请求都是JSON + bkapi.OptSetRequestHeader("X-Api-Key", "123456"), // 设置统一的header + }, + }) + if err != nil { + log.Printf("client init error: %v", err) + return + } + + // 创建 api operation + apiOperation := client.NewOperation( + // 填充接口配置 + bkapi.OperationConfig{ + Name: "query_team_user_demo", + Method: "GET", + Path: "/get/{team_id}/user/", + }, + // 设置header参数 + bkapi.OptSetRequestHeader("X-Bkapi-Header", "demo"), + // 设置path参数 + bkapi.OptSetRequestPathParams( + map[string]string{ + "team_id": `1`, + }, + ), + // 设置query参数 + bkapi.OptSetRequestQueryParam("name", "demo"), + // 设置body参数: 自定义struct + bkapi.OptSetRequestBody(QueryUserDemoBodyRequest{Name: "demo"}), + // 设置body参数: map[string]string + bkapi.OptSetRequestBody(map[string]string{"name": "demo"}), + ) + + // 创建结果变量 + var result QueryUserDemoResponse + + // 调用接口(Request()的返回值是:*http.Response,err,看具体情况是否需要处理) + + //// 直接通过 api operation传参 + //_,_=apiOperation.SetHeaders(map[string]string{"X-Bkapi-Header": "demo"}). + // SetPathParams(map[string]string{"team_id": `1`}). + // SetBody(QueryUserDemoBodyRequest{Name: "demo"}). + // SetQueryParams(map[string]string{"name": "demo"}). + // SetResult(&result).Request() + + _, _ = apiOperation.SetResult(&result).Request() + // 结果将自动填充到 result 中 + fmt.Printf("%#v", result) + +}