2

I am using Servicestack version 4.0.52.0 and ServiceStack.Api.Swagger 4.0.0.0

I have defined all routes with variable route parameter in serviceStack application host derived class(AppHostBase):Configure method

public class AppHost : AppHostBase
{
    public override void Configure(Funq.Container container)
    {
        //Infrastructure code goes here
        ....

        //Add routes
        Routes.Add<TestRequestDTO>("/{MyApplicationKey}/TestOperation/", "GET")
    }
}

Although these routes are visible in ServiceStack metadata page, swagger UI does not show routes begining with MyApplicationKey; Digging deeper into codebase of we found the issue in ServiceStack.Api.Swagger.SwaggerResourcesService.Get method:

 [AddHeader(DefaultContentType = MimeTypes.Json)]
    [DefaultRequest(typeof(SwaggerResources))]
    [Restrict(VisibilityTo = RequestAttributes.None)]
    public class SwaggerResourcesService : Service
    {
        private readonly Regex resourcePathCleanerRegex = new Regex(@"/[^\/\{]*", RegexOptions.Compiled);
        internal static Regex resourceFilterRegex;

        internal static Action<SwaggerResourcesResponse> ResourcesResponseFilter { get; set; }

        internal const string RESOURCE_PATH = "/resource";

        public object Get(SwaggerResources request)
        {
            var basePath = base.Request.GetBaseUrl();

            var result = new SwaggerResourcesResponse
            {
                BasePath = basePath,
                Apis = new List<SwaggerResourceRef>(),
                ApiVersion = HostContext.Config.ApiVersion,
                Info = new SwaggerInfo
                {
                    Title = HostContext.ServiceName,
                }
            };
            var operations = HostContext.Metadata;
            var allTypes = operations.GetAllOperationTypes();
            var allOperationNames = operations.GetAllOperationNames();
            foreach (var operationName in allOperationNames)
            {
                if (resourceFilterRegex != null && !resourceFilterRegex.IsMatch(operationName)) continue;
                var name = operationName;
                var operationType = allTypes.FirstOrDefault(x => x.Name == name);
                if (operationType == null) continue;
                if (operationType == typeof(SwaggerResources) || operationType == typeof(SwaggerResource))
                    continue;
                if (!operations.IsVisible(Request, Format.Json, operationName)) continue;

                CreateRestPaths(result.Apis, operationType, operationName);
            }

            result.Apis = result.Apis.OrderBy(a => a.Path).ToList();

            if (ResourcesResponseFilter != null)
                ResourcesResponseFilter(result);

            return new HttpResult(result) {
                ResultScope = () => JsConfig.With(includeNullValues:false)
            };
        }

        protected void CreateRestPaths(List<SwaggerResourceRef> apis, Type operationType, string operationName)
        {
            var map = HostContext.ServiceController.RestPathMap;
            var feature = HostContext.GetPlugin<SwaggerFeature>();

            var paths = new List<string>();

            foreach (var key in map.Keys)
            {
                paths.AddRange(map[key].Where(x => x.RequestType == operationType).Select(t => **resourcePathCleanerRegex.Match**(t.Path).Value));
            }
 ......
}

Any hints on how we can fix the issue? Is there any way to tell value of MyApplicationKey to Swagger API when it is doing resource listing?

Cache Staheli
  • 3,510
  • 7
  • 32
  • 51

1 Answers1

2

There is an opportunity to modify the Swagger Response by specifying a custom ResourcesResponseFilter when you register the SwaggerFeature plugin, e.g:

Plugins.Add(new SwaggerFeature {
    ResourceFilterPattern = @"/[^\/\{]*",
    ResourcesResponseFilter = response => ...
});

Which will let you modify the Swagger Response that the Swagger UI receives.

mythz
  • 141,670
  • 29
  • 246
  • 390
  • Yes, ResourcesResponseFilter allows us to change/filter results generated from SwaggerResourcesService's Get() method, but as i am using {MyApplicationKey} as prefix of my every API url, SwaggerResourcesService's Get() method avoiding my those methods due to this **private readonly Regex resourcePathCleanerRegex = new Regex(@"/[^\/\{]*", RegexOptions.Compiled);** regex , and as a result i am not getting any of my Url as resources in the ResourcesResponseFilter's results. – Disham Parikh Nov 30 '16 at 13:35
  • @DishamParikh you can also modify `resourcePathCleanerRegex` with [SwaggerFeature.ResourceFilterPattern](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Api.Swagger/SwaggerFeature.cs#L52) – mythz Nov 30 '16 at 15:45
  • yes, but SwaggerFeature.ResourceFilterPattern is not delegate for resourcePathCleanerRegex which is been used in CreateRestPaths() method of SwaggerResourcesService, the code part of CreatePaths() i.e https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Api.Swagger/SwaggerResourcesService.cs#L120, is escaping {MyApplicationKey} – Disham Parikh Dec 05 '16 at 13:50