feat(wasm-plugin): add jsonrpc-converter plugin (#2805)

This commit is contained in:
澄潭
2025-08-28 19:28:37 +08:00
committed by GitHub
parent 44c33617fa
commit 3e0a5f02a7
9 changed files with 416 additions and 3 deletions

View File

@@ -0,0 +1,35 @@
module jsonrpc-converter
go 1.24.3
require (
github.com/higress-group/proxy-wasm-go-sdk v0.0.0-20250611100342-5654e89a7a80
github.com/higress-group/wasm-go v1.0.2-0.20250819092116-2fd2b083a8e2
github.com/tidwall/gjson v1.18.0
)
require (
dario.cat/mergo v1.0.1 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.3.0 // indirect
github.com/Masterminds/sprig/v3 v3.3.0 // indirect
github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/higress-group/gjson_template v0.0.0-20250413075336-4c4161ed428b // indirect
github.com/huandu/xstrings v1.5.0 // indirect
github.com/invopop/jsonschema v0.13.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/shopspring/decimal v1.4.0 // indirect
github.com/spf13/cast v1.7.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tidwall/resp v0.1.1 // indirect
github.com/tidwall/sjson v1.2.5 // indirect
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
golang.org/x/crypto v0.26.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

View File

@@ -0,0 +1,75 @@
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0=
github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=
github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/higress-group/gjson_template v0.0.0-20250413075336-4c4161ed428b h1:rRI9+ThQbe+nw4jUiYEyOFaREkXCMMW9k1X2gy2d6pE=
github.com/higress-group/gjson_template v0.0.0-20250413075336-4c4161ed428b/go.mod h1:rU3M+Tq5VrQOo0dxpKHGb03Ty0sdWIZfAH+YCOACx/Y=
github.com/higress-group/proxy-wasm-go-sdk v0.0.0-20250611100342-5654e89a7a80 h1:xqmtTZI0JQ2O+Lg9/CE6c+Tw9KD6FnvWw8EpLVuuvfg=
github.com/higress-group/proxy-wasm-go-sdk v0.0.0-20250611100342-5654e89a7a80/go.mod h1:tRI2LfMudSkKHhyv1uex3BWzcice2s/l8Ah8axporfA=
github.com/higress-group/wasm-go v1.0.2-0.20250724062140-49cd26dcf15a h1:WCnqxeHgvV5LZvPx37EBWi1vXQ3Aw5ldFezZlG4l5Zk=
github.com/higress-group/wasm-go v1.0.2-0.20250724062140-49cd26dcf15a/go.mod h1:9k7L730huS/q4V5iH9WLDgf5ZUHEtfhM/uXcegKDG/M=
github.com/higress-group/wasm-go v1.0.2-0.20250819092116-2fd2b083a8e2 h1:2wlbNpFJCQNbPBFYgswz7Zvxo9O3L0PH0AJxwiCc5lk=
github.com/higress-group/wasm-go v1.0.2-0.20250819092116-2fd2b083a8e2/go.mod h1:9k7L730huS/q4V5iH9WLDgf5ZUHEtfhM/uXcegKDG/M=
github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI=
github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=
github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/resp v0.1.1 h1:Ly20wkhqKTmDUPlyM1S7pWo5kk0tDu8OoC/vFArXmwE=
github.com/tidwall/resp v0.1.1/go.mod h1:3/FrruOBAxPTPtundW0VXgmsQ4ZBA0Aw714lVYgwFa0=
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@@ -0,0 +1,271 @@
package main
import (
"encoding/json"
"fmt"
"slices"
"strconv"
"github.com/higress-group/proxy-wasm-go-sdk/proxywasm"
"github.com/higress-group/proxy-wasm-go-sdk/proxywasm/types"
"github.com/higress-group/wasm-go/pkg/log"
"github.com/higress-group/wasm-go/pkg/mcp"
"github.com/higress-group/wasm-go/pkg/mcp/utils"
"github.com/higress-group/wasm-go/pkg/wrapper"
"github.com/tidwall/gjson"
)
func main() {}
const (
JsonRpcId = "x-envoy-jsonrpc-id"
JsonRpcMethod = "x-envoy-jsonrpc-method"
JsonRpcParams = "x-envoy-jsonrpc-params"
JsonRpcResult = "x-envoy-jsonrpc-result"
JsonRpcError = "x-envoy-jsonrpc-error"
McpToolName = "x-envoy-mcp-tool-name"
McpToolArguments = "x-envoy-mcp-tool-arguments"
McpToolResponse = "x-envoy-mcp-tool-response"
McpToolError = "x-envoy-mcp-tool-error"
DefaultMaxHeaderLength = 4000 // default max length for truncation
MethodToolList = "tools/list" // default method for tool list
MethodToolCall = "tools/call" // default method for tool call
)
type ProcessStage string
const (
ProcessRequest ProcessStage = "request"
ProcessResponse ProcessStage = "response"
)
type McpConverterConfig struct {
Stage ProcessStage `json:"stage"`
MaxHeaderLength int `json:"max_header_length,omitempty"`
AllowedMethods []string `json:"allowed_methods,omitempty"` // optional, for future use
}
func init() {
mcp.LoadMCPFilter(
mcp.FilterName("jsonrpc-converter"),
mcp.SetConfigParser(parseConfig),
mcp.SetJsonRpcRequestFilter(processJsonRpcRequest),
mcp.SetJsonRpcResponseFilter(processJsonRpcResponse),
mcp.SetToolListResponseFilter(processToolListResponse),
mcp.SetToolCallRequestFilter(processToolCallRequest),
mcp.SetToolCallResponseFilter(processToolCallResponse),
)
mcp.InitMCPFilter()
}
func parseConfig(configBytes []byte, filterConfig *any) error {
var config McpConverterConfig
if err := json.Unmarshal(configBytes, &config); err != nil {
return fmt.Errorf("failed to parse mcp-converter config: %v", err)
}
// validate stage
if config.Stage != ProcessRequest && config.Stage != ProcessResponse {
return fmt.Errorf("invalid mcp-converter stage: %s, must be 'request' or 'response'", config.Stage)
}
// validate length
if config.MaxHeaderLength <= 0 {
config.MaxHeaderLength = DefaultMaxHeaderLength
}
// validate allowed methods
if len(config.AllowedMethods) == 0 {
config.AllowedMethods = []string{MethodToolList, MethodToolCall}
}
log.Infof("MCP Converter config parsed successfully, stage: %s", config.Stage)
*filterConfig = config
return nil
}
func isPreRequestStage(config any) bool {
return config.(McpConverterConfig).Stage == ProcessRequest
}
func isPreResponseStage(config any) bool {
return config.(McpConverterConfig).Stage == ProcessResponse
}
func isMethodAllowed(config any, method string) bool {
allowedMethods := config.(McpConverterConfig).AllowedMethods
return slices.Contains(allowedMethods, method)
}
// Remove jsonrpc headers
func removeJsonRpcHeaders(isRequest bool) {
headersToRemove := []string{
JsonRpcId,
JsonRpcMethod,
JsonRpcParams,
JsonRpcResult,
McpToolName,
McpToolArguments,
McpToolResponse,
McpToolError,
}
for _, header := range headersToRemove {
var err error
if isRequest {
err = proxywasm.RemoveHttpRequestHeader(header)
} else {
err = proxywasm.RemoveHttpResponseHeader(header)
}
if err != nil {
log.Errorf("failed to remove header %s: %v", header, err)
}
}
}
// Insert jsonrpc headers
func insertJsonRpcHeaders(isRequest bool, config any, name string, value string) {
if value == "" {
log.Debugf("Skipping insertion of empty header %s", name)
return
}
truncatedValue := truncateString(value, config)
var err error
if isRequest {
err = proxywasm.ReplaceHttpRequestHeader(name, truncatedValue)
} else {
err = proxywasm.ReplaceHttpResponseHeader(name, truncatedValue)
}
if err != nil {
log.Errorf("failed to insert header %s: %v", name, err)
}
}
func printHeaders(stage ProcessStage, s string) {
var err error
var headersNow any
switch stage {
case ProcessRequest:
headersNow, err = proxywasm.GetHttpRequestHeaders()
case ProcessResponse:
headersNow, err = proxywasm.GetHttpResponseHeaders()
}
if err != nil {
log.Errorf("PrintHeaders %s: failed to get request headers: %v", s, err)
return
}
log.Debugf("PrintHeaders %s: %v", s, headersNow)
}
// truncates a string to a maximum length of 4000 characters.
func truncateString(s string, config any) string {
length := config.(McpConverterConfig).MaxHeaderLength
if len(s) <= length {
return s
}
prefix := s[:length/2]
suffix := s[len(s)-length/2:]
return fmt.Sprintf("%s...(truncated)...%s", prefix, suffix)
}
func processJsonRpcRequest(context wrapper.HttpContext, config any, id utils.JsonRpcID, method string, params gjson.Result, rawBody []byte) types.Action {
if isPreResponseStage(config) {
// pre-response removes request headers, which are added by pre-request
removeJsonRpcHeaders(true)
return types.ActionContinue
}
if !isMethodAllowed(config, method) {
log.Debugf("[JsonRpcRequest] Method %s is not allowed, skipping processing", method)
return types.ActionContinue
}
// Set common headers, JsonRpcId, JsonRpcMethod
insertJsonRpcHeaders(true, config, JsonRpcId, id.StringValue)
insertJsonRpcHeaders(true, config, JsonRpcMethod, method)
// Set other headers based on the method
// For MethodToolCall, we set the params in processToolCallRequest
if method != MethodToolCall {
// JsonRpcParams
insertJsonRpcHeaders(true, config, JsonRpcParams, params.String())
}
return types.ActionContinue
}
func processJsonRpcResponse(context wrapper.HttpContext, config any, id utils.JsonRpcID, result, error gjson.Result, rawBody []byte) types.Action {
if isPreRequestStage(config) {
// pre-request removes response headers, which are added by pre-response
removeJsonRpcHeaders(false)
return types.ActionContinue
}
method := context.GetStringContext("JSONRPC_METHOD", "")
if !isMethodAllowed(config, method) {
log.Debugf("[JsonRpcResponse] Method %s is not allowed, skipping processing", method)
return types.ActionContinue
}
// Set common headers, JsonRpcId, JsonRpcMethod
insertJsonRpcHeaders(false, config, JsonRpcId, id.StringValue)
insertJsonRpcHeaders(false, config, JsonRpcMethod, method)
// Set other headers based on the method
// For MethodToolList & MethodToolCall, we set the params in processToolCallResponse and processToolListResponse
if method != MethodToolList && method != MethodToolCall {
// JsonRpcResult
insertJsonRpcHeaders(false, config, JsonRpcResult, result.String())
// JsonRpcError
insertJsonRpcHeaders(false, config, JsonRpcError, error.String())
}
return types.ActionContinue
}
func processToolListResponse(ctx wrapper.HttpContext, config any, tools gjson.Result, rawBody []byte) types.Action {
if isPreRequestStage(config) {
return types.ActionContinue
}
if !isMethodAllowed(config, MethodToolList) {
log.Debugf("[ToolListResponse] Method %s is not allowed, skipping processing", MethodToolList)
return types.ActionContinue
}
// JsonRpcResult
insertJsonRpcHeaders(false, config, JsonRpcResult, tools.String())
return types.ActionContinue
}
func processToolCallRequest(ctx wrapper.HttpContext, config any, toolName string, toolArgs gjson.Result, rawBody []byte) types.Action {
if isPreResponseStage(config) {
return types.ActionContinue
}
if !isMethodAllowed(config, MethodToolCall) {
log.Debugf("[ToolCallRequest] Method %s is not allowed, skipping processing", MethodToolCall)
return types.ActionContinue
}
// McpToolName, McpToolArguments
insertJsonRpcHeaders(true, config, McpToolName, toolName)
insertJsonRpcHeaders(true, config, McpToolArguments, toolArgs.String())
return types.ActionContinue
}
func processToolCallResponse(ctx wrapper.HttpContext, config any, isError bool, content gjson.Result, rawBody []byte) types.Action {
if isPreRequestStage(config) {
return types.ActionContinue
}
if !isMethodAllowed(config, MethodToolCall) {
log.Debugf("[ToolCallResponse] Method %s is not allowed, skipping processing", MethodToolCall)
return types.ActionContinue
}
// McpToolResponse, McpToolError
insertJsonRpcHeaders(false, config, McpToolResponse, content.String())
insertJsonRpcHeaders(false, config, McpToolError, strconv.FormatBool(isError))
return types.ActionContinue
}

View File

@@ -0,0 +1,28 @@
package main
import (
"testing"
)
func TestTruncateString(t *testing.T) {
tests := []struct {
name string
input string
maxLen int
expected string
}{
{"Short String", "Higress Is an AI-Native API Gateway", 1000, "Higress Is an AI-Native API Gateway"},
{"Exact Length", "Higress Is an AI-Native API Gateway", 35, "Higress Is an AI-Native API Gateway"},
{"Truncated String", "Higress Is an AI-Native API Gateway", 20, "Higress Is...(truncated)...PI Gateway"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
config := McpConverterConfig{MaxHeaderLength: tt.maxLen}
result := truncateString(tt.input, config)
if result != tt.expected {
t.Errorf("truncateString(%q, %d) = %q; want %q", tt.input, tt.maxLen, result, tt.expected)
}
})
}
}

View File

@@ -4,7 +4,7 @@ go 1.24.1
require (
github.com/higress-group/proxy-wasm-go-sdk v0.0.0-20250611100342-5654e89a7a80
github.com/higress-group/wasm-go v1.0.2-0.20250807064511-eb1cd98e1f57
github.com/higress-group/wasm-go v1.0.2-0.20250819092116-2fd2b083a8e2
github.com/tidwall/gjson v1.18.0
github.com/tidwall/sjson v1.2.5
)

View File

@@ -24,6 +24,8 @@ github.com/higress-group/proxy-wasm-go-sdk v0.0.0-20250611100342-5654e89a7a80 h1
github.com/higress-group/proxy-wasm-go-sdk v0.0.0-20250611100342-5654e89a7a80/go.mod h1:tRI2LfMudSkKHhyv1uex3BWzcice2s/l8Ah8axporfA=
github.com/higress-group/wasm-go v1.0.2-0.20250807064511-eb1cd98e1f57 h1:WhNdnKSDtAQrh4Yil8HAtbl7VW+WC85m7WS8kirnHAA=
github.com/higress-group/wasm-go v1.0.2-0.20250807064511-eb1cd98e1f57/go.mod h1:9k7L730huS/q4V5iH9WLDgf5ZUHEtfhM/uXcegKDG/M=
github.com/higress-group/wasm-go v1.0.2-0.20250819092116-2fd2b083a8e2 h1:2wlbNpFJCQNbPBFYgswz7Zvxo9O3L0PH0AJxwiCc5lk=
github.com/higress-group/wasm-go v1.0.2-0.20250819092116-2fd2b083a8e2/go.mod h1:9k7L730huS/q4V5iH9WLDgf5ZUHEtfhM/uXcegKDG/M=
github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI=
github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=

View File

@@ -100,7 +100,7 @@ func ProcessRequest(context wrapper.HttpContext, config any, toolName string, to
if !routerConfig.enable {
return types.ActionContinue
}
// Extract server name from tool name (format: "${serverName}HigressRouteTo${toolName}")
// Extract server name from tool name (format: "${serverName}___${toolName}")
parts := strings.SplitN(toolName, consts.ToolSetNameSplitter, 2)
if len(parts) != 2 {
log.Debugf("Tool name '%s' does not contain server prefix, continuing without routing", toolName)

View File

@@ -8,7 +8,7 @@ replace amap-tools => ../amap-tools
require (
amap-tools v0.0.0-00010101000000-000000000000
github.com/higress-group/wasm-go v1.0.2-0.20250819032348-2591c1c2476d
github.com/higress-group/wasm-go v1.0.2-0.20250819092116-2fd2b083a8e2
quark-search v0.0.0-00010101000000-000000000000
)

View File

@@ -24,6 +24,8 @@ github.com/higress-group/proxy-wasm-go-sdk v0.0.0-20250611100342-5654e89a7a80 h1
github.com/higress-group/proxy-wasm-go-sdk v0.0.0-20250611100342-5654e89a7a80/go.mod h1:tRI2LfMudSkKHhyv1uex3BWzcice2s/l8Ah8axporfA=
github.com/higress-group/wasm-go v1.0.2-0.20250819032348-2591c1c2476d h1:9XEF+IifLNcEqRTPQc9o6zqVEO6NXzjHUWM6S3qpbss=
github.com/higress-group/wasm-go v1.0.2-0.20250819032348-2591c1c2476d/go.mod h1:9k7L730huS/q4V5iH9WLDgf5ZUHEtfhM/uXcegKDG/M=
github.com/higress-group/wasm-go v1.0.2-0.20250819092116-2fd2b083a8e2 h1:2wlbNpFJCQNbPBFYgswz7Zvxo9O3L0PH0AJxwiCc5lk=
github.com/higress-group/wasm-go v1.0.2-0.20250819092116-2fd2b083a8e2/go.mod h1:9k7L730huS/q4V5iH9WLDgf5ZUHEtfhM/uXcegKDG/M=
github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI=
github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=