<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
<!-- generated by https://github.com/cabo/kramdown-rfc version 1.6.35 (Ruby 3.2.2) -->
<?rfc tocindent="yes"?>
<?rfc strict="yes"?>
<?rfc compact="yes"?>
<?rfc comments="yes"?>
<?rfc inline="yes"?>
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-nottingham-http-invalidation-00" category="std" consensus="true" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.17.3 -->
  <front>
    <title>An HTTP Cache Invalidation API</title>
    <seriesInfo name="Internet-Draft" value="draft-nottingham-http-invalidation-00"/>
    <author initials="M." surname="Nottingham" fullname="Mark Nottingham">
      <organization/>
      <address>
        <postal>
          <postalLine>Prahran</postalLine>
          <postalLine>Australia</postalLine>
        </postal>
        <email>mnot@mnot.net</email>
        <uri>https://www.mnot.net/</uri>
      </address>
    </author>
    <date/>
    <keyword>Internet-Draft</keyword>
    <abstract>
      <?line 43?>

<t>This document specifies an HTTP-based API that gateway caches (such as those in reverse proxies and content delivery networks) can expose to allow origin servers to their invalidate stored responses.</t>
    </abstract>
    <note removeInRFC="true">
      <name>About This Document</name>
      <t>
        Status information for this document may be found at <eref target="https://datatracker.ietf.org/doc/draft-nottingham-http-invalidation/"/>.
      </t>
      <t>
         information can be found at <eref target="https://mnot.github.io/I-D/"/>.
      </t>
      <t>Source for this draft and an issue tracker can be found at
        <eref target="https://github.com/mnot/I-D/labels/http-invalidation"/>.</t>
    </note>
  </front>
  <middle>
    <?line 47?>

<section anchor="introduction">
      <name>Introduction</name>
      <t><xref section="4.4" sectionFormat="of" target="HTTP-CACHING"/> defines invalidation as the side effect of a state-changing request on one or more stored responses in an HTTP cache.</t>
      <t>In practice, it has become common for caches to allow invalidation to be triggered through other mechanisms -- often, using a dedicated HTTP API. This is especially useful for caches that have a relationship with the origin server and wish to offer them finer-grained control, as is the case for reverse proxies and content delivery networks.</t>
      <t>While many such APIs already exist, they are proprietary. That makes it difficult for the origin server or its delegates (for example, content management systems) to take advantage of those facilities, because each integration needs to created and maintained, hindering interoperability.</t>
      <t>This document standardises an HTTP-based API for HTTP cache invalidation. <xref target="resource"/> describes an HTTP resource that accepts requests to invalidate stored responses, using a format described in <xref target="event-format"/>. <xref target="desc-format"/> specifies a format that describes the capabilities and configuration of a cache's invalidation API, so that tools used by the origin server can easily consume it.</t>
      <section anchor="notational-conventions">
        <name>Notational Conventions</name>
        <t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL
NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
"<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as
described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they
appear in all capitals, as shown here.</t>
        <?line -18?>

