网关api 聚合 zuul + swagger + swaggerbutler

邹修真
2023-12-01

网关api 聚合 zuul + swagger + SwaggerButler

1 缘起

在微服务化的过程中,每个微服务都有自己的 swagger 接口,能不能在统一的一个地方显示,比如在网关显示

2 技术选型

  • 微服务框架 springboot
  • 网关 zuul
  • api文档 swagger
  • 网关 api 聚合项目(改造过源码的)SwaggerButler

3 实战

springboot + zuul + swagger 就不说了,网上一搜一大把

SwaggerButler (https://github.com/dyc87112/swagger-butler)是一个开源项目,方便集成 swagger-zuul 聚合网关的,大家看看文档就行

4 遇到的问题

如果笔者一切顺利,就不会有这篇博客了。这里说一下笔者遇到的问题

如果你的各个微服务没有设置 server.servlet.context-path 就不用往下看了

  • 问题
 1 当 通过 SwaggerButler 聚合网关之后
 2 在网关的swagger-ui 
 3 通过 zuul 调用带有 context-path 的服务的接口
 4 发现 404
  • 原因
如果你打印了 请求路由,你会发现缺少了 context-path
  • 解决方案

通过新增 zuul 的前缀过滤器, 修改 x-forwarded-prefix,拼接上下文解决

package com.surfilter.core.config.swagger;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.X_FORWARDED_PREFIX_HEADER;

/**
 * @description: 转换请求头, 添加上下文
 * @author: huangwenjun
 * @createDate: 2019/12/20
 */
@Slf4j
public class XForwardedFilter extends ZuulFilter {

    @Autowired
    SwaggerButlerProperties swaggerButlerProperties;

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 6;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        String prefix = ctx.getZuulRequestHeaders().get("x-forwarded-prefix");

        if (StringUtils.isNotBlank(prefix)) {
            return true;
        }

        return false;
    }

    @Override
    public Object run() {
        try {
            RequestContext ctx = RequestContext.getCurrentContext();
            String prefix = ctx.getZuulRequestHeaders().get("x-forwarded-prefix");

            if (StringUtils.isNotBlank(prefix)) {
                String serviceId = String.valueOf(ctx.get("serviceId"));
                String contextPath = swaggerButlerProperties.getServiceContextConfig().get(serviceId);

                if (StringUtils.isNotBlank(contextPath)) {
                    contextPath = "/" + contextPath;
                    prefix = prefix + contextPath;
                    ctx.addZuulRequestHeader(X_FORWARDED_PREFIX_HEADER, prefix);
                }
            }
        } catch (Exception e) {
            log.error("请求头 x-forwarded-prefix 转换失败 {}", e);
        }

        return null;
    }
}

  • 以下是笔者的配置
# 聚合网关配置
swagger.butler.auto-generate-from-zuul-routes=true
# 配置需要聚合的服务id
swagger.butler.generate-routes=ga-system-service-252,ga-data-open-service-hwj
# serviceId 和 context-path 的映射
swagger.butler.serviceContextConfig.ga-system-service-252=system
swagger.butler.serviceContextConfig.ga-data-open-service-hwj=dataservice

更多

  • 为啥要修改 x-forwarded-prefix
如果你去看看 Swagger2Controller 源码就知道了

如果传了 x-forwarded-prefix ,则会根据传的参数确定 basePath

swagger basePath 拼装接口路由
  • spring-getway 如何实现聚合网关
其实 getway 实现聚合网关的方式应该类似
无非就是要多传一个 x-forwarded-prefix
笔者没用实现过,就不多说了
 类似资料: