diff --git a/README.md b/README.md index 0a23c7815..bcbcbe1cf 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@

AI Native API Gateway

- + [![Build Status](https://github.com/alibaba/higress/actions/workflows/build-and-test.yaml/badge.svg?branch=main)](https://github.com/alibaba/higress/actions) [![license](https://img.shields.io/github/license/alibaba/higress.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) [![discord](https://img.shields.io/discord/1364956090566971515?color=5865F2&label=discord&labelColor=black&logo=discord&logoColor=white&style=flat-square)](https://discord.gg/tSbww9VDaM) @@ -34,7 +34,7 @@ Higress is a cloud-native API gateway based on Istio and Envoy, which can be ext ### Core Use Cases -Higress's AI gateway capabilities support all [mainstream model providers](https://github.com/alibaba/higress/tree/main/plugins/wasm-go/extensions/ai-proxy/provider) both domestic and international. It also supports hosting MCP (Model Context Protocol) Servers through its plugin mechanism, enabling AI Agents to easily call various tools and services. With the [openapi-to-mcp tool](https://github.com/higress-group/openapi-to-mcpserver), you can quickly convert OpenAPI specifications into remote MCP servers for hosting. Higress provides unified management for both LLM API and MCP API. +Higress's AI gateway capabilities support all [mainstream model providers](https://github.com/alibaba/higress/tree/main/plugins/wasm-go/extensions/ai-proxy/provider) both domestic and international. It also supports hosting MCP (Model Context Protocol) Servers through its plugin mechanism, enabling AI Agents to easily call various tools and services. With the [openapi-to-mcp tool](https://github.com/higress-group/openapi-to-mcpserver), you can quickly convert OpenAPI specifications into remote MCP servers for hosting. Higress provides unified management for both LLM API and MCP API. **🌟 Try it now at [https://mcp.higress.ai/](https://mcp.higress.ai/)** to experience Higress-hosted Remote MCP Servers firsthand: @@ -51,7 +51,7 @@ You can click the button below to install the enterprise version of Higress: ## Summary -- [**Quick Start**](#quick-start) +- [**Quick Start**](#quick-start) - [**Feature Showcase**](#feature-showcase) - [**Use Cases**](#use-cases) - [**Core Advantages**](#core-advantages) @@ -78,20 +78,20 @@ Port descriptions: > All Higress Docker images use Higress's own image repository and are not affected by Docker Hub rate limits. > In addition, the submission and updates of the images are protected by a security scanning mechanism (powered by Alibaba Cloud ACR), making them very secure for use in production environments. -> +> > If you experience a timeout when pulling image from `higress-registry.cn-hangzhou.cr.aliyuncs.com`, you can try replacing it with the following docker registry mirror source: -> +> > **North America**: `higress-registry.us-west-1.cr.aliyuncs.com` -> +> > **Southeast Asia**: `higress-registry.ap-southeast-7.cr.aliyuncs.com` > **For Kubernetes deployments**, you can configure the `global.hub` parameter in Helm values to use a mirror registry closer to your region. This applies to both Higress component images and built-in Wasm plugin images: -> +> > ```bash > # Example: Using North America mirror > helm install higress -n higress-system higress.io/higress --set global.hub=higress-registry.us-west-1.cr.aliyuncs.com --create-namespace > ``` -> +> > Available mirror registries: > - **China (Hangzhou)**: `higress-registry.cn-hangzhou.cr.aliyuncs.com` (default) > - **North America**: `higress-registry.us-west-1.cr.aliyuncs.com` @@ -129,7 +129,7 @@ If you are deploying on the cloud, it is recommended to use the [Enterprise Edit - **Kubernetes ingress controller**: Higress can function as a feature-rich ingress controller, which is compatible with many annotations of K8s' nginx ingress controller. - + [Gateway API](https://gateway-api.sigs.k8s.io/) is already supported, and it supports a smooth migration from Ingress API to Gateway API. Compared to ingress-nginx, the resource overhead has significantly decreased, and the speed at which route changes take effect has improved by ten times. @@ -140,13 +140,13 @@ If you are deploying on the cloud, it is recommended to use the [Enterprise Edit ![](https://img.alicdn.com/imgextra/i1/O1CN01bhEtb229eeMNBWmdP_!!6000000008093-2-tps-750-547.png) - + - **Microservice gateway**: Higress can function as a microservice gateway, which can discovery microservices from various service registries, such as Nacos, ZooKeeper, Consul, Eureka, etc. - + It deeply integrates with [Dubbo](https://github.com/apache/dubbo), [Nacos](https://github.com/alibaba/nacos), [Sentinel](https://github.com/alibaba/Sentinel) and other microservice technology stacks. - + - **Security gateway**: Higress can be used as a security gateway, supporting WAF and various authentication strategies, such as key-auth, hmac-auth, jwt-auth, basic-auth, oidc, etc. @@ -165,15 +165,15 @@ If you are deploying on the cloud, it is recommended to use the [Enterprise Edit Supports true complete streaming processing of request/response bodies, Wasm plugins can easily customize the handling of streaming protocols such as SSE (Server-Sent Events). In high-bandwidth scenarios such as AI businesses, it can significantly reduce memory overhead. - + - **Easy to Extend** - + Provides a rich official plugin library covering AI, traffic management, security protection and other common functions, meeting more than 90% of business scenario requirements. Focuses on Wasm plugin extensions, ensuring memory safety through sandbox isolation, supporting multiple programming languages, allowing plugin versions to be upgraded independently, and achieving traffic-lossless hot updates of gateway logic. - **Secure and Easy to Use** - + Based on Ingress API and Gateway API standards, provides out-of-the-box UI console, WAF protection plugin, IP/Cookie CC protection plugin ready to use. Supports connecting to Let's Encrypt for automatic issuance and renewal of free certificates, and can be deployed outside of K8s, started with a single Docker command, convenient for individual developers to use. diff --git a/plugins/golang-filter/mcp-server/servers/gorm/db.go b/plugins/golang-filter/mcp-server/servers/gorm/db.go index 90ce36d4f..db5c374c1 100644 --- a/plugins/golang-filter/mcp-server/servers/gorm/db.go +++ b/plugins/golang-filter/mcp-server/servers/gorm/db.go @@ -164,14 +164,14 @@ func (c *DBClient) DescribeTable(table string) ([]map[string]interface{}, error) switch c.dbType { case MYSQL: sql = ` - select + select column_name, column_type, is_nullable, column_key, column_default, extra, - column_comment + column_comment from information_schema.columns where table_schema = database() and table_name = ? ` @@ -179,17 +179,17 @@ func (c *DBClient) DescribeTable(table string) ([]map[string]interface{}, error) case POSTGRES: sql = ` - select + select column_name, data_type as column_type, is_nullable, - case + case when column_default like 'nextval%' then 'auto_increment' when column_default is not null then 'default' else '' end as column_key, column_default, - case + case when column_default like 'nextval%' then 'auto_increment' else '' end as extra, @@ -202,7 +202,7 @@ func (c *DBClient) DescribeTable(table string) ([]map[string]interface{}, error) case CLICKHOUSE: sql = ` - select + select name as column_name, type as column_type, if(is_nullable, 'YES', 'NO') as is_nullable, @@ -217,7 +217,7 @@ func (c *DBClient) DescribeTable(table string) ([]map[string]interface{}, error) case SQLITE: sql = ` - select + select name as column_name, type as column_type, not (notnull = 1) as is_nullable, @@ -236,6 +236,10 @@ func (c *DBClient) DescribeTable(table string) ([]map[string]interface{}, error) // ListTables List all tables in the connected database. func (c *DBClient) ListTables() ([]string, error) { + if err := c.reconnectIfDbEmpty(); err != nil { + return nil, err + } + var sql string switch c.dbType { case MYSQL: @@ -265,6 +269,10 @@ func (c *DBClient) ListTables() ([]string, error) { tables = append(tables, table) } + if err := rows.Err(); err != nil { + return nil, fmt.Errorf("error iterating table rows: %w", err) + } + return tables, nil } @@ -335,6 +343,10 @@ func (c *DBClient) Query(sql string, args ...interface{}) ([]map[string]interfac results = append(results, rowMap) } + if err := rows.Err(); err != nil { + return nil, fmt.Errorf("failed to iterate table rows in Query: %w", err) + } + return results, nil } diff --git a/plugins/golang-filter/mcp-server/servers/rag/vectordb/milvus.go b/plugins/golang-filter/mcp-server/servers/rag/vectordb/milvus.go index 66c8706f1..0c929abf4 100644 --- a/plugins/golang-filter/mcp-server/servers/rag/vectordb/milvus.go +++ b/plugins/golang-filter/mcp-server/servers/rag/vectordb/milvus.go @@ -792,22 +792,36 @@ func (m *MilvusProvider) ListDocs(ctx context.Context, limit int) ([]schema.Docu fieldName := strings.ToLower(fieldMapping.StandardName) switch fieldName { case "id": - if v, err := col.(*entity.ColumnVarChar).Get(i); err == nil { - id = v.(string) + if typedCol, ok := col.(*entity.ColumnVarChar); ok { + if v, err := typedCol.Get(i); err == nil { + if s, ok := v.(string); ok { + id = s + } + } } case "content": - if v, err := col.(*entity.ColumnVarChar).Get(i); err == nil { - content = v.(string) + if typedCol, ok := col.(*entity.ColumnVarChar); ok { + if v, err := typedCol.Get(i); err == nil { + if s, ok := v.(string); ok { + content = s + } + } } case "metadata": - if v, err := col.(*entity.ColumnJSONBytes).Get(i); err == nil { - if bytes, ok := v.([]byte); ok { - _ = json.Unmarshal(bytes, &metadata) + if typedCol, ok := col.(*entity.ColumnJSONBytes); ok { + if v, err := typedCol.Get(i); err == nil { + if bytes, ok := v.([]byte); ok { + _ = json.Unmarshal(bytes, &metadata) + } } } case "created_at": - if v, err := col.(*entity.ColumnInt64).Get(i); err == nil { - createdAt = v.(int64) + if typedCol, ok := col.(*entity.ColumnInt64); ok { + if v, err := typedCol.Get(i); err == nil { + if ts, ok := v.(int64); ok { + createdAt = ts + } + } } } } diff --git a/plugins/wasm-go/extensions/request-block/main.go b/plugins/wasm-go/extensions/request-block/main.go index 0612d0421..34197dd2f 100644 --- a/plugins/wasm-go/extensions/request-block/main.go +++ b/plugins/wasm-go/extensions/request-block/main.go @@ -87,13 +87,17 @@ func parseConfig(json gjson.Result, config *RequestBlockConfig, log log.Log) err if regexpUrl == "" { continue } + var reg *regexp.Regexp + var err error if config.caseSensitive { - reg := regexp.MustCompile(regexpUrl) - config.blockRegExpArray = append(config.blockRegExpArray, reg) + reg, err = regexp.Compile(regexpUrl) } else { - reg := regexp.MustCompile(strings.ToLower(regexpUrl)) - config.blockRegExpArray = append(config.blockRegExpArray, reg) + reg, err = regexp.Compile(strings.ToLower(regexpUrl)) } + if err != nil { + return fmt.Errorf("invalid regexp pattern %q: %w", regexpUrl, err) + } + config.blockRegExpArray = append(config.blockRegExpArray, reg) } for _, item := range json.Get("block_headers").Array() { header := item.String()