skip to Main Content

I have to implement a routine/library to discover an application’s APIs then list them in a database. I don’t know where to start and I can’t find anything really helpful in internet.

All I can do is display the API information via their URL but I can’t find them.

2

Answers


  1. The URL with API information might be made from an XML or JSON documentation file, like Swagger does. c.f. : https://swagger.io/specification/

    Hopefully, you can access this file directly (And not the generated HTML) and therefore extract the required info. Then store it in your DB. We might need more precise info to help further.

    Login or Signup to reply.
  2. Assuming you’re using ASP.NET instead of Core, this is a code snippet I used to do similar things.

            // Get custom ones in RouteTable (custom routes defined in RouteConfig)
            private static readonly IEnumerable<string> UrlsFromRouteTable = RouteTable.Routes
                .Select(r => ((Route)r).Url)
                // For ignoring Default ({controller}/{action}), but looking back now I think there's better way
                .Where(url => !url.Contains("{"));
    
            private static readonly HashSet<string> Urls = Assembly.GetExecutingAssembly()
                .GetTypes()
    
                // find all Controller typed classes, and get the public methods with Http Action-related attributes in those
                .Where(t => typeof(System.Web.Mvc.Controller).IsAssignableFrom(t))
                .SelectMany(t => t.GetMethods())
                .Where(m => m.IsPublic && m.CustomAttributes.Any(ca =>
                    typeof(ActionMethodSelectorAttribute).IsAssignableFrom(ca.AttributeType)))
                .Select(m => $"{m.DeclaringType?.Name.Replace("Controller", "")}/{m.Name}")
    
                // If endpoint exists in RouteTable, remove from result
                .Except(RouteTable.Routes
                    .Select(r => r as Route)
                    .Where(r => r != null
                                && r.Defaults != null
                                && r.Defaults.ContainsKey("controller")
                                && r.Defaults.ContainsKey("action"))
                    // transform into route format
                    .Select(r => $"{r.Defaults["controller"]}/{r.Defaults["action"]}"))
    
                // Concats with custom endpoints
                .Concat(UrlsFromRouteTable)
                .Where(s => s.HasContent())
                .Distinct()
    
                // Note that here I transformed them all into lower case, remove if you don't need
                .Select(s => s.ToLowerInvariant())
                .ToHashSet();
    

    For some stupid reason our project couldn’t use swagger, so this is a dirty way we do when we need to check if a certain endpoint exists in the project.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search