By Abhilash | November 11, 2019
For one of our clients we built an API driven platform which could be consumed in two ways, either as a service using our front end or by integrating third party UI interfaces with the API. As one could guess API documentation plays a vital role in usability of such systems.
We use ServiceStack as our web services framework and API documentation generation is built into the framework. The generated documentation is a JSON file that conforms to Open API, which is a specification and complete framework implementation for describing, producing, consuming, and visualizing restful web services. To view the generated documentation we have to visit the URL - [base-webservices-url]/meta
of your hosted ServiceStack web API, provided the [Feature.Metadata]
is enabled.
Broadly there were two kinds of endpoints in our API system: endpoints an integrator could access and endpoints meant only for consumption from our own web apps. So an obvious requirement was that an integrator should only get to see the documentation for the endpoints he can access, rest of the (internal) API documentation should be excluded or hidden.
Now by default, the servicestack framework generates documentation for all the implemented endpoints and this wasnt going to work for us. We needed an explicit opt in mechanism for showing the integrator API documentation and rest of the API which did not opt in were considered internal and thereby hidden in terms of documentation.
ServiceStack does provide couple of ways to prevent an endpoint’s documentation from showing up.
[Exclude(Feature.Metadata)]
Applying this attribute at the endpoint or service level excludes the endpoint or list of endpoints in the service from the documentation, In debug mode, the endpoint details appear in a greyed out manner while in the release mode it gets completely hidden.[Restrict(VisibilityTo = RequestAttributes.None)]
Applying the Restrict attribute with visibility set to None has the same effect on documentation but this is also meant to hide the functionality as well.
[Exclude(Feature.Metadata)]
seemed to be the way to arrive at what we needed but we have around 200 plus integrator API endpoints and marking each one of them statically was a tedious process not to mention ensuring new endpoints also adhered to the same.
The [Exclude(Feature.Metadata)]
can be dynamically applied except that it has to be done at Pre-Init stage of the AppHost startup for it to take effect. Using this method we can apply [Exclude(Feature.Metadata)]
on AppHost.PreInit only on those endpoints that needed to be excluded, the list of which could be potentially arrived at from the database, or some other configuration at runtime.
public override void OnBeforeInit()
{
// Get requestDtoTypes
var requestDtoTypes = GetRequestDtoTypes();
foreach (var requestDtoType in requestDtoTypes)
{
if ( !requestDtoType.HasAttribute<ExcludeAttribute>())
{
requestDtoType.AddAttributes(new ExcludeAttribute(Feature.Metadata));
}
}
base.OnBeforeInit();
}