</section>
    </section>
    <section anchor="resource">
      <name>HTTP Cache Invalidation Resources</name>
      <t>An HTTP Cache Invalidation Resource (hereafter, 'invalidation resource') is an HTTP resource (<xref section="3.1" sectionFormat="of" target="HTTP"/>) that has the behaviours described in this section.</t>
      <t>Invalidation resources <bcp14>SHOULD</bcp14> require requests to include some form of authentication. The specific mechanism is out of scope for this document, but note that <xref target="desc-format"/> describes a way to specify a mechanism and credentials in the description format.</t>
      <t>When an invalidation resource receives a POST request whose content is in the format described in <xref target="event-format"/>, its expected behaviour will be to process the request and invalidate the responses it indicates that are stored in the cache(s) associated with it.</t>
      <t>As described in <xref section="4.4" sectionFormat="of" target="HTTP-CACHING"/>:</t>
      <ul empty="true">
        <li>
          <t>invalidate means that the cache will either remove all stored responses whose target URI matches the given URI or mark them as "invalid" and in need of a mandatory validation before they can be sent in response to a subsequent request.</t>
        </li>
      </ul>
      <t>This includes all responses for the URI, including those who have cache keys that include information derived from the Vary response field (see <xref section="4.1" sectionFormat="of" target="HTTP-CACHING"/>).</t>
      <t>The authenticated user <bcp14>MUST</bcp14> be authorized to perform each invalidation. Unauthorized invalidations <bcp14>MUST</bcp14> be ignored; future extensions might allow description of which invalidations succeeded or failed.</t>
      <t>Furthermore, some features in the event format described in <xref target="event-format"/> are not required to be implemented; for example, some event selector types might not be supported, or the "purge" member might not be supported. An invalidation resource that receives a request using an unsupported feature <bcp14>SHOULD</bcp14> respond with a 501 (Not Implemented) status code.</t>
      <t>TODO: specify a problem details object for these errors</t>
      <t>If the cache is able to invalidate the indicated stored responses in a reasonable amount of time (for example, 30 seconds), the invalidation resource <bcp14>SHOULD</bcp14> respond with a 200 (OK) status code only once all of those responses have been invalidated.</t>
      <t>Otherwise (i.e., the cache cannot invalidate within a reasonable amount of time, or cannot estimate how long invalidation will take), it <bcp14>SHOULD</bcp14> immediately respond with a 202 (Accepted) status code.</t>
      <t>This specification does not define a format for successful responses from invalidation resources; implementations <bcp14>MAY</bcp14> send responses with empty content. Future extensions might allow description of the results of invalidation.</t>
    </section>
    <section anchor="event-format">
      <name>HTTP Cache Invalidation Event Format</name>
      <t>The HTTP Cache Invalidation Event Format (hereafter, 'event format') is a JSON-based <xref target="JSON"/> format that conveys a list of selectors that are used to identify the stored responses in a cache, along with additional instructions about the nature of invalidation being requested.</t>
      <t>Its content is an object with the following two required members:</t>
      <ul spacing="normal">
        <li>"type": a case-sensitive string indicating the selector type for the invalidation event; see <xref target="selector-types"/></li>
        <li>"selectors": an array of strings, each being a selector of the indicated type.</li>
      </ul>
      <t>For example, this document contains an event using the "URI" selector type, and invalidates two URIs:</t>
      <sourcecode type="json"><![CDATA[
{
    "type": "uri",
    "selectors": [
      "https://example.com/foo/bar",
      "https://example.com/foo/bar/baz"
    ]
}
]]></sourcecode>
      <t>Additionally, this document defines one optional member of the top-level object:</t>
      <ul spacing="normal">
        <li>"purge": a boolean that when true indicates that the selected stored responses should be removed from cache, rather than just marked as invalid.</li>
      </ul>
      <t>When a cache indicates support for purge (see <xref target="desc-format"/>) and purge is true, the cache <bcp14>MUST</bcp14> remove the relevant response(s) from volatile and non-volatile storage as promptly as possible, and if the cache indicates success with a 200 (OK) status code, <bcp14>MUST</bcp14> do so before returning the response.</t>
      <t>Unrecognised members of the top-level object <bcp14>MUST</bcp14> be ignored, to allow future updates of this specification to add new features.</t>
      <section anchor="selector-types">
        <name>Selector Types</name>
        <t>This document defines the following cache invalidation selector types:</t>
        <section anchor="uri-selector">
          <name>URI Selectors</name>
          <t>The "uri" selector type selects one or more stored responses by their URI. When the invalidation event type is "uri", the content each selector string <bcp14>MUST</bcp14> be either a URI <xref target="URI"/> or an IRI <xref target="IRI"/>.</t>
          <t>When a selector value is compared to a stored response URI to determine whether it selects that response, the following process is used:</t>
          <ol spacing="normal" type="1"><li>If the selector value is a IRI, it is converted to a URI, per <xref section="3.2" sectionFormat="of" target="IRI"/>.</li>
            <li>Syntax-based normalization is applied to both the selector and stored response URI, per <xref section="6.2.2" sectionFormat="of" target="URI"/>.</li>
            <li>Scheme-based normalization is applied to both the selector and stored response URI, per <xref section="6.2.3" sectionFormat="of" target="URI"/>.</li>
          </ol>
          <t>For example, "https://www.example.com/foo/bar" selects stored responses with the following URIs:</t>
          <ul spacing="normal">
            <li>"https://www.example.com/foo/bar"</li>
            <li>"HTTPS://www.example.com:443/foo/bar"</li>
            <li>"https://www.example.com/fo%6f/bar"</li>
            <li>"https://www.example.com/fo%6F/bar"</li>
            <li>"https://www.example.com/../foo/bar"</li>
            <li>"https://www.example.com:/foo/bar"</li>
          </ul>
          <t>... but does not select stored responses with the following URIs:</t>
          <ul spacing="normal">
            <li>"https://www.example.com/FOO/bar" (different path)</li>
            <li>"https://www.example.com/foo/bar/baz" (different path)</li>
            <li>"https://www.example.com/foo/barbaz" (different path)</li>
            <li>"https://www.example.com/foo/bar/" (different path)</li>
            <li>"http://www.example.com/foo/bar" (different scheme)</li>
            <li>"https://example.com/foo/bar" (different authority)</li>
            <li>"https://www.example.com/foo/bar?baz" (different query)</li>
            <li>"https://www.example.com/foo/bar?" (different query)</li>
            <li>"https://www.example.com:8080/foo/bar" (different authority)</li>
          </ul>
        </section>
        <section anchor="prefix-selector">
          <name>URI Prefix Selectors</name>
          <t>The "uri-prefix" selector type selects one or more stored responses by their URI prefix. When the invalidation event type is "uri-prefix", the content each selector string <bcp14>MUST</bcp14> be either a URI <xref target="URI"/> or an IRI <xref target="IRI"/>.</t>
          <t>When a selector value is compared to a stored response URI to determine whether it selects that response, the same normalization process described in <xref target="uri-selector"/> is used. However, the selector value is considered to be a prefix to match. Additionally, each segment of the selector value's path must have a matching segment in the stored response URI.</t>
          <t>For example, "https://www.example.com/foo/bar" would select all of the following URIs:</t>
          <ul spacing="normal">
            <li>"https://www.example.com/foo/bar"</li>
            <li>"https://www.example.com/foo/bar/"</li>
            <li>"https://www.example.com/foo/bar/baz"</li>
            <li>"https://www.example.com/foo/bar/baz/bat"</li>
            <li>"https://www.example.com/foo/bar?"</li>
            <li>"https://www.example.com/foo/bar?baz"</li>
          </ul>
          <t>... but does not match stored responses with the following URIs:</t>
          <ul spacing="normal">
            <li>"https://www.example.com/foo/barbaz" (last segment does not match)
