客户端添加切换租户
This commit is contained in:
+21
-1
@@ -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
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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{
|
||||
|
||||
Reference in New Issue
Block a user