Ocelot Swagger MMLib.SwaggerForOcelot showing "No operations defined in spec!"

Viewed 340

I am using Ocelot gateway and for swagger document using "MMLib.SwaggerForOcelot" library. For some swagger Key, swagger UI is showing "No operations defined in spec!" and swagger JSON is coming without paths like

{
  "openapi": "3.0.1",
  "info": {
    "title": "Admin API",
    "version": "v1"
  },
  "paths": {},
  "components": {
    "schemas": {}
  }
}

Ocelot Configuration Route is

{
      "DownstreamPathTemplate": "/api/admin/v{version}/{everything} ",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5000
        }
      ],
      "UpstreamPathTemplate": "/api/admin/v{version}/{everything}",
      "UpstreamHttpMethod": [],
      "QoSOptions": {
        "ExceptionsAllowedBeforeBreaking": 3,
        "DurationOfBreak": 1000,
        "TimeoutValue": 900000
      },
      "SwaggerKey": "AdminAPI"
    }

and Swagger Configuration is

 "SwaggerEndPoints": [
    {
      "Key": "AdminAPI",
      "Config": [
        {
          "Name": "Admin API",
          "Version": "v1",
          "Url": "http://localhost:5000/swagger/v1/swagger.json"
        }
      ]
    }
    
  ]

after reviewing the MMLib.SwaggerForOcelot source code, it looks like something to do with the version in the downstream path, any clue on how this can be fixed?

1 Answers

The issue is that MMLib.SwaggerForOcelot is not considering {version} while doing Ocelot transformation.

RouteOptions has a property TransformByOcelotConfig which is set to true by default, so once swagger JSON is obtained from downstream, the transformation will be done. here, it will try to find the route from the route configuration like below and if not found it will delete the route from swagger JSON

private static RouteOptions FindRoute(IEnumerable<RouteOptions> routes, string downstreamPath, string basePath)
        {
            string downstreamPathWithBasePath = PathHelper.BuildPath(basePath, downstreamPath);
            return routes.FirstOrDefault(p
                => p.CanCatchAll
                    ? downstreamPathWithBasePath.StartsWith(p.DownstreamPathWithSlash, StringComparison.CurrentCultureIgnoreCase)
                    : p.DownstreamPathWithSlash.Equals(downstreamPathWithBasePath, StringComparison.CurrentCultureIgnoreCase));
        }

The problem is StartsWith will return false since swagger JSON path will be like

/api/admin/v{version}/Connections

and route config is like

/api/admin/v{version}/{everything}

and version will replace with the version given in swagger options so that it will become

/api/admin/v1/{everything}

Fix to this problem will be

  1. Either set "TransformByOcelotConfig":false in swagger option
"SwaggerEndPoints": [
    {
      "Key": "AdminAPI",
      "TransformByOcelotConfig":false,
      "Config": [
        {
          "Name": "Admin API",
          "Version": "v1",
          "Url": "http://localhost:5000/swagger/v1/swagger.json"
        }
      ]
    }
    
  ]
  1. Or Change the route, just to have {everything} keyword
{
      "DownstreamPathTemplate": "/api/admin/{everything} ",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5000
        }
      ],
      "UpstreamPathTemplate": "/api/admin/{everything}",
      "UpstreamHttpMethod": [],
      "QoSOptions": {
        "ExceptionsAllowedBeforeBreaking": 3,
        "DurationOfBreak": 1000,
        "TimeoutValue": 900000
      },
      "SwaggerKey": "AdminAPI"
    }
Related