You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Cloud基于请求体的路由实现技术求助

基于请求体内容的API网关路由实现方案

以下是针对主流API网关的具体实现方案,覆盖Spring Cloud Gateway、Apache APISIX、Kong三种常用场景:

1. Spring Cloud Gateway 实现方式

Spring Cloud Gateway可通过内置的RequestBodyRoutePredicateFactory或自定义逻辑实现基于请求体的路由,需注意解决请求体只能读取一次的问题。

步骤1:配置路由规则

在application.yml中定义路由,通过请求体内容匹配目标服务:

spring:
  cloud:
    gateway:
      routes:
        - id: service-a-type1
          uri: http://service-a/v1/type1
          predicates:
            - Path=/serve-this-request
            - name: RequestBody
              args:
                pattern: '{"service":"service-a","type":"type1"}'
                matchType: CONTAINS
        - id: service-b-type5
          uri: http://service-b/v1/type5
          predicates:
            - Path=/serve-this-request
            - name: RequestBody
              args:
                pattern: '{"service":"service-b","type":"type5"}'
                matchType: CONTAINS
        - id: service-a-type2
          uri: http://service-a/v1/type2
          predicates:
            - Path=/serve-this-request
            - name: RequestBody
              args:
                pattern: '{"service":"service-a","type":"type2"}'
                matchType: CONTAINS
        - id: service-b-type2
          uri: http://service-b/v1/type2
          predicates:
            - Path=/serve-this-request
            - name: RequestBody
              args:
                pattern: '{"service":"service-b","type":"type2"}'
                matchType: CONTAINS
        - id: service-c-type3
          uri: http://service-c/v1/type3
          predicates:
            - Path=/serve-this-request
            - name: RequestBody
              args:
                pattern: '{"service":"service-c","type":"type3"}'
                matchType: CONTAINS

步骤2:添加请求体缓存过滤器

由于请求体默认只能读取一次,需自定义过滤器缓存请求体,确保后续路由断言能重复读取:

@Component
public class BodyCacheFilter implements GatewayFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        if (request.getHeaders().getContentLength() > 0) {
            return DataBufferUtils.join(request.getBody())
                    .map(dataBuffer -> {
                        byte[] bytes = new byte[dataBuffer.readableByteCount()];
                        dataBuffer.read(bytes);
                        DataBufferUtils.release(dataBuffer);
                        return bytes;
                    })
                    .flatMap(bytes -> {
                        ServerHttpRequestDecorator decoratedRequest = new ServerHttpRequestDecorator(request) {
                            @Override
                            public Flux<DataBuffer> getBody() {
                                return Flux.just(bufferFactory().wrap(bytes));
                            }
                        };
                        return chain.filter(exchange.mutate().request(decoratedRequest).build());
                    });
        }
        return chain.filter(exchange);
    }
}

将该过滤器添加到所有路由的filters列表中即可。

2. Apache APISIX 实现方式

APISIX可通过Lua脚本直接解析请求体,动态设置上游服务地址和URI。

创建路由规则

通过Admin API配置路由,嵌入Lua脚本处理路由逻辑:

curl http://apisix-admin:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
    "uri": "/serve-this-request",
    "plugins": {
        "request-validation": {
            "body_schema": {
                "type": "object",
                "properties": {
                    "service": {"type": "string"},
                    "type": {"type": "string"}
                }
            }
        }
    },
    "script": "local body = core.request.get_body() local json_body = core.json.decode(body) if json_body.service == \"service-a\" and json_body.type == \"type1\" then core.var.upstream_host = \"service-a\" core.var.upstream_uri = \"/v1/type1\" elseif json_body.service == \"service-b\" and json_body.type == \"type5\" then core.var.upstream_host = \"service-b\" core.var.upstream_uri = \"/v1/type5\" elseif json_body.service == \"service-a\" and json_body.type == \"type2\" then core.var.upstream_host = \"service-a\" core.var.upstream_uri = \"/v1/type2\" elseif json_body.service == \"service-b\" and json_body.type == \"type2\" then core.var.upstream_host = \"service-b\" core.var.upstream_uri = \"/v1/type2\" elseif json_body.service == \"service-c\" and json_body.type == \"type3\" then core.var.upstream_host = \"service-c\" core.var.upstream_uri = \"/v1/type3\" end"
}'

3. Kong 实现方式

Kong通过自定义Lua插件实现请求体解析与路由转发逻辑。

自定义插件核心代码

local plugin = {
    PRIORITY = 1000,
    VERSION = "0.1",
}

function plugin:access(conf)
    local body = kong.request.get_body()
    if body.service == "service-a" and body.type == "type1" then
        kong.service.set_target("service-a", 80)
        kong.service.set_path("/v1/type1")
    elseif body.service == "service-b" and body.type == "type5" then
        kong.service.set_target("service-b", 80)
        kong.service.set_path("/v1/type5")
    elseif body.service == "service-a" and body.type == "type2" then
        kong.service.set_target("service-a", 80)
        kong.service.set_path("/v1/type2")
    elseif body.service == "service-b" and body.type == "type2" then
        kong.service.set_target("service-b", 80)
        kong.service.set_path("/v1/type2")
    elseif body.service == "service-c" and body.type == "type3" then
        kong.service.set_target("service-c", 80)
        kong.service.set_path("/v1/type3")
    end
end

return plugin

将插件打包部署到Kong后,为/serve-this-request路由启用该插件即可。


内容的提问来源于stack exchange,提问作者spyder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 04:33:11