trnelson
trnelson

Reputation: 2773

Force a 404 on Web API routes (and sub endpoints)

I'm looking for a simple way to return a 404 error on all requests to a given route in Web API, and all endpoints in that route. In my scenario, I'll have a configuration flag to turn it on and off. It's a documentation endpoint using Swagger/Swashbuckle, and want the ability to turn it on and off as a feature toggle of sorts.

<add key="EnableDocumentation" value="true|false" />

Ideally, for all routes starting with /swagger (including /swagger/ui/index.html) I want to return a 404 if the above value is false

I tried IgnoreRoute in HttpConfiguration.Routes, but that doesn't work for routes deeper than the level specified. If I ignore /swagger, it's still possible to access /swagger/ui/index.html

Any suggestions on a good way to do this?

Thanks!

Upvotes: 0

Views: 1437

Answers (2)

Jamie Keeling
Jamie Keeling

Reputation: 9966

I had a similar scenario whereby:

  1. I want Swashbuckle installed for API documentation
  2. I want to control access to Swagger without removing the Nuget Package or redeployment of the API

This led me to the following code:

public class SwaggerConfig
{
    private const string AllowSwaggerUsageAppSetting = "AllowSwaggerAccess";

    public static void Register()
    {
        if (AllowSwaggerAccess)
        {
            Swashbuckle.Bootstrapper.Init(GlobalConfiguration.Configuration);
        }

        // NOTE: If you want to customize the generated swagger or UI, use SwaggerSpecConfig and/or SwaggerUiConfig here ...
    }

    private static bool AllowSwaggerAccess
    {
        get
        {
            bool _parsedValue;

            return bool.TryParse(ConfigurationManager.AppSettings[AllowSwaggerUsageAppSetting] ?? "false", out _parsedValue) && _parsedValue;
        }
    }
}

Unless there is a key in the appSettings section of web.config with the name AllowSwaggerAccess and a Bool.Parse'able value of true, the Swashbuckle bootstrapper is ignored meaning swagger documentation cannot be accessed and requests to the API return a 404.

The above code is based on v4 of the Swashbuckle Nuget Package.

If you download the code from github you can see that the Init method is responsible for setting up the routes:

public static class Bootstrapper
{
    public static void Init(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            "swagger_root",
            "swagger",
            null,
            null,
            new RedirectHandler("swagger/ui/index.html"));

        config.Routes.MapHttpRoute(
            "swagger_ui",
            "swagger/ui/{*uiPath}",
            null,
            new { uiPath = @".+" },
            new SwaggerUiHandler());

        config.Routes.MapHttpRoute(
            "swagger_versioned_api_docs",
            "swagger/{apiVersion}/api-docs/{resourceName}",
            new { resourceName = RouteParameter.Optional },
            null,
            new SwaggerSpecHandler());

        config.Routes.MapHttpRoute(
            "swagger_api_docs",
            "swagger/api-docs/{resourceName}",
            new { resourceName = RouteParameter.Optional },
            null,
            new SwaggerSpecHandler());
    }
}

Upvotes: 1

Yasser Shaikh
Yasser Shaikh

Reputation: 47794

You can do this by writing up your own custom HTTP module.

In your HTTP module you could check the incoming url request and return 404 if the url matches your route.

Check these out(only to get an idea of how a custom http module is written)

Upvotes: 1

Related Questions