feat[Go] implement check connection by using apikey and region (#15475)

### What problem does this PR solve?

**Verified from PostMan**


GET http://127.0.0.1:9384/api/v1/providers/gitee/connection
```json
body: 

{
    "api_key": "XXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "region": "default"

}

resp: 
{
    "code": 0,
    "message": "success"
}
```

GET http://127.0.0.1:9384/api/v1/providers/gitee/connection
```json
body: 

{
    "api_key": "XXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "region": "deprecated"

}

resp: 
{
    "code": 0,
    "message": "success"
}
```

GET http://127.0.0.1:9384/api/v1/providers/gitee/connection
```json
body: 

{
    "api_key": "XXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "region": "china"

}

resp: 
{
    "code": 0,
    "message": "success"
}

```

GET http://127.0.0.1:9384/api/v1/providers/lmstudio/connection
```json
body: 

{
    "api_key": "",
    "region": "test"

}

resp: 
{
    "code": 0,
    "message": "success"
}
```


### Type of change

- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
Haruko386
2026-06-02 19:32:41 +08:00
committed by GitHub
parent 36357a6afd
commit 9f969feb89
4 changed files with 111 additions and 4 deletions

View File

@@ -41,6 +41,15 @@ func (dao *TenantModelInstanceDAO) GetAllInstancesByProviderID(providerID string
return instances, nil
}
func (dao *TenantModelInstanceDAO) GetInstanceByApiKey(apiKey, providerID string) (*entity.TenantModelInstance, error) {
var instance entity.TenantModelInstance
err := DB.Where("api_key = ? && provider_id = ?", apiKey, providerID).First(&instance).Error
if err != nil {
return nil, err
}
return &instance, nil
}
func (dao *TenantModelInstanceDAO) GetByProviderIDAndInstanceName(providerID, instanceName string) (*entity.TenantModelInstance, error) {
var instance entity.TenantModelInstance
err := DB.Where("provider_id = ? AND instance_name = ?", providerID, instanceName).First(&instance).Error

View File

@@ -387,7 +387,42 @@ func (h *ProviderHandler) ShowInstanceBalance(c *gin.Context) {
})
}
func (h *ProviderHandler) CheckProviderConnection(c *gin.Context) {
func (h *ProviderHandler) CheckConnection(c *gin.Context) {
providerName := c.Param("provider_name")
if providerName == "" {
c.JSON(http.StatusBadRequest, gin.H{
"code": 400,
"message": "Provider name is required",
})
return
}
var req service.CheckConnectionRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"code": 400,
"message": err.Error(),
})
return
}
userID := c.GetString("user_id")
errCode, err := h.modelProviderService.CheckConnection(providerName, req.APIKey, req.Region, req.BaseURL, userID)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"code": errCode,
"message": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"code": 0,
"message": "success",
})
}
func (h *ProviderHandler) CheckInstanceConnection(c *gin.Context) {
providerName := c.Param("provider_name")
if providerName == "" {
c.JSON(http.StatusBadRequest, gin.H{
@@ -408,8 +443,21 @@ func (h *ProviderHandler) CheckProviderConnection(c *gin.Context) {
userID := c.GetString("user_id")
instanceInfo, code, err := h.modelProviderService.ShowProviderInstance(providerName, instanceName, userID)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"code": code,
"message": err.Error(),
})
return
}
apikey, _ := instanceInfo["apikey"].(string)
region, _ := instanceInfo["region"].(string)
baseURL, _ := instanceInfo["base_url"].(string)
// Get tenant ID from user
errorCode, err := h.modelProviderService.CheckProviderConnection(providerName, instanceName, userID)
errorCode, err := h.modelProviderService.CheckConnection(providerName, apikey, region, baseURL, userID)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"code": errorCode,

View File

@@ -319,7 +319,8 @@ func (r *Router) Setup(engine *gin.Engine) {
provider.GET("/:provider_name/instances", r.providerHandler.ListProviderInstances)
provider.GET("/:provider_name/instances/:instance_name", r.providerHandler.ShowProviderInstance)
provider.GET("/:provider_name/instances/:instance_name/balance", r.providerHandler.ShowInstanceBalance)
provider.GET("/:provider_name/instances/:instance_name/connection", r.providerHandler.CheckProviderConnection)
provider.GET("/:provider_name/instances/:instance_name/connection", r.providerHandler.CheckInstanceConnection)
provider.GET("/:provider_name/connection", r.providerHandler.CheckConnection)
provider.GET("/:provider_name/instances/:instance_name/tasks", r.providerHandler.ListTasks)
provider.GET("/:provider_name/instances/:instance_name/tasks/:task_id", r.providerHandler.ShowTask)
provider.PUT("/:provider_name/instances/:instance_name", r.providerHandler.AlterProviderInstance)

View File

@@ -88,6 +88,14 @@ type ModelProviderService struct {
userTenantDAO *dao.UserTenantDAO
}
// CheckConnectionRequest carries the credentials and optional instance selector
// for checking provider connectivity without creating a new model instance.
type CheckConnectionRequest struct {
APIKey string `json:"api_key"`
Region string `json:"region"`
BaseURL string `json:"base_url"`
}
func (m *ModelProviderService) AddModelProvider(providerName, userID string) (common.ErrorCode, error) {
_, err := dao.GetModelProviderManager().GetProviderByName(providerName)
@@ -364,7 +372,9 @@ func (m *ModelProviderService) ShowProviderInstance(providerName, instanceName,
"instanceName": instance.InstanceName,
"providerID": instance.ProviderID,
"status": instance.Status,
"apikey": instance.APIKey,
"region": extra["region"],
"base_url": extra["base_url"],
}
return result, common.CodeSuccess, nil
@@ -423,7 +433,46 @@ func (m *ModelProviderService) ShowInstanceBalance(providerName, instanceName, u
return result, common.CodeSuccess, nil
}
func (m *ModelProviderService) CheckProviderConnection(providerName, instanceName, userID string) (common.ErrorCode, error) {
func (m *ModelProviderService) CheckConnection(providerName, apiKey, region, baseURL string, userID string) (common.ErrorCode, error) {
providerInfo := dao.GetModelProviderManager().FindProvider(providerName)
if providerInfo == nil {
return common.CodeServerError, fmt.Errorf("provider %s not found", providerName)
}
apiKey = strings.TrimSpace(apiKey)
region = strings.TrimSpace(region)
baseURL = strings.TrimSpace(baseURL)
if region == "" {
region = "default"
}
driver := providerInfo.ModelDriver
if strings.EqualFold(providerInfo.Class, "local") {
if baseURL == "" {
return common.CodeDataError, fmt.Errorf("base_url is required for local provider %s", providerName)
}
var err error
driver, err = newModelDriverForBaseURL(driver, providerName, region, baseURL)
if err != nil {
return common.CodeServerError, err
}
}
apiConfig := &modelModule.APIConfig{
ApiKey: &apiKey,
Region: &region,
}
err := driver.CheckConnection(apiConfig)
if err != nil {
return common.CodeServerError, err
}
return common.CodeSuccess, nil
}
func (m *ModelProviderService) CheckInstanceConnection(providerName, instanceName, userID string) (common.ErrorCode, error) {
// Get tenant ID from user
tenants, err := m.userTenantDAO.GetByUserIDAndRole(userID, "owner")