Skip to content

Version Policies

Chris Martinez edited this page Jan 2, 2023 · 2 revisions

Version discovery supports advertising which API versions are supported and deprecated via the api-supported-versions and api-deprecated-versions respectively. A key limitation of this support is that it does not indicate when an API version will be sunset nor what the stated policy is.

Version policies introduces support for RFC 8594. This will allow an API version to indicate when it will disappear for good via the Sunset header. This header does not necessarily apply to all API versions; it will only apply to the API version that was requested. The sunset policy can include additional information such as a web page or OpenAPI document. These additional links will conform to RFC 8288: Web Linking.

These capabilities are useful, not only for instrumented clients, but also for tooling. As an example, an API might support an OPTIONS request to retrieve this information for tooling:

OPTIONS /weather?api-version=1.0 HTTP/2
Host: localhost
HTTP/2 200 OK
Allow: GET, POST, OPTIONS
Api-Supported-Versions: 1.0, 2.0, 3.0
Api-Deprecated-Versions: 0.9
Sunset: Thu, 01 Apr 2022 00:00:00 GMT
Link: <https://docs.api.com/policy.html?api-version=1.0>; rel="sunset"; title="API Policy"; type="text/html"
Link: </swagger/v1/swagger.json>; rel="openapi"; title="OpenAPI"; type="application/json"

This indicates to a client that the requested API version 1.0 will sunset on 4/1/2022. It also provides a link to a public web page that outlines the API versioning policy as well as a link to where the OpenAPI document is located.

Sunset policies do not have to have a date. The following scenarios are supported:

  • Define a sunset policy by API name and version
  • Define a sunset policy by API name for any version
  • Define a sunset policy by API version for any API
  • A sunset policy may have a date
  • A sunset policy can have zero or more links

Supporting a sunset policy with links alone enables advertising a stated policy when you don't know when an API version might actually be sunset, which will be common for the current version of an API. If a sunset policy is defined, it will be emitted through the existing IReportApiVersions service. This service is automatically utilized whenever ApiVersioningOptions.ReportApiVersions is set to true or ReportApiVersionsAttribute is applied.

Configuration

The configuration is performed the same way across all platforms via:

AddApiVersioning(options =>
{
  // version 1.0 sunsets 4/1/2022 with a public policy page
  options.Policies.Sunset( 1.0 )
                  .Effective( 2022, 4, 1 )
                  .Link( "https://docs.api.com/policy.html?api-version=1.0" )
                      .Title( "API Policy" )
                      .Type( "text/html" );

  // public policy page for version 2.0 without a sunset date
  options.Policies.Sunset( 2.0 )
                  .Link( "https://docs.api.com/policy.html?api-version=2.0" )
                      .Title( "API Policy" )
                      .Type( "text/html" )
})

It should be noted that although links confirm to RFC 8288, all configurable links are meant to be specific to sunset policies in API versioning. The provided configuration APIs, therefore, only expose a subset of what is configurable and always use a relation type of rel="sunset". The default implementation can be replaced or extended or you can use the LinkHeaderValue directly in your own code, which exposes the complete feature set.

API Explorer Integration

The API Explorer extensions will attach the appropriate SunsetPolicy to a ApiVersionDescription and ApiDescription. The policy for a ApiVersionDescription will be for an entire API version, while the policy for an ApiDescription could be for a specific API, version, or combination of both.

The provided information can be used in any number of different ways, but would most likely be used in conjunction with OpenAPI. There is currently no direct support for a sunset policy in OpenAPI, but it can be exposed via an OpenAPI extension or directly in the API documentation.

var text = new StringBuilder( "An example API." );

if ( description.SunsetPolicy is not SunsetPolicy policy )
{
  return;
}

if ( policy.Date is DateTimeOffset when )
{
  text.Append( " The API will be sunset on " )
      .Append( when.Date.ToShortDateString() )
      .Append( '.' );
}

if ( !policy.HasLinks )
{
  return;
}
    
text.AppendLine();

for ( var i = 0; i < policy.Links.Count; i++ )
{
  var link = policy.Links[i];

  // only add links to HTML pages
  if ( link.Type == "text/html" )
  {
    text.AppendLine();

    if ( link.Title.HasValue )
    {
      text.Append( link.Title.Value ).Append( ": " );
    }

    text.Append( link.LinkTarget.OriginalString );
  }
}
Clone this wiki locally