swagger3.0的一个bug:由于网关层的stripprefix配置导致swagger页面内的所有请求接口404 not found

问题描述

在swagger3.0中,请求网关层https://ip:port/swagger-ui/index.html,在请求页面内任何一个服务的接口时,请求的接口 not found 。原因:我们发现页面Curl 或者 Request URL处的url地址为:https://ip:port/接口定义的路径,而缺失了服务名。我们请求网关的正确url 应该为https://ip:port/服务名/接口路径(比如:https://ip:port/order/haha —>https://ip:port//haha order 为服务名,haha为接口路径)。

原因

我们发现这是由于在网关层中添加了stripprefix配置,导致路由转发时会去掉路径中的前缀(即上面所提到的服务名)。而swagger3.0没能处理这个前缀。

swagger2.x 如何处理这个前缀

springfox.documentation.swagger2.web.Swagger2Controller#getDocumentation 的控制器方法。会返回io.swagger.models.Swagger 实体类的json数据。源码如下:
springfox.documentation.swagger2.web.Swagger2Controller#getDocumentation 的控制器方法
Swagger实体类
通过debug,发现Swagger的basePath 属性,封装了路径中的前缀信息。以下是拿到basePath的方法

basePath的封装方法

swagge3.0

在3.0中,控制方法变为了 springfox.documentation.oas.web.OpenApiControllerWebMvc#getDocumentation。返回给前端的实体类变成了io.swagger.v3.oas.models.OpenAPI 。
在这里插入图片描述
在这里插入图片描述
如上图,OpenAPI中缺失了 basePath。
发现swagger页面中所有的接口url的封装为 Server.url 加上 paths 中任意一个接口路径。

解决方案

在springfox.documentation.oas.web.OpenApiControllerWebMvc#getDocumentation 控制器方法返回结果之前,会遍历所有的springfox.documentation.oas.web.WebMvcOpenApiTransformationFilter,并执行其中的springfox.documentation.oas.web.OpenApiTransformationFilter#transform 方法(底层有一个默认的:WebMvcBasePathAndHostnameTransformationFilter,执行的优先级最高,主要是封装了OpenAPI中的servers属性)。
在这里插入图片描述
在自定义的swagger3配置类中添加如下的内部类(在OpenAPI的Server.url中 添加了在网关层去掉的前缀 ):

    class BasePathAddingFilter implements WebMvcOpenApiTransformationFilter {


        @Override
        public OpenAPI transform(OpenApiTransformationContext<HttpServletRequest> context) {
            OpenAPI openApi = context.getSpecification();
            List<Server> servers = openApi.getServers();
            Optional<HttpServletRequest> request = context.request();
            HttpServletRequest httpServletRequest = request.get();
            Enumeration<String> headers = httpServletRequest.getHeaders("X-Forwarded-Prefix");
            if (headers.hasMoreElements()) {
                String s = headers.nextElement();
                for (Server server : servers) {
                    server.setUrl(String.format("%s%s", server.getUrl(), s));
                }
            }
            return openApi;
        }

        @Override
        public boolean supports(DocumentationType documentationType) {
            return documentationType == DocumentationType.OAS_30;
        }
    }
  • 15
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值