客户端添加切换租户

This commit is contained in:
cn-kali-team
2026-04-29 18:57:00 +08:00
committed by lyingbug
parent b3898eb101
commit 1e170793b3
4 changed files with 103 additions and 2 deletions
+21 -1
View File
@@ -23,7 +23,7 @@
```go
import (
"context"
"github.com/Tencent/WeKnora/internal/client"
"github.com/Tencent/WeKnora/client"
"time"
)
@@ -35,6 +35,26 @@ apiClient := client.NewClient(
)
```
### 租户配置
客户端支持通过 `WithTenantID` 设置默认租户,请求时会自动携带 `X-Tenant-ID` 请求头:
```go
tenantID := uint64(10000)
apiClient := client.NewClient(
"http://api.example.com",
client.WithToken("your-auth-token"),
client.WithTenantID(tenantID),
)
```
如果某个请求需要临时切换租户,可以在 `context` 中设置 `TenantID`,值可以是 `uint64`、`*uint64` 或字符串形式的数字,客户端会优先使用该值:
```go
ctx := context.WithValue(context.Background(), "TenantID", uint64(10000))
// 调用任意客户端方法时传入 ctx,即可切换到租户 10000
```
### 示例:创建知识库并上传文件
```go
+21 -1
View File
@@ -23,7 +23,7 @@ The client includes the following main functional modules:
```go
import (
"context"
"github.com/Tencent/WeKnora/internal/client"
"github.com/Tencent/WeKnora/client"
"time"
)
@@ -35,6 +35,26 @@ apiClient := client.NewClient(
)
```
### Tenant Configuration
You can set a default tenant with `WithTenantID`; the client will automatically send the `X-Tenant-ID` header:
```go
tenantID := uint64(10000)
apiClient := client.NewClient(
"http://api.example.com",
client.WithToken("your-auth-token"),
client.WithTenantID(tenantID),
)
```
If a single request needs a different tenant, set `TenantID` in the request context. The value can be a `uint64`, `*uint64`, or a numeric string, and it will take precedence over the client default:
```go
ctx := context.WithValue(context.Background(), "TenantID", uint64(10000))
// Pass ctx into any client method to switch to tenant 10000 for that request
```
### Example: Create Knowledge Base and Upload File
```go
+54
View File
@@ -10,6 +10,7 @@ import (
"io"
"net/http"
"net/url"
"strconv"
"time"
)
@@ -18,6 +19,7 @@ type Client struct {
baseURL string
httpClient *http.Client
token string
tenantID *uint64
}
// ClientOption defines client configuration options
@@ -37,6 +39,14 @@ func WithToken(token string) ClientOption {
}
}
// WithTenantID sets the tenant ID that will be included in requests as the X-Tenant-ID header.
// It can be overridden per-request by setting the "TenantID" value in the request context.
func WithTenantID(tenantID uint64) ClientOption {
return func(c *Client) {
c.tenantID = &tenantID
}
}
// NewClient creates a new client instance
func NewClient(baseURL string, options ...ClientOption) *Client {
client := &Client{
@@ -84,6 +94,50 @@ func (c *Client) doRequest(ctx context.Context,
req.Header.Set("X-Request-ID", requestID.(string))
}
// Tenant header: prefer per-request context value, fall back to client-level tenantID
tenantID := c.tenantID
if ctxTenant := ctx.Value("TenantID"); ctxTenant != nil {
switch v := ctxTenant.(type) {
case *uint64:
if v != nil {
tenantID = v
}
case uint64:
tmp := v
tenantID = &tmp
case string:
if parsed, err := strconv.ParseUint(v, 10, 64); err == nil {
tmp := parsed
tenantID = &tmp
}
}
}
// 2) Fallback: plain string key "TenantID" (some callers may use this)
if tenantID == nil {
if ctxTenant := ctx.Value("TenantID"); ctxTenant != nil {
switch v := ctxTenant.(type) {
case *uint64:
if v != nil {
tenantID = v
}
case uint64:
tmp := v
tenantID = &tmp
case string:
if parsed, err := strconv.ParseUint(v, 10, 64); err == nil {
tmp := parsed
tenantID = &tmp
}
}
}
}
if tenantID != nil {
req.Header.Set("X-Tenant-ID", strconv.FormatUint(*tenantID, 10))
}
return c.httpClient.Do(req)
}
+7
View File
@@ -21,12 +21,19 @@ import (
// - Cleaning up resources
func ExampleUsage() {
// Create a client instance
tenantID := uint64(10000) // default tenant for all requests from this client
apiClient := NewClient(
"http://localhost:8080",
WithToken("your-auth-token"),
WithTimeout(30*time.Second),
WithTenantID(tenantID), // default tenant for all requests from this client
)
// Per-request tenant override example:
// You can override the tenant for a single request by setting the "TenantID" value in the context.
// e.g. ctx := context.WithValue(context.Background(), "TenantID", &tenantID)
// then pass `ctx` to any client method to use tenant 2 for that request only.
// 1. Create a knowledge base
fmt.Println("1. Creating knowledge base...")
kb := &KnowledgeBase{