ww.example.com/foo/BAR/baz" (second segment does not match)</li>
          </ul>
        </section>
        <section anchor="origin-selector">
          <name>Origin Selectors</name>
          <t>The "origin" selector type selects all stored responses associated with a URI origin (<xref section="4.3.1" sectionFormat="of" target="HTTP"/>). When the invalidation event type is "origin", the content of each selector string <bcp14>MUST</bcp14> be a normalized (using the process defined in <xref target="uri-selector"/>) URI prefix, without a trailing "/". If the port is not present, it is assumed to be the default port for the scheme.</t>
          <t>For example, all of these are origin selectors:</t>
          <ul spacing="normal">
            <li>"https://www.example.com:443"</li>
            <li>"http://example.com"</li>
            <li>"https://example.net:8080"</li>
          </ul>
        </section>
        <section anchor="group-selectors">
          <name>Group Selectors</name>
          <t>The "group" selector type selects all stored responses associated with a group on a specified origin. When the invalidation event type is "group", the content of each selector string <bcp14>MUST</bcp14> be a normalized (using the process defined in <xref target="uri-selector"/>) URI prefix with port always present, and without a trailing "/". See <xref target="origin-selector"/> for examples.</t>
          <t>Additionally, when the invalidation event type is "group", the document's root object <bcp14>MUST</bcp14> contain an additional member, "groups", whose value is an array of strings that correspond to the group(s) being invalidated, per <xref target="GROUPS"/>.</t>
          <t>For example:</t>
          <sourcecode type="json"><![CDATA[
{
    "type": "group",
    "selectors": [
      "https://example.com:443",
      "https://www.example.com:443"
    ],
    "groups": [
      "scripts"
    ]
}
]]></sourcecode>
        </section>
      </section>
    </section>
    <section anchor="desc-format">
      <name>Gateway Description Format</name>
      <t>To alloworigin servers and tools that they use to be easily configured, this document defines a Gateway Description Format that describes the configuration of an HTTP gateway (commonly, a "reverse proxy" or content delivery network). It is intended to be generated by gateways and made available out-of-band to origin servers using them.</t>
      <t>The format is based upon JSON <xref target="JSON"/>. The root object can contain members with the following names and values:</t>
      <ul spacing="normal">
        <li>"generated": a string containing the date that the description was generated, in the IMF-fixdate format described in <xref section="5.6.7" sectionFormat="of" target="HTTP"/></li>
        <li>"description": a string containing a human-readable description of the gateway</li>
        <li>"invalidation": an invalidation description object (see below)</li>
        <li>"api-authentication": an API authentication description object (see below)</li>
        <li>"targeted-cc": an array of strings indicating the targeted cache-control header field(s) <xref target="TARGETED"/> supported by the gateway, in order of precedence (i.e., first entry overrides later entries)</li>
        <li>"vendor": an object containing arbitrary, vendor-specific extensions</li>
      </ul>
      <t>Invalidation description objects can contain the following members and values:</t>
      <ul spacing="normal">
        <li>"uri": a string conveying the URI of the Invalidation Resource (<xref target="resource"/>)</li>
        <li>"selectors": an array of strings indicating the selectors (<xref target="selector-types"/>) that the Invalidation Resource supports</li>
        <li>"purge": a boolean indicating whether the Invalidation Resource supports the "purge" member in requests (see <xref target="event-format"/>)</li>
        <li>"p95-latency": an integer indicating the number of milliseconds that 95% of invalidation requests should be fully applied to the scope indicated by the description.</li>
      </ul>
      <t>API authentication objects can contain the following members and values:</t>
      <ul spacing="normal">
        <li>"bearer": a string containing a token to be used to authenticate to the API(s) described in the document, using Bearer HTTP authentication as described in <xref section="2.1" sectionFormat="of" target="BEARER"/></li>
      </ul>
      <t>Unrecognised members of all of these objects <bcp14>MUST</bcp14> be ignored. New members may be introduced to them by updating this specification.</t>
      <t>For example:</t>
      <sourcecode type="json"><![CDATA[
{
  "description": "The Example CDN",
  "generated": "",
  "invalidation": {
    "uri": "https://api.cdn.example.com/invalidate",
    "selectors": ["uri", "uri-prefix", "group"],
    "purge": true,
    "p95-latency": 2000
  },
  "targeted-cc": [
    "ExampleCDN-Cache-Control",
    "CDN-Cache-Control"
  ],
  "api-authentication": {
    "bearer": "mF_9.B5f-4.1JqM"
  }
}
]]></sourcecode>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <section anchor="media-types">
        <name>Media Types</name>
        <t><em>TBD</em></t>
      </section>
      <section anchor="cache-invalidation-selector-types">
        <name>Cache Invalidation Selector Types</name>
        <t><em>TBD</em></t>
      </section>
    </section>
    <section anchor="security-considerations">
      <name>Security Considerations</name>
      <t><em>TBD</em></t>
    </section>
  </middle>
  <back>
    <references>
      <name>Normative References</name>
      <reference anchor="HTTP">
        <front>
          <title>HTTP Semantics</title>
          <author fullname="R. Fielding" initials="R." role="editor" surname="Fielding"/>
          <author fullname="M. Nottingham" initials="M." role="editor" surname="Nottingham"/>
          <author fullname="J. Reschke" initials="J." role="editor" surname="Reschke"/>
          <date month="June" year="2022"/>
          <abstract>
            <t>The Hypertext Transfer Protocol (HTTP) is a stateless application-level protocol for distributed, collaborative, hypertext information systems. This document describes the overall architecture of HTTP, establishes common terminology, and defines aspects of the protocol that are shared by all versions. In this definition are core protocol elements, extensibility mechanisms, and the "http" and "https" Uniform Resource Identifier (URI) schemes.</t>
            <t>This document updates RFC 3864 and obsoletes RFCs 2818, 7231, 7232, 7233, 7235, 7538, 7615, 7694, and portions of 7230.</t>
          </abstract>
        </front>
        <seriesInfo name="STD" value="97"/>
        <seriesInfo name="RFC" value="9110"/>
        <seriesInfo name="DOI" value="10.17487/RFC9110"/>
      </reference>
      <reference anchor="HTTP-CACHING">
        <front>
          <title>HTTP Caching</title>
          <author fullname="R. Fielding" initials="R." role="editor" surname="Fielding"/>
          <author fullname="M. Nottingham" initials="M." role="editor" surname="Nottingham"/>
          <author fullname="J. Reschke" initials="J." role="editor" surname="Reschke"/>
          <date month="June" year="2022"/>
          <abstract>
            <t>The Hypertext Transfer Protocol (HTTP) is a stateless application-level protocol for distributed, collaborative, hypertext information systems. This document defines HTTP caches and the associated header fields that control cache behavior or indicate cacheable response messages.</t>
            <t>This document obsoletes RFC 7234.</t>
          </abstract>
        </front>
        <seriesInfo name="STD" value="98"/>
        <seriesInfo name="RFC" value="9111"/>
        <seriesInfo name="DOI" value="10.17487/RFC9111"/>
      </reference>
      <reference anchor="GROUPS">
        <front>
          <title>*** BROKEN REFERENCE ***</title>
          <author>
            <organization/>
          </author>
          <date/>
        </front>
      </reference>
      <reference anchor="BEARER">
        <front>
          <title>The OAuth 2.0 Authorization Framework: Bearer Token Usage</title>
          <author fullname="M. Jones" initials="M." surname="Jones"/>
          <author fullname="D. Hardt" initials="D." surname="Hardt"/>
          <date month="October" year="2012"/>
          <abstract>
            <t>This specification describes how to use bearer tokens in HTTP requests to access OAuth 2.0 protected resources.  Any party in possession of a bearer token (a "bearer") can use it to get access to the associated resources (without demonstrating possession of a cryptographic key).  To prevent misuse, bearer tokens need to be protected from disclosure in storage and in transport. [STANDARDS-TRACK]</t>
          </abstract>
        </front>
        <seriesInfo name="RFC" value="6750"/>
        <seriesInfo name="DOI" value="10.17487/RFC6750"/>
      </reference>
      <reference anchor="TARGETED">
        <front>
          <title>Targeted HTTP Cache Control</title>
          <author fullname="S. Ludin" initials="S." surname="Ludin"/>
          <author fullname="M. Nottingham" initials="M." surname="Nottingham"/>
          <author fullname="Y. Wu" initials="Y." surname="Wu"/>
          <date month="June" year="2022"/>
          <abstract>
            <t>This specification defines a convention for HTTP response header fields that allow cache directives to be targeted at specific caches or classes of caches.  It also defines one such header field, the CDN-Cache-Control response header field, which is targeted at content delivery network (CDN) caches.</t>
          </abstract>
        </front>
        <seriesInfo name="RFC" value="9213"/>
        <seriesInfo name="DOI" value="10.17487/RFC9213"/>
      </reference>
      <reference anchor="JSON">
        <front>
          <title>The JavaScript Object Notation (JSON) Data Interchange Format</title>
          <author fullname="T. Bray" initials="T." role="editor" surname="Bray"/>
          <date month="December" year="2017"/>
          <abstract>
            <t>JavaScript Object Notation (JSON) is a lightweight, text-based, language-independent data interchange format. It was derived from the ECMAScript Programming Language Standard. JSON defines a small set of formatting rules for the portable representation of structured data.</t>
            <t>This document removes inconsistencies with other specifications of JSON, repairs specification errors, and offers experience-based interoperability guidance.</t>
          </abstract>
        </front>
        <seriesInfo name="STD" value="90"/>
        <seriesInfo name="RFC" value="8259"/>
        <seriesInfo name="DOI" value="10.17487/RFC8259"/>
      </reference>
      <reference anchor="URI">
        <front>
          <title>Uniform Resource Identifier (URI): Generic Syntax</title>
          <author fullname="T. Berners-Lee" initials="T." surname="Berners-Lee"/>
          <author fullname="R. Fielding" initials="R." surname="Fielding"/>
          <author fullname="L. Masinter" initials="L." surname="Masinter"/>
          <date month="January" year="2005"/>
          <abstract>
            <t>A Uniform Resource Identifier (URI) is a compact sequence of characters that identifies an abstract or physical resource.  This specification defines the generic URI syntax and a process for resolving URI references that might be in relative form, along with guidelines and security considerations for the use of URIs on the Internet.  The URI syntax defines a grammar that is a superset of all valid URIs, allowing an implementation to parse the common components of a URI reference without knowing the scheme-specific requirements of every possible identifier.  This specification does not define a generative grammar for URIs; that task is performed by the individual specifications of each URI scheme. [STANDARDS-TRACK]</t>
          </abstract>
        </front>
        <seriesInfo name="STD" value="66"/>
        <seriesInfo name="RFC" value="3986"/>
        <seriesInfo name="DOI" value="10.17487/RFC3986"/>
      </reference>
      <reference anchor="IRI">
        <front>
          <title>Internationalized Resource Identifiers (IRIs)</title>
          <author fullname="M. Duerst" initials="M." surname="Duerst"/>
          <author fullname="M. Suignard" initials="M." surname="Suignard"/>
          <date month="January" year="2005"/>
          <abstract>
            <t>This document defines a new protocol element, the Internationalized Resource Identifier (IRI), as a complement of the Uniform Resource Identifier (URI). An IRI is a sequence of characters from the Universal Character Set (Unicode/ISO 10646). A mapping from IRIs to URIs is defined, which means that IRIs can be used instead of URIs, where appropriate, to identify resources.</t>
            <t>The approach of defining a new protocol element was chosen instead of extending or changing the definition of URIs. This was done in order to allow a clear distinction and to avoid incompatibilities with existing software. Guidelines are provided for the use and deployment of IRIs in various protocols, formats, and software components that currently deal with URIs.</t>
          </abstract>
        </front>
        <seriesInfo name="RFC" value="3987"/>
        <seriesInfo name="DOI" value="10.17487/RFC3987"/>
      </reference>
      <reference anchor="RFC2119">
        <front>
          <title>Key words for use in RFCs to Indicate Requirement Levels</title>
          <author fullname="S. Bradner" initials="S." surname="Bradner"/>
          <date month="March" year="1997"/>
          <abstract>
            <t>In many standards track documents several words are used to signify the requirements in the specification.  These words are often capitalized.  This document defines these words as they should be interpreted in IETF documents.  This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
          </abstract>
        </front>
        <seriesInfo name="BCP" value="14"/>
        <seriesInfo name="RFC" value="2119"/>
        <seriesInfo name="DOI" value="10.17487/RFC2119"/>
      </reference>
      <reference anchor="RFC8174">
        <front>
          <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
          <author fullname="B. Leiba" initials="B." surname="Leiba"/>
          <date month="May" year="2017"/>
          <abstract>
            <t>RFC 2119 specifies common key words that may be used in protocol specifications.  This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
          </abstract>
        </front>
        <seriesInfo name="BCP" value="14"/>
        <seriesInfo name="RFC" value="8174"/>
        <seriesInfo name="DOI" value="10.17487/RFC8174"/>
      </reference>
    </references>
    <?line 294?>

<section anchor="acknowledgements">
      <name>Acknowledgements</name>
      <t>Thanks to Stephen Ludin for his review and suggestions.</t>
    </section>
  </back>
  <!-- ##markdown-source:
H4sIAAAAAAAAA9Vb624bR5b+309RS2MQKWDTknyJzQySlSU51oxteSR5FkEQ
GMXuIllxX5iqbtGMoDzLPMs82XznVPWVLVnOzGKxQByzu+ty7uc7p8phGAaF
LhI1FYeZeHV5+U4cyWipxGl2JRMdy0LnmTh8dxrI2cyoq2kQ51EmU4yPjZwX
YZYXhc4WS5mGy6JYhbo1L9zbC/ALY6+PDy9PboIID4vcbKbCFnEQ6JWZisKU
tjjY23u+dxB8VJt1buIpdi+UyVQRHtMmQWALmcUfZJJnWGyjbGBTaYoPv5Z5
oexUZHmw0lPxU5FHY4H/6SxWWTEWNjeFUXOLX5vU/yiMjvApytOV9D9SDMYn
nSU6Uz8HwZXKSjUNhFjmxOiIGLPThw9TMDtZ6GJZziY6f3gaHj8cYZRRq7w1
yg/AujyBhyVyphL7cEtCoyBww0NtbalCHjcVW+OCQJbFMjcgKsSOArSC7TcT
8bYWP792mnkjzcf+l9wsZKZ/49Wm/GaVQ6qJ+y1EKN4ZuTQy4+coL7OC9HQI
5RiQIfm1SqUGecTWf7MwoCL+UBrtqCYBrNfrSfX1YRBkuUmx7RVLlCxsKs5f
Hj3f39/zz+HR4dGr07c/VO/38f6H87P37y5gCOHxpG9iERlouDB5ubIY+uLk
8PzknCc//eYJLXp5eP7DyeXJsVvwYP8R3v3l4uwtPz87ePIcz+/PT/nx0fNn
T/F42jx+EwRBGIZCzoj1CNZ3udRWwO5LMhRhVyrSc62skM5jwpm0KiYnEcVS
FmIBK1/LjWA6rdixZbQU0uJjbhU0B4O5UgY/Vyb/5NaJIXGYPFaPVQJRmY2A
8OALH+0u1smE+rSiyUUuZJLka6hTL7CSVYaWovfFUmkjaqNRsPTcgCyj7CrP
rLITx1aq4zhR4PEBeZnJ4zJyFnZ9faH4p3g8eSzyeUc3NzegbA73sKJtl44t
7KVjJdR8jgVopsTmICGMljIDmQsQ8WupLL5l+E+BepGCuC0SSTheqE56oPk0
g5ygBh0puGghlthypuBdil0XK86xnJd1LZ8OkXg7g+wgsoWi/YolbGexFDlI
ByWKyNQ2tQLiyedQw1iUlsiWYDrWFLViRxR0PBFsDvhPsSVgvw2Gq3mZdCgh
S1jKK4VFjEqYELvUK7GGv7PMOipkG1hruyRicwjS0JhUkMgNbF3ib2ckJk/G
JHbtJB/B9njfLzIqyPV/ljpRIpXZRrCBgjVMSoyS8Qbmpi1iIzbYCGl40ZXR
qpBmQ/yDtVR+JH1hbT2f66hMCqZimzG81IUlEhQ5BvyBxqlPMl0lalyTCELk
QjkH29hCpTB8smpsI2R8JbMCn8m2nBfNZaQTXYDRMVmDhAKEguSheKQY4/Se
KRWzTUTginRIMkEIw1okzrFYUqIwpGmaBh6VkTNadzPZ8nrKQNLE2g46PvHU
mG3H/Cbi+hoWnpcmUuxGNjJ61qwiqo/OZmQUqRUE5l2G6b/DqxtTnXOcrdeP
yZmur2EVWRG6bzc3RAsNqF+0o1m1ApPRkOmsbOUE07KsuV6UXtDs8sz5V734
ANlQGnZrFnmeWPKVWMw2A6bCgU5aDYfC+haCh+lMKFQ9oHTGK8pEHOUZMUUO
RVpSArBBEG6wYvTm/cXlaOz+Fm/P+Pf5yd/en56fHNPvi1eHr1/XPwI/4uLV
2fvXx82vZubR2Zs3J2+P3WS8FZ1XwejN4Y/4QhIZnb27PD17e/h6RIIvOsZD
LuSCENvZyii2Rht0lPXi6N0//7H/GCr6L2Sig/3959CPe3i2/81jPKyXFJto
tzyDkNwjOWkgVyslDcfPJCF1aeR2y4HCLvN1JhDpKJp+/RNJ5uep+PMsWu0/
/s6/IIY7LyuZdV6yzLbfbE12Qhx4NbBNLc3O+56ku/Qe/th5ruTeevnn7wnJ
iXD/2fffBQHnutug7bl3PiuuH9ReGgR3gOFqhtghmQKeKjMWX3Wsvlroq10K
01t+vtOk2keT/SrV3tzsVlnDOd1MIX9oTLFdp2bbsm4BTpADO1vhJU5hRMP8
uuEkSkokbEtJlJyeHRgAk7wq8kGLHMsHh6jJkcRPXnKStxHipQ/6LWNHPMZ3
YDYfz/oBpxX/BKEk0OO2QaZp7cNBBpGOSIIlO76Vn71iXt2SnMoU44ZBHeBH
pJD9aL93ZzD1CousOZFU+UfXW9wnjo45pwGUQQsUzSpNIYXD/Wbs7ciZ0INT
ZbUncdUK5u5TDX5ARebghscPssFInjgOsjvIjdJa1Dmc1RhRcKA8tH2y74R0
0yD4rk1OqmTmd673chwpzVDJqDQnRIM3W9DNiRMIYaEKQtdItIVHQkosoICM
3xL0o/KE0Q0MfeT3H3nZcNJ2CSWljIttNqKl1pmaE3JkZEL5ArK2rL+spoVR
IEDNzJLU8c1Lv8rp3vwt89EwUMEXUDn2YyixOrwB7hyac0JBxvGCqnxJZ842
iEbCFFfgYm7ylJf8O3BTQx6ybRKjLFCqo6D9bQXtTlyCa/kmlkUCNYKj9sx9
Qhb9jWAtbE4Z9mcPhdog5H3WGtr+ZOu19CIjpX4r5mVRQsjqE1zD8pBUL5aF
x9ZtHwTJ66XubWYJUUbQI2nSAKsBacZg5WVpyIwI+o998AEuw06177GX3csD
2TcQZaoAF1cJlmAlxSHmo400eUO3gQUYjQrS92alKuZoMbKmcrXKTUHw0BvE
aFXCqEdwj3RG9cLg6An1T4YDENtJKwpVwcADt0yUWb1MJZEmfJPReB+X4sne
vtgBFBKnDZu7XGyVFqEsphR/eXZ8Nm3FVMShGcZCnIC9iKT57Bcq07y5E242
JjeAUqfzlttT3sK0HvosGNtWJdFg+YZHaYHTaLJMqY/AqF1D+F3k/2iPkhiY
s7tjv/CQ9IYFcbC3J3bO/trh3YGiPItchKprhYY+9uCZUi1NsWGekVmi+gKJ
eqIm45YcEGNI1S0ZEAV3M8qW4ydC0TqlaUBhIsm51GixydGVipxdLm49szpN
UXdiVrLZZvxA7BxyjTCgekYGPmn7WJSDbyLEle8NyiddsJtaS6VrKw5S1BrU
hf22ca8qdBz+SPG3kwiIUJWuik2VXCfi5ZcEFJ8VUVJaeuyEsTux3Ak790vH
3/WDTsBwgfReMzu4rh2RPJzjXpKv/a6v6QHhqF07RVSgbGhkoq3DSj7gtPI6
l0HkXQxx5q4eGvYotkRgeTYfZwdxrH01pDNbGNfDIZclcEYrZS6M9OQH42+1
Y9j2TwvbBkEIRz5A1I2KeU5a4ly4zpt468KhBYj4WowokI6mTKtVoSUtU8uP
261s8xwzXD5V3fhbJ94OoSz3b4VLktX4kOP1zQ3tWIuUtoWUjAGYJFHzjih9
OAc6fmWzo7evJojRkpSb2qGpW72RdKTOWDbOHFzk5twAtDDq8jPuoTzLYsM4
EtXvv/8ufkHUCK65b1rJbVQajXKSX7UZ+8l3Z+vmsieRu8vzPH84k8bPu3sQ
/vw24nE/BzdEBcBibUPJps9y1evjZt3KW5rPf16CRb4KE4gj8fbi7MClSjKE
GYp94Eln8FSpUqdf9RFuYw1D+QSla5kQvPbI00Mq7w9GMijFOpn4pbQFA0uu
qyvp17VB3ZapNvcJl22Paa7wWKdY2WVVuu/UbwMD7dzAuMljYhe0IBDJgNNx
QECdKb7KqQNIiQLrZXkW1i+IZ+psgWgkakRNhHz6nVurZ0llTJ3M3GKCw/dd
OXHsiIxzasJ47GwUQkNWWXBFK2T1PgNKyReovxr3vk3dfdA4bnqvHj2WK2f9
vMBWXqLRMWSh1jUI9J2ei8qZLhmcXT/oeX+/M1fZajdUbffheqhvSps94Jrk
oo7O1w/giGE10CcNds5ezHJP9u5utmtyaUObTARb4nCcc2uCKRcHnLJ9TOYw
Vm/u42klfF+XSWbj+hr/RyrKqZtMJxp4c0pvGjeo1wEFJe/I52AePss+C7ws
PgA6ArYTfIAj8466qEXg4a2bMe6poSqCtev7Qej7E+GB5jYxkqhmIMSUIYsy
JmbSuCxDfSPazZMDsi7P48FEXGwQqT/51MznTok/8uLVV6tE+0Ih97mtpoHc
bID7/pZPJwdu0/du00fYFIaWqv/tTR+1Nu0mq1H73G0oP9Sa2q7Zt1O8z1Nf
f35ZGkN46mJ7zPTx40edcbev9aen83uNevnZUZPJfbacNoOCyWTCzaoaIztB
/Yfk9PLszIl/h45IACnhzCukrN17CJfT9R+Z+EfnPbx91l2W1Zpj2Q06e31u
im9IFJv7UPh9nzVAWHO/mV82bfps79ne5+itc8c7g/TzqZNCVvxqKIuE7tO/
nUyEW+f+OaXa+P9/arEyVb0oW+WYXr+ok8lvqgw0Ea/yNR2Vjm/JQXTyhJqs
6ShJL2165J7mRHShsxfjgtFIPpTbvrLsUiIllOoPhXkpEng107fABuT05RF/
zbjZh7O6GfLH4/xno8d9Y9o9x+FPcZ+x399rEG+8He1ZA//ZpOhiVCJtUau1
u91uMDDxxeG5D/iuIXbrXI46Z+7MtB1x3DHqVsRxr2+LNoNd/P6xgvRNe95y
p92u7p5c3TMUeYq6YQir3BmJZO3voGqnqb0bv5/z7YgBr99tRcsxc0T9EYlK
TuqE1hk9HNV4lAtC7QSOKZYPsxwWhVhQbFQRwR1EzSVdeqirSPZdzoF9d238
D+5MrZ/61Ntr8E7TIiw1auXi1qfRULLNVMEZbBQ4c/mB7kk11uJNg29P/ZuW
wWvQlR5Z3yKIPW/3NAdHxf+JNTgmWHsyWcuNbVQufbd1yFQuuEnQ97eb9kkD
1bHdBLH+UllUtS3yhslhje2S23ejuOfVdAFdtT72y9jR2J/HNaXVdousalaa
qsXsbpE5vVLrwjXPWq3yqjBxt/P6pcgd7S3P3Jc1uNjyt5pbg+7BjS2/vJdA
a23XXba9/lcA3/A39Y5bDei6fdzuBMFrfHejd/FOstjoWkvVzuLLYD5QNJdZ
+LIMd0kGexfyLlKG7uNsXb/xdwyqu4c77m4cWZ8Uo/bdsM2ITyduuRmGQH7q
D8PxPa5D3kJlyrDzA4f6Tay/TxXDKa/gJHwSAqcJ8zmqYWdPPXHV7pr6k03f
NseGrn4uYYjcX6876+4mQtsN6Ni38oKqSzWQtOkurCORncBH2ZoRblL62OJX
q0KJP+ry7cn26cRa2kYU4wqynb55GSKk8LThs8sqbT6ZPJ1806RNIqi1/C0k
SbEsU5mFdDWPZTxwXuJVQgt27hdPt+5FdCY7gXLrc6YgN66L5EqH3dsgbhm6
59Z9f4/F3IUAFYdRNNyo758NVBNcBy/0Vx7FEswj9vDZOcWm6+vqli9dYquP
T/29Mi8O1lBuYte1XtEZbKzofNAf8821AVJTdNVZ5DBQo+laQILJht9qZZkJ
ROo4N47+yghb+jEzjSxhsJ0bGNb3ZpoDr949nW3B2Y5dd025svK+MVO3sGsz
V2pTCZKBm7OOW+4vte8l7t7jTOW2YxxLS/XPaHYbDxre3ivNDh8btLaqCsPP
LzV0XM8XQ/zdJ9/j794kYM5Xz5+EpPcs2lQ+U6gFT++wnJXVGUiqk0T7A2zH
6vMnf9o6b6u3bo4y5iXdGG71BR1ypMtUzamUt+OWmRCq2HbAP247MwUoam4N
OUX+UVU3p6ujyvY1lIpw0ETu2LugplrXwVzMf8HbuSTV40HeemvpwNUY7oY/
wuWtJxQdiF3JpHdCMRFv1bqelMKy3X1MvgJfayIl0fPRhVN5/+DibsjTi+Yj
Sl0nbqg4On7LaKaTgkbuVS9me/Tk3LtGPojLkyjOOuVjA84G0ZU/T+i2gDwa
q/BS5Xt8uuVfdbzhYG+P/lXFDVPajecOYo08i+Aw5MP18MhF7Yqm7Q+Bx2vD
ycbzX5voKH354fnkxZN5+Hiy/5df39D0mxaOOz18e0jXgrlxI/3NYNQ+b+gW
hTtHCoIPly+OP/DrgQsA3UOnZjA+RCW1/LaW9yP431TMZPSRBh9GH7N8najY
3WTnYktmH/nS5UWhVlQHvKZrZVwvkG0BmWlYJR8ElIsF3RbB6pPgX7QDASSY
NQAA

-->

</rfc>
