ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

使用 Yarp 做网关(二) : 网关 Swagger

2022-05-26 20:32:18  阅读:186  来源: 互联网

标签:网关 Swagger app Yarp json swagger options


Yarp & Swagger

目录

接着上一节 使用 Yarp 做网关 (一)
完成上一节的练习后,还遗留了一个问题:
如何通过 YarpGateway 访问内部服务的Swagger呢?

问题:无法访问内部服务 Swagger

​ 外部访问 IdentityService 和 OrderService 是通过 网关:YarpGateway 访问的,使用者这个并不知道这个两个服务的具体地址,也就是不知道如何访问它们的 Swagger,那么:

如何通过 YarpGateway 访问这两个服务的Swagger呢?

实现原理

使用网关内部服务的 Swagger 信息,其地址为:

http://ip:port/swagger/v1/swagger.json

例如,OrderService 服务的 Swagger 信息为:

http://localhost:7721/swagger/v1/swagger.json

在网关中使用内部服务的 Swagger 终点,再注册 Swagger 终点。

访问 OrderService 服务的 Swagger 信息地址:http://localhost:7711/swagger/v1/swagger.json

返回如下信息:(只列举部分数据)

{
  "openapi": "3.0.1",
  "info": {
    "title": "Identity Service",
    "version": "v1"
  },
  "paths": {
    "/api/identity/users": {
      "get": {
        "tags": [
          "User"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/IdentityService.Models.User"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/IdentityService.Models.User"
                  }
                }
              },
              "text/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/IdentityService.Models.User"
                  }
                }
              }
            }
          }
        }
      },
        
     .....

内部服务支持跨域

网关要请求内部服务的Swagger 信息,这是跨域请求,所以要求两个服务支持对网关的跨域请求。

IdentityServiceOrderService 项目中都做如下修改:

添加跨域配置

appsettins.json 文件中添加跨域配置:

{
  "App": {
    "CorsOrigins": "http://localhost:7700"      // 网关地址,支持网关的Yarp gatewary跨域请求
  }
}

其中,这个地址http://localhost:7700 就是网关的地址

支持跨域

修改 Program.cs文件:
代码清单:IdentityService/Program.cs

代码清单:OrderService/Program.cs

......
            builder.Services.AddCors(options =>
            {
                options.AddDefaultPolicy(builder =>
                {
                    builder
                        .WithOrigins(
                            configuration["App:CorsOrigins"]
                                .Split(",", StringSplitOptions.RemoveEmptyEntries)
                                .ToArray()
                        )
                        .SetIsOriginAllowedToAllowWildcardSubdomains()
                        .AllowAnyHeader()
                        .AllowAnyMethod()
                        .AllowCredentials();
                });
            });
......
    
            app.UseRouting();
 +          app.UseCors();  // 添加跨域支持
            app.UseSwagger();
            app.UseSwaggerUI();
.....

网关添加 Swagger

在网关项目【YarpGateway】中做如下修改:

代码清单:YarpGateway/Program.cs

            builder.Services.AddControllers(); //Web MVC
            ......
            builder.Services.AddSwaggerGen(options =>
            {
                options.SwaggerDoc("v1", new OpenApiInfo 
                { 
                    Title = "Order Service", Version = "v1" 
                });
                options.DocInclusionPredicate((docName, description) => true);
                options.CustomSchemaIds(type => type.FullName);
            });

            ......
            // 添加内部服务的Swagger终点
            app.UseSwaggerUIWithYarp();
            //访问网关地址,自动跳转到 /swagger 的首页
            app.UseRewriter(new RewriteOptions() 
                // Regex for "", "/" and "" (whitespace)
                .AddRedirect("^(|\\|\\s+)$", "/swagger"));

            app.UseRouting();

其中,调用方法 app.UseSwaggerUIWithYarp(); 的目的是:添加内部服务的Swagger终点,其代码如下:

代码清单:YarpGateway/Extensions/YarpSwaggerUIBuilderExtensions.cs

using Yarp.ReverseProxy.Configuration;

namespace YarpGateway.Extensions;
public static class YarpSwaggerUIBuilderExtensions
{
    public static IApplicationBuilder UseSwaggerUIWithYarp(this IApplicationBuilder app)
    {
        var serviceProvider = app.ApplicationServices;

        app.UseSwagger();
        app.UseSwaggerUI(options =>
        {
            var configuration = serviceProvider.GetRequiredService<IConfiguration>();
            var logger = serviceProvider.GetRequiredService<ILogger<Program>>();
            var proxyConfigProvider = serviceProvider.GetRequiredService<IProxyConfigProvider>();
            var yarpConfig = proxyConfigProvider.GetConfig();

            var routedClusters = yarpConfig.Clusters
                .SelectMany(t => t.Destinations,
                    (clusterId, destination) => new { clusterId.ClusterId, destination.Value });

            var groupedClusters = routedClusters
                .GroupBy(q => q.Value.Address)
                .Select(t => t.First())
                .Distinct()
                .ToList();

            foreach (var clusterGroup in groupedClusters)
            {
                var routeConfig = yarpConfig.Routes.FirstOrDefault(q =>
                    q.ClusterId == clusterGroup.ClusterId);
                if (routeConfig == null)
                {
                    logger.LogWarning($"Swagger UI: Couldn't find route configuration for {clusterGroup.ClusterId}...");
                    continue;
                }

                options.SwaggerEndpoint($"{clusterGroup.Value.Address}/swagger/v1/swagger.json", $"{routeConfig.RouteId} API");
                options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]);
                options.OAuthClientSecret(configuration["AuthServer:SwaggerClientSecret"]);
            }
        });

        return app;
    }
}

关键代码:

options.SwaggerEndpoint($"{clusterGroup.Value.Address}/swagger/v1/swagger.json", $"{routeConfig.RouteId} API");

通过 IProxyConfigProvider 得到内部服务的信息,如下图所示:

然后,拼接出内部服务的 Swagger 信息地址,

$"{clusterGroup.Value.Address}/swagger/v1/swagger.json"

最终得到两个服务的Swagger信息地址:

  • IdentityServer 的 Swagger 信息地址:
http://localhost:7711/swagger/v1/swagger.json
  • OrderService 的 Swagger 信息地址:
http://localhost:7721/swagger/v1/swagger.json

最后,根据信息添加Swagger终点:

options.SwaggerEndpoint(
        $"{clusterGroup.Value.Address}/swagger/v1/swagger.json", 
        $"{routeConfig.RouteId} API"
);

其中,

routeConfig.RouteId: Identity Service 或 Ordering Service

访问网关 Swagger

访问网地址:http://localhost:7700

自动跳转到地址:http://localhost:7700/swagger/index.html

右上角有个下拉框,可以选择不同的服务的Swagger,这里切换到 OrderService 的Swagger,如下图所示:

在网关 Swagger 调用服务接口

可以在网关 Swagger 调用内部服务接口,如下图所示:

返回:




标签:网关,Swagger,app,Yarp,json,swagger,options
来源: https://www.cnblogs.com/easy5weikai/p/16314830.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有