<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<?rfc toc="yes"?>
<?rfc tocompact="yes"?>
<?rfc tocdepth="4"?>
<?rfc tocindent="yes"?>
<?rfc symrefs="yes"?>
<?rfc sortrefs="yes"?>
<?rfc comments="yes"?>
<?rfc inline="yes"?>
<?rfc compact="yes"?>
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" category="std" docName="draft-goldstein-cdni-metadata-model-extensions-02" updates="8006,8008" ipr="trust200902" tocInclude="true" tocDepth="4" symRefs="true" sortRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.12.2 -->
  <front>
    <title abbrev="CDNI Metadata Model Extensions">CDNI Metadata Model Extensions</title>
    <seriesInfo name="Internet-Draft" value="draft-goldstein-cdni-metadata-model-extensions-02"/>
    <author fullname="Glenn Goldstein" initials="G." surname="Goldstein">
      <organization>Lumen Technologies</organization>
      <address>
        <postal>
          <street/>
          <city/>
          <region/>
          <code/>
          <country>US</country>
        </postal>
        <email>glenng1215@gmail.com</email>
      </address>
    </author>
    <author initials="W." surname="Power" fullname="Will Power">
      <organization>Lumen Technologies</organization>
      <address>
        <postal>
          <street/>
          <city/>
          <region/>
          <code/>
          <country>US</country>
        </postal>
        <email>wrpower@gmail.com</email>
      </address>
    </author>
    <author initials="G." surname="Bichot" fullname="Guillaume Bichot">
      <organization>Broadpeak</organization>
      <address>
        <postal>
          <street/>
          <city/>
          <region/>
          <code/>
          <country>France</country>
        </postal>
        <email>guillaume.bichot@gmail.com</email>
      </address>
    </author>
    <author initials="A." surname="Siloniz" fullname="Alfonso Siloniz">
      <organization>Telefonica</organization>
      <address>
        <postal>
          <street/>
          <city/>
          <region/>
          <code/>
          <country>Spain</country>
        </postal>
        <email>alfonsosiloniz@gmail.com</email>
      </address>
    </author>
    <date/>
    <abstract>
      <t>
            The Content Delivery Network Interconnection (CDNI) Metadata interface enables interconnected Content Delivery Networks (CDNs) to exchange content distribution metadata in order to enable content acquisition and delivery. To facilitate a wider set of use cases such as Open Caching, this document describes extensions to the CDNI Metadata object model and its associated Capabilities model as documented in "CDNI Metadata" RFC8006 and "CDNI Request Routing: Footprint and Capabilities Semantics" RFC8008
            .
      </t>
      <t>
           This document is a reflection of the content in the Streaming Video Alliance specification titled "SVA Configuration Interface: Part 2 Extensions to CDNI Metadata Object Model".
      </t>
    </abstract>
  </front>
  <middle>
    <section anchor="Introduction-and-Scope">
      <name>Introduction and Scope</name>
      <t>The Content Delivery Network Interconnection (CDNI) Metadata interface enables interconnected Content Delivery Networks (CDNs) to exchange content distribution metadata in order to enable content acquisition and delivery. To facilitate a wider set of use cases encountered in the commercial CDN and Open Caching ecosystems, this document describes extensions to the CDNI Metadata object model and its associated Capabilities model.</t>
      <t>The objectives of this document are:</t>
      <ol spacing="normal" type="1"><li>Identify the requirements for extending <xref target="RFC8006"/> and <xref target="RFC8008"/> and specify a set of extensions that realize these requirements.</li>
        <li>Maintain backward compatibility with <xref target="RFC8006"/> and <xref target="RFC8008"/> by not altering the definitions or semantics of the original object model. All extensions are defined as new GenericMetadata Objects.</li>
        <li>Define the metadata object model independently of the APIs used to publish and retrieve metadata.</li>
      </ol>
      <t>Scope this document ADDRESSES:</t>
      <ol spacing="normal" type="1"><li>Define and register CDNI GenericMetadata objects, as defined in section 4 of <xref target="RFC8006"/>.</li>
        <li>Define and register CDNI Payload Types, as defined in section 7.1 of <xref target="RFC8006"/>.</li>
        <li>Define Capabilities Objects that facilitate advertisement of a dCDN's support of these new metadata features, extending definitions in section 5 of <xref target="RFC8008"/>.</li>
        <li>Specification of a Metadata Expression Language <xref target="cdni-mel"/> used within the metadata object model extensions.</li>
        <li>Provide JSON examples illustrating real-world CDN and Open Caching use cases.</li>
      </ol>
      <t>Scope this document DOES NOT ADDRESS:</t>
      <ol spacing="normal" type="1"><li>Metadata object model definitions already specified in <xref target="RFC8006"/>.</li>
        <li>Interface API definitions for publishing and retrieving configuration metadata. The Metadata Interface (MI) as defined in <xref target="RFC8006"/> can be used to retrieve metadata. To enable more sophisticated metadata configuration publishing workflows, the Streaming Video Alliance (SVA) Open Caching API <xref target="OC-CI"/>, as documented in the SVA Configuration Interface Part 3 (Simple API) and Part 4 (Advanced API) specifications can be used.</li>
      </ol>
      <section anchor="terminology">
        <name>Terminology</name>
        <t>For consistency with other CDNI documents this document follows the CDNI convention of uCDN (upstream CDN) and dCDN (downstream CDN). It should be noted, however, that uCDN and dCDN are roles that can be played by a variety of entities in the distribution ecosystem. A Content Provider, for example, can play the roles of a uCDN, while a commercial CDN or Open Caching system can play either the roles of a uCDN or dCDN. Additionally, this document reuses the terminology defined in <xref target="RFC6707"/>,<xref target="RFC7336"/>, <xref target="RFC8006"/>, <xref target="RFC8007"/> and <xref target="RFC8804"/>.</t>
        <t>
        The following terms are used throughout this document:
        </t>
        <ul spacing="normal">
          <li>
    API - Application Programming Interface
</li>
          <li>
    AWS - Amazon Web Services
</li>
          <li>
    CDN - Content Delivery Network
</li>
          <li>
    CDNi - CDN Interconnect
</li>
          <li>
    CORS - Cross-Origin Resource Sharing
</li>
          <li>
    CP - Content Provider
</li>
          <li>
    dCDN - Downstream CDN
</li>
          <li>
    DNS - Domain Name System
</li>
          <li>
    FCI - Footprint and Capabilities Advertising Interface
</li>
          <li>
    HREF - Hypertext Reference (link)
</li>
          <li>
    HTTP - Hypertext Transfer Protocol
</li>
          <li>
    IETF - Internet Engineering Task Force
</li>
          <li>
    ISP - Internet Service Provider
</li>
          <li>
    JSON - JavaScript Object Notation
</li>
          <li>
    MEL - Metadata Expression Language
</li>
          <li>
    Object - A collection of properties.
</li>
          <li>
    OC - Open Caching
</li>
          <li>
    OCN - Open Caching Node
</li>
          <li>
    PatternMatch - An object which matches a string pattern
</li>
          <li>
    UA - User Agent
</li>
          <li>
    uCDN - Upstream CDN
</li>
          <li>
    URI - Uniform Resource Identifier
</li>
          <li>
    URN - Uniform Resource Name
</li>
          <li>
    VOD - Video-on-Demand
</li>
          <li>
  W3C - World Wide Web Consortium
</li>
        </ul>
      </section>
      <section>
        <name>Requirements Language</name>
        <t>
        The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
        "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" 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>
      </section>
    </section>
    <section anchor="CDNI-Metadata-Model-Extensions">
      <name>CDNI Metadata Model Extensions</name>
      <t>This section details extensions to the CDNI Metadata model as defined in Section 4 of <xref target="RFC8006"/>, expressed as a set of new GenericMetadata objects. To preserve backward compatibility with <xref target="RFC8006"/>, no changes are proposed to the original set of GenericMetadata.</t>
      <figure>
        <name>CDNI Metadata Model with Extensions</name>
        <artwork type="ascii-art"><![CDATA[
   +---------+      +---------+      +------------+
   |HostIndex++(*)+>+HostMatch++(1)+>+HostMetadata+------+(*)+-----+
   +---------+      +---------+      +------+-----+                |
                                            +                      |
                                           (*)                     +
                                            +                      V
   +-> Contains or references               V         *****************
   (1) One and only one                +---------+    *GenericMetadata*
   (*) Zero or more               +--->+PathMatch|    *     Objects   *<+
                                  |    +----+---++    ***************** |
                                  +         +   +                  ^    |
                                 (*)       (1) (1) +------------+  |    |
                                  +         +   +->+PatternMatch|  |    |
                                  |         V      +------------+  |    |
                                  |  +------------+                |    |
                                  +--+PathMetadata+------+(*)+-----+    |
                                     +------------+                     |
                                                                        |
                                                                        |
                                                                        |
                                +---------------------------------------+
                                |
                                +
          New GenericMetadata Object by Categories (SVA)
+-------------------+   +-------------------+  +---------------------+
|   Cache Control   |   |   Origin Access   |  |Client Access Control|
+-------------------+   +-------------------+  +---------------------+

+-------------------+   +-------------------+  +---------------------+
|   Edge  Control   |   | Processing Stages |  |   General Metadata  |
+-------------------+   +-------------------+  +---------------------+
  ]]></artwork>
      </figure>
      <t>The remainder of this section presents the extended set of GenericMetadata objects organized by the categories in the above diagram.</t>
      <t>Note: In the following sections, the term "mandatory-to-specify" is used to convey which properties MUST be included when serializing a given capability object.  When mandatory-to-specify is defined as "Yes" for an individual property, it means that if the object containing that property is included in a message, then the mandatory-to-specify property MUST also be included.</t>
      <section anchor="Cache-Control-Metadata">
        <name>Cache Control Metadata</name>
        <t>In addition to the cache control policies currently specified by CDNI metadata, content providers often need more fine-grained control over CDN caching, including scenarios where it is desirable to override or adjust cache-control headers from the origin. </t>
        <t>The following additional capabilities are needed for general CDN and open caching use cases:</t>
        <ol spacing="normal" type="1"><li>Positive Cache Control - Allows the uCDN to specify internal caching policies for the dCDN and external caching policies advertised to clients of the dCDN, overriding any cache control policy set in the response from the uCDN.</li>
          <li>Negative Cache Control - Allows the specification of caching policies based on error response codes received from the origin, allowing for fine-grained control of the downstream caching of error responses. For example, it may be desirable to cache error responses at the dCDN for a short period of time to prevent an overwhelmed origin service or uCDN from being flooded with requests.</li>
          <li>Cache Bypass Control - Allows content providers to bypass CDN caching when needed (typically for testing or performance benchmarking purposes).</li>
          <li>Stale Content Policies - Allows control over how the dCDN should process requests for stale content. For example, this policy allows the content provider to specify that stale content be served from cache for a specified time period while refreshes from the origin occur asynchronously. </li>
          <li>Dynamically Constructed Cache Keys - While the properties provided by the standard CDNI metadata Cache object provide some simple control over the construction of the cache key, it is typical in advanced CDN configurations to generate cache keys that are dynamically constructed via lightweight processing of various properties of the HTTP request and/or response. As an example, an origin may specify a cache key as a value returned in a specific HTTP response header. A rich expression language is provided to allow for such advanced cache key construction.</li>
        </ol>
        <section anchor="MI.CachePolicy">
          <name>MI.CachePolicy</name>
          <t>CachePolicy is a new GenericMetadata object that allows for the uCDN to specify internal caching policies for the dCDN, as well as external caching policies advertised to clients of the dCDN (overriding any cache control policy set in the response from the uCDN).</t>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property: internal  </t>
              <ul spacing="normal">
                <li>Description: Specifies the internal cache control policy to be used by the dCDN.</li>
                <li>Type: Number in seconds encoded as string (e.g. 5 is a five second cache ) and/or a list of Enumeration [as-is|no-cache|no-store]</li>
                <li>Mandatory-to-Specify: No. The default is to use the cache control policy specified in the response from the uCDN.</li>
              </ul>
            </li>
            <li>
              <t>Property: external  </t>
              <ul spacing="normal">
                <li>Description: Specifies the external cache control policy to be used by clients of this dCDN.</li>
                <li>Type: Number in seconds encoded as string (e.g. 5 is a five second cache ) and/or a list of Enumeration [as-is|no-cache|no-store]</li>
                <li>Mandatory-to-Specify: No. The default is to use the cache control policy specified in the response from the uCDN.</li>
              </ul>
            </li>
            <li>
              <t>Property: force  </t>
              <ul spacing="normal">
                <li>Description: If set to True, the metadata interface cache policy defined in the MI.CachePolicy will override any cache control policy set in the response from the uCDN. If set to False, the MI.CachePolicy is only used if there is no cache control policy provided in the response from the uCDN.</li>
                <li>Type: Boolean</li>
                <li>Mandatory-to-Specify: No. The default is "False", which will apply the MI.CachePolicy only if no policy is provided in the response from the uCDN.</li>
              </ul>
            </li>
          </ul>
          <t>Example 1: An MI.CachePolicy that sets the internal cache control policy to five seconds. The external cache policy is set to 'no-cache':</t>
          <artwork><![CDATA[{
  "generic-metadata-type": "MI.CachePolicy",
  "generic-metadata-value": {
    "internal": "5",
    "external": "no-cache",
    "force": "true"
  }
}
]]></artwork>
          <t> </t>
          <t>Example 2: An MI.CachePolicy that sets the internal cache control policy to "as-is" (keep the policy set in the response from the uCDN). The external cache policy is set to 'no-cache:</t>
          <artwork><![CDATA[{
  "generic-metadata-type": "MI.CachePolicy",
  "generic-metadata-value": {
    "internal": "as-is",
    "external": "no-cache",
    "force": "true"
  }
}
]]></artwork>
          <t>Example 3: An MI.CachePolicy in the context of the processing stages model that sets a caching policy only if the HTTP status code received from the origin is a 200. In this example, the internal cache control policy is set to five seconds. The external cache policy is set to 'no-cache'. Force is set to 'False', indicating that the MI.CachePolicy only applies if there is no cache policy in the response from the uCDN.</t>
          <artwork><![CDATA[{
  "generic-metadata-type": "MI.ProcessingStages",
  "generic-metadata-value": {
    "origin-response": [
      {
        "match": {
          "expression": "resp.status == 200"
      },
      "stage-metadata": {
          "generic-metadata": [
            {
              "generic-metadata-type": "MI.CachePolicy",
              "generic-metadata-value": {
                "internal": "5",
                "external": "no-cache",
                "force": "false"
              }
            }
          ]
        }
      }
    ]
  }
}
]]></artwork>
        </section>
        <section anchor="MI.NegativeCachePolicy">
          <name>MI.NegativeCachePolicy</name>
          <t>NegativeCachePolicy is a new GenericMetadata object that allows for the specification of caching policies based on error response codes received from the origin.</t>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property: error-codes  </t>
              <ul spacing="normal">
                <li>Description: Array of HTTP response error status codes (See Sections 6.5 and 6.6 of <xref target="RFC7231"/> , that if returned from the uCDN, will be cached using the cache policy defined by the cache-policy property.</li>
                <li>Type: Array of HTTP response error status codes</li>
                <li>Values: ["404", "503", "504"]  </li>
                <li>Mandatory-to-Specify: No. The default is to revert to <xref target="RFC8006"/> behavior.         </li>
              </ul>
            </li>
          </ul>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property: cache-policy</t>
              <ul spacing="normal">
                <li>Description: MI.CachePolicy to apply to the HTTP response error status codes returned by the uCDN.</li>
                <li>Mandatory-to-Specify: Yes</li>
              </ul>
            </li>
          </ul>
          <t>Example: A MI.NegativeCachePolicy that applies to HTTP error codes: "404", "503", "504" and sets the internal cache control policy to five seconds and external to 'no-cache'.</t>
          <artwork><![CDATA[{
  "generic-metadata-type": "MI.NegativeCachePolicy",
  "generic-metadata-value": {
    "error-codes": [ "404", "503", "504" ],
    "cache-policy": {
      "internal": "5",
      "external": "no-cache",
      "force": "true"
    }
  }
}
]]></artwork>
        </section>
        <section anchor="MI.StaleContentCachePolicy">
          <name>MI.StaleContentCachePolicy</name>
          <t>MI.StaleContentCachePolicy is a new GenericMetadata object that allows the uCDN to specify the policy to use by a dCDN when responding with stale content.  For example, this policy allows the content provider to specify that stale content be served from cache for a specified time period while refreshes from the origin occur asynchronously.</t>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property: stale-while-revalidating</t>
              <ul spacing="normal">
                <li>Description: Instructs the dCDN to serve a stale version of a resource while refreshing the resource with the uCDN. When set to "True", the dCDN will return a previously cached version of a resource while the resource is refreshed with the uCDN in the background. </li>
                <li>Type: Boolean</li>
                <li>Mandatory-to-Specify: No. The default is False, which waits for the uCDN to refresh a resource before responding to the client.   </li>
              </ul>
            </li>
            <li>
              <t>Property: stale-if-error</t>
              <ul spacing="normal">
                <li>Description: Instructs the dCDN to serve a stale version of a resource if an error was received when trying to refresh the resource with the uCDN.  When set, the dCDN will return a previously cached version of a resource instead of caching the error response.  Per Section 4 of <xref target="RFC5861"/>, an error is any situation that would result in a 500, 502, 503, or 504 HTTP response status code being returned</li>
                <li>Type: Array of HTTP response error status codes. Example: [ "503", "504"] </li>
                <li>Mandatory-to-Specify: No. The default is to cache the error response received from the uCDN.</li>
              </ul>
            </li>
            <li>
              <t>Property: failed-refresh-ttl</t>
              <ul spacing="normal">
                <li>Description: Instructs the dCDN to serve a stale version of a resource for the number of seconds specified in failed-refresh-ttl before trying to revalidate the resource with the uCDN.  Use of failed-refresh-ttl allows the load to be reduced on the uCDN during times of system stress.</li>
                <li>Type: Integer</li>
                <li>Mandatory-to-Specify: No </li>
              </ul>
            </li>
          </ul>
          <t>Example 1: A MI.StaleContentCachePolicy where stale-while-revalidating is true, instructing the dCDN to respond with a stale cached version of the resource while it refreshes the resource with the uCDN in the background:</t>
          <artwork><![CDATA[{
  "generic-metadata-type": "MI.StaleContentCachePolicy",
  "generic-metadata-value": {
    "stale-while-revalidating": true
  }
}
]]></artwork>
          <t>Example 2: A MI.StaleContentCachePolicy where stale-if-error instructs the dCDN to use the stale cached resource if it receives an error of type 503 or 504 when trying to refresh the resource with the uCDN.</t>
          <t>failed-refresh-ttl instructs the dCDN to use a five second cache TTL on the resource that receives an error when refreshing from the uCDN. That is, after five seconds, the dCDN will attempt to refresh the resource with the uCDN.</t>
          <artwork><![CDATA[{
  "generic-metadata-type": "MI.StaleContentCachePolicy",
  "generic-metadata-value": {
    "stale-if-error": [ "503", "504" ],
    "failed-refresh-ttl": "5"
  }
}
]]></artwork>
          <t>Example 3: A MI.StaleContentCachePolicy where stale-while-revalidating is true, instructing the dCDN to respond with a stale cached version of the resource while it refreshes the resource with the uCDN in the background. </t>
          <t>stale-if-error instructs the dCDN to use the stale cached resource if it receives an error of type 404, 503, or 504 when trying to refresh the resource with the uCDN.</t>
          <t>failed-refresh-ttl instructs the dCDN to use a five second cache TTL on the resource that receives an error when refreshing from the uCDN. That is, after five seconds, the dCDN will attempt to refresh the resource with the uCDN.</t>
          <artwork><![CDATA[{
  "generic-metadata-type": "MI.StaleContentCachePolicy",
  "generic-metadata-value": {
    "stale-while-revalidating": "true",
      "stale-if-error": [ "404", "503", "504" ],
      "failed-refresh-ttl": "5"
  }
}
]]></artwork>
        </section>
        <section anchor="MI.CacheBypassPolicy">
          <name>MI.CacheBypassPolicy</name>
          <t>CacheBypassPolicy is a new GenericMetadata object that allows a client request to be set as non-cacheable. It is expected that this feature will be used to allow clients to bypass cache when testing the uCDN fill path. Note: CacheBypassPolicy is typically used in conjunction with a path match or match expression on a header value or query parameter. Any content previously cached (by client requests that do not set CacheBypassPolicy) is not evicted. </t>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property:  bypass-cache</t>
              <ul spacing="normal">
                <li>Description: A Boolean value that can activate the feature for a given client request.  It is expected that this feature will be used within ProcessingStages to allow a client request to be marked to bypass cache.</li>
                <li>Type: Boolean</li>
                <li>Mandatory-to-Specify: No. The default is False.</li>
              </ul>
            </li>
          </ul>
          <t>Example 1: A MI.CacheBypassPolicy with the client HTTP header of: CDN-BYPASS:  "True":</t>
          <artwork><![CDATA[{
  "generic-metadata-type": "MI.ProcessingStages",
  "generic-metadata-value": {
    "client-request": [
      {
        "match": {
          "expression": "req.h.cdn-bypass == 'true'"
        },
        "stage-metadata": {
          "generic-metadata": [
            {
              "generic-metadata-type": "MI.CacheBypassPolicy",
              "generic-metadata-value": {
                "bypass-cache": "true"
              }
            }
          ]
        }
      }
    ]
  }
}
]]></artwork>
          <t>Example 2: A MI.CacheBypassPolicy that applies to all requests where the host header is bypass.example.com:</t>
          <artwork><![CDATA[{
  "generic-metadata-type": "MI.ProcessingStages",
  "generic-metadata-value": {
    "client-request": [
      {
        "match": {
          "expression": "req.h.host == 'bypass.example.com'"
      },
      "stage-metadata": {
          "generic-metadata": [
            {
              "generic-metadata-type": "MI.CacheBypassPolicy",
              "generic-metadata-value": {
                "bypass-cache": "true"
              }
            }
          ]
        }
      }
    ]
  }
}
]]></artwork>
        </section>
        <section anchor="MI.ComputedCacheKey">
          <name>MI.ComputedCacheKey</name>
          <t>While the properties provided by the standard CDNi metadata Cache object (See Section 4.2.6 of <xref target="RFC8006"/>) provide some simple control over the construction of the cache key, it is typical in advanced CDN configurations to generate cache keys that are dynamically constructed via lightweight processing of various properties of the HTTP request and/or response. As an example, an origin may specify a cache key as a value returned in a specific HTTP response header.</t>
          <t>ComputedCacheKey is a new GenericMetadata object that allows for the specification of a cache key using the metadata expression language. Typical use cases would involve the construction of a cache key from one or more elements of the HTTP request. In cases where both the ComputedCacheKey and the Cache object are applied, the ComputedCacheKey will take precedence.</t>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property: expression</t>
              <ul spacing="normal">
                <li>Description: The expression that specifies how the cache key shall be constructed.</li>
                <li>Type: String. An expression using [CDNI-MEL] to dynamically construct the cache key from elements of the HTTP request and/or response.</li>
                <li>Mandatory-to-Specify: Yes</li>
              </ul>
            </li>
          </ul>
          <t>Example, using a custom request header as the cache key instead of the URI path:</t>
          <artwork><![CDATA[{
  "generic-metadata-type": "MI.ComputedCacheKey",
  "generic-metadata-value": {
    "expression": "req.h.X-Cache-Key"
  }
}
]]></artwork>
        </section>
      </section>
      <section anchor="Origin-Access-Metadata">
        <name>Origin Access Metadata</name>
        <t>The CDNI metadata definitions for sources (also known as origins in the CDN industry), are extended to provide the following capabilities required:</t>
        <ol spacing="normal" type="1"><li>Designation as to whether a source requires HTTPS access.</li>
          <li>Specification of the source's TCP port number.</li>
          <li>Web root path specification for the source.</li>
          <li>Indication as to whether redirects should be followed.</li>
          <li>Support for additional forms of origin authentication.</li>
          <li>Multi-origin failover - The ability to specify a list of origins that can act as fallbacks to the primary origin. Failure rules can specify types of errors and timeout values that trigger failover.</li>
          <li>Multi-origin load balancing - The ability to specify a list of origins that can be selected by one of several balancing rules (round robin, content hash, IP hash).</li>
          <li>Specification of SNI configurations required for origin access.</li>
          <li>Specification of connection control parameters for origin access.</li>
        </ol>
        <section anchor="MI.SourceMetadataExtended">
          <name>MI.SourceMetadataExtended</name>
          <t>SourceMetadataExtended is an alternative to the CDNI standard SourceMetadata object, which adds a property to specify load balancing across multiple sources, as well as a SourceExtended sub-object with additional attributes to the CDNI standard Source object. While both SourceMetadataExtended and SourceMetadata can be provided for backward compatibility, a dCDN that advertises capability for SourceMetadataExtended will ignore SourceMetadata if both are provided for a given host or path match.</t>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property: sources</t>
              <ul spacing="normal">
                <li>Description: Sources from which the dCDN can acquire content, listed in order of preference.</li>
                <li>Type: Array of SourceExtended objects</li>
                <li>Mandatory-to-Specify: No. Default is to use static configuration, out-of-band from the CDNI metadata interface.</li>
              </ul>
            </li>
            <li>
              <t>Property:  load-balance</t>
              <ul spacing="normal">
                <li>Description: Specifies load balancing rules for the set of sources.</li>
                <li>Type: LoadBalanceMetadata object</li>
                <li>Mandatory-to-Specify: No</li>
              </ul>
            </li>
          </ul>
          <t>Example of a SourceMetadataExtended object with the associated LoadBalanceMetadata configuration object:</t>
          <artwork><![CDATA[{
  "generic-metadata-type": "MI.SourceMetadataExtended",
  "generic-metadata-value": {
    "sources": [
      {
        "endpoints": [
          "a.service123.ucdn.example",
          "b.service123.ucdn.example"
        ],
        "protocol": "http/1.1"
      },
      {
        "endpoints": [
          "origin.service123.example"
        ],
        "protocol": "http/1.1"
      }
    ],
    "load-balance": {
      "balance-algorithm": "content-hash",
      "balance-path-pattern": "^/prod/(.*)/.*\\.ts$"
    }
  }
}
]]></artwork>
          <section anchor="MI.SourceExtended">
            <name>MI.SourceExtended</name>
            <t>SourceExtended is an alternative to the CDNI standard Source object with additional metadata. It contains all the attributes of the <xref target="RFC8006"/> Source object (acquisition-auth, endpoints, and protocol), with additions specified below.</t>
            <ul empty="true" spacing="normal">
              <li>
                <t>Property: acquisition-auth  </t>
                <ul spacing="normal">
                  <li>Description: Authentication method to use when requesting content from this source. Same as <xref target="RFC8006"/>.</li>
                  <li>Type: Auth (see <xref target="RFC8006"/> Section 4.2.7 and the new MI.Auth types in this specification)</li>
                  <li>Mandatory-to-Specify: No. Default is no authentication required.</li>
                </ul>
              </li>
              <li>
                <t>Property: endpoints  </t>
                <ul spacing="normal">
                  <li>Description: Origins from which the dCDN can acquire content. If multiple endpoints are specified, they are all equal, i.e., the list is not ordered by preference. Same as <xref target="RFC8006"/>.</li>
                  <li>Type: Array of Endpoint objects (see <xref target="RFC8006"/> Section 4.3.3)</li>
                  <li>Mandatory-to-Specify: Yes..</li>
                </ul>
              </li>
              <li>
                <t>Property: protocol  </t>
                <ul spacing="normal">
                  <li>Description: Network retrieval protocol to use when requesting content from this source. Same as <xref target="RFC8006"/>.</li>
                  <li>Type: Protocol (see <xref target="RFC8006"/> Section 4.3.2)</li>
                  <li>Mandatory-to-Specify: Yes..</li>
                </ul>
              </li>
              <li>
                <t>Property: origin-host  </t>
                <ul spacing="normal">
                  <li>Description: HTTP host header to pass to the endpoints when retrieving content from a uCDN. The host MUST conform to the Domain Name System (DNS) syntax defined in <xref target="RFC1034"/> and <xref target="RFC1123"/></li>
                  <li>Type: String</li>
                  <li>Mandatory-to-Specify: No. The default is to use the host name passed by the dCDN.</li>
                </ul>
              </li>
              <li>
                <t>Property: webroot  </t>
                <ul spacing="normal">
                  <li>Description: The path element that is prepended to a resource's URI before retrieving content from a uCDN.</li>
                  <li>Type: String</li>
                  <li>Mandatory-to-Specify: No. The default is to use the original URI.</li>
                </ul>
              </li>
              <li>
                <t>Property: follow-redirects </t>
                <ul spacing="normal">
                  <li>Description: If the follow-redirects property is set to "True", HTTP redirect responses returned from a uCDN will be followed when retrieving content.  Otherwise, the HTTP redirect response is returned to the client.</li>
                  <li>Type: Boolean</li>
                  <li>Mandatory-to-Specify: No. The default is "True" (i.e., follow redirect responses from the uCDN).</li>
                </ul>
              </li>
              <li>
                <t>Property: timeout-ms</t>
                <ul spacing="normal">
                  <li>Description: A timeout (in milliseconds) to apply when connecting to a uCDN.  If the connection is not established within timeout-ms, this source is abandoned and the next source in the MI.SourceMetadataExtended sources array is tried.  Once a connection is established, timeout-ms is used on subsequent reads of data from the uCDN.</li>
                  <li>Type: Integer</li>
                  <li>Mandatory-to-Specify: No. The default is to revert to <xref target="RFC8006"/> behavior.      </li>
                </ul>
              </li>
              <li>
                <t>Property: failover-errors</t>
                <ul spacing="normal">
                  <li>Description: Array of HTTP response error status codes  (Section 6 of <xref target="RFC7231"/>), that if returned from the uCDN, will trigger a failover to the next source in the MI.SourceMetadataExtended sources array.  If the uCDN returns an HTTP error code that is not in the failover-errors array, that error code is returned to the client of the dCDN.</li>
                  <li>Type: Array of HTTP response error status codes.</li>
                  <li>Mandatory-to-Specify: No. The default is to revert to <xref target="RFC8006"/> behavior.</li>
                </ul>
              </li>
            </ul>
            <t> </t>
            <t>Example of a SourceExtended object that describes a pair of endpoints (servers) that the dCDN can use to acquire content for the applicable host and/or URI path:</t>
            <artwork><![CDATA[{
  "generic-metadata-type": "MI.SourceMetadataExtended",
  "generic-metadata-value": {
    "sources": [
      {
        "endpoints": [
          "a.service123.ucdn.example",
          "b.service123.ucdn.example:8443"
        ],
        "protocol": "https/1.1",
        "origin-host": "internal.example.com",
        "webroot": "/prod",
        "follow-redirects": false,
        "timeout-ms": 4000,
        "failover-errors": [ "502", "503", "504" ]
      },
      {
        "endpoints": [ "origin.service123.example" ],
        "protocol": "http/1.1",
        "webroot": "/prod",
        "follow-redirects": true,
        "timeout-ms": 8000
      }
    ]
  }
}
]]></artwork>
          </section>
          <section anchor="MI.LoadBalanceMetadata">
            <name>MI.LoadBalanceMetadata</name>
            <t>The LoadBalanceMetadata object defines how content acquisition requests are distributed over the SourceExtended objects listed in the SourceMetadataExtended object.</t>
            <ul empty="true" spacing="normal">
              <li>
                <t>Property: balance-algorithm</t>
                <ul spacing="normal">
                  <li>Description: Specifies the algorithm to be used when distributing content acquisition requests over the sources in a SourceMetadataExtended object. The available algorithms are random, content-hash, and ip-hash.</li>
                </ul>
              </li>
            </ul>
            <t>o   random: Requests are distributed over the sources in proportion to their associated weights.</t>
            <t>o   content-hash: Requests are distributed over the sources in a consistent fashion, based on the balance-path-pattern property.</t>
            <t>o   ip-hash: Requests are distributed over the sources in a consistent fashion based on the IP address of the client requestor.      </t>
            <ol spacing="normal" type="1"><li>Type: Enumeration [random|content-hash|ip-hash] encoded as a lowercase string.</li>
              <li>Mandatory-to-Specify: No. The default is to use sources in preference order as defined in the SourceMetadataExtended object. </li>
            </ol>
            <ul empty="true" spacing="normal">
              <li>
                <t>Property:  balance-weights</t>
                <ul spacing="normal">
                  <li>Description:  This property specifies the relative frequency that a source is used when distributing requests. For example, if there are three SourceExtended objects in a SourceMetadataExtended object with balance-weights [1, 2, 1], source 1 will receive 1/4 of the requests; source 2 will receive 2/4 of the requests; source 3 will receive 1/4 of the requests.</li>
                  <li>Type: Array of integers</li>
                  <li>Mandatory-to-Specify: No. The default is to use sources in preference order as defined in the SourceMetadataExtended object.</li>
                </ul>
              </li>
              <li>
                <t>Property:  balance-path-pattern</t>
                <ul spacing="normal">
                  <li>Description: This property specifies a regular expression pattern to apply to the URI when calculating the content hash used by the balance-algorithm. For example, "balance-path-pattern": "^/prod/(.*)/.*\.ts$" would distribute requests based on the URI but excluding the /prod prefix and the .ts segment file.</li>
                  <li>Type: String (regular expression)</li>
                  <li>Mandatory-to-Specify: No. The default is to use the original URI.</li>
                </ul>
              </li>
            </ul>
            <t>Example 1: The LoadBalanceMetadata object distributes content acquisition requests over sources using a content-hash algorithm:</t>
            <artwork><![CDATA[{
  "generic-metadata-type": "MI.LoadBalanceMetadata",
  "generic-metadata-value": {
    "balance-algorithm": "content-hash",
    "balance-path-pattern": "^/prod/(.*)/.*\\.ts$"
  }
}
]]></artwork>
            <t>Example 2: The LoadBalanceMetadata object distributes content acquisition requests over sources using the random algorithm:</t>
            <artwork><![CDATA[{
  "generic-metadata-type": "MI.LoadBalanceMetadata",
  "generic-metadata-value": {
    "balance-algorithm": "random",
    "balance-weights": [ 1, 2, 1 ]
  }
}
]]></artwork>
          </section>
        </section>
        <section anchor="MI.Auth">
          <name>MI.Auth</name>
          <t>To meet the typical industry requirements for authenticating CDNs to external origins, two new authentication types are defined.</t>
          <ul empty="true" spacing="normal">
            <li>
              <t>auth-type: MI.HeaderAuth</t>
              <ul spacing="normal">
                <li>Description: Header based authentication is used to pass an HTTP header (secret-name) and value (secret-value) to a uCDN when requesting content. The header name and value are agreed upon between parties out of band.</li>
                <li>Note: We may want to add a way to encrypt or separately communicate the secret; this could be a general capability for CDNI.</li>
                <li>auth-value: MI.HeaderAuth object specifying the header name and value (secret name, secret key) required for authenticated access to an origin. For more information, refer to the MI.HeaderAuth section below.</li>
              </ul>
            </li>
            <li>
              <t>auth-type:  MI.AWSv4Auth</t>
              <ul spacing="normal">
                <li>Description: Allows for the specification of a set of headers to be added to requests that are forwarded to an origin to enable Amazon Web Services (AWS) authentication, as documented by AWS (See Specifications &amp; Standards References).</li>
                <li>auth-value: MI.AWSv4Auth object specifying the access parameters. For more information, refer to the MI.AWSv4Auth section below.</li>
              </ul>
            </li>
          </ul>
          <section anchor="MI.HeaderAuth">
            <name>MI.HeaderAuth</name>
            <t>The HeaderAuth metadata object is used in the auth-value property of the</t>
            <t>Auth object, as defined in <xref target="RFC8006"/> section 4.2.7, and may be applied to any</t>
            <t>source by including or referencing it under its authentication property. This method of authentication provides a simple capability for a mutually agreed upon header to be added by the CDN to all requests sent to a specific origin. Note that if a dynamically generated header value is required, the RequestTransform capabilities within StageProcessing can be used.</t>
            <ul empty="true" spacing="normal">
              <li>
                <t>Property: header-name</t>
                <ul spacing="normal">
                  <li>Description: Name of the authentication header.</li>
                  <li>Type: String</li>
                  <li>Mandatory-to-Specify: Yes</li>
                </ul>
              </li>
              <li>
                <t>Property: header-value</t>
                <ul spacing="normal">
                  <li>Description: Value of the authentication header (typically a pre-shared key). Note that this value SHOULD NOT be disclosed; it SHOULD be protected by some mechanism such as a secret-sharing API, which is outside the scope of this specification.</li>
                  <li>Type: String</li>
                  <li>Mandatory-to-Specify: Yes</li>
                </ul>
              </li>
            </ul>
            <t>Example Auth object for header authentication:</t>
            <artwork><![CDATA[{
  "generic-metadata-type": "MI.SourceMetadataExtended",
  "generic-metadata-value": {
    "sources": [
      {
        "endpoints": [ "origin.example.com" ],
        "protocol": "http/1.1",
        "acquisition-auth": {
          "generic-metadata-type": "MI.Auth",
          "generic-metadata-value": {
            "auth-type": "MI.HeaderAuth",
            "auth-value": {
              "header-name": "X-Origin-Auth",
              "header-value": "SECRETKEYJKSDHFSIFUI4UFH78HW4NF7"
            }
          }
        }
      }
    ]
  }
}
]]></artwork>
          </section>
          <section anchor="MI.AWSv4Auth">
            <name>MI.AWSv4Auth</name>
            <t>The AWSv4Auth metadata object is used in the auth-value property of the Auth object as defined in <xref target="RFC8006"/> section 4.2.7, and may be applied to any source by including or referencing it under its authentication property.</t>
            <t> </t>
            <t>AWSv4 authentication causes upstream requests to have a signature applied, following the method described in <xref target="AWSv4Method"/>. A hash-based signature is calculated over the request URI and specified headers, and provided in an Authorization: header on the upstream request. The signature is tied to a pre-shared secret key specific to an AWS service, region, and key ID.</t>
            <ol spacing="normal" type="1"><li>We may want to add a way to encrypt or separately communicate the secret; this could be a general capability for CDNI.</li>
              <li>We may want to add optional properties that allow overriding the default headers to sign.</li>
              <li>We may want to add optional properties that allow the signature to be sent in a way other than with the Authorization: header (e.g., query strings are also supported).</li>
            </ol>
            <ul empty="true" spacing="normal">
              <li>
                <t>Property: access-key-id</t>
                <ul spacing="normal">
                  <li>Description: The preconfigured ID of the pre-shared authorization secret.</li>
                  <li>Type: String</li>
                  <li>Mandatory-to-Specify: Yes</li>
                </ul>
              </li>
              <li>
                <t>Property: secret-access-key</t>
                <ul spacing="normal">
                  <li>Description: The pre-shared authorization secret, which is the basis of building the signature. This is a secret key that SHOULD NOT be disclosed; it SHOULD be protected by some mechanism such as a secret-sharing API, which is outside the scope of this specification.</li>
                  <li>Type: String</li>
                  <li>Mandatory-to-Specify: Yes</li>
                </ul>
              </li>
              <li>
                <t>Property: aws-region</t>
                <ul spacing="normal">
                  <li>Description: The AWS region name that is hosting the service and shares the key ID and corresponding pre-shared secret.</li>
                  <li>Type: String</li>
                  <li>Mandatory-to-Specify: Yes</li>
                </ul>
              </li>
              <li>
                <t>Property: aws-service</t>
                <ul spacing="normal">
                  <li>Description: The AWS service name that is serving the upstream requests.</li>
                  <li>Type: String</li>
                  <li>Mandatory-to-Specify: No.  It defaults to "s3" if not specified.</li>
                </ul>
              </li>
              <li>
                <t>Property: host-name</t>
                <ul spacing="normal">
                  <li>Description: The host name to use as part of the signature calculation.</li>
                  <li>Type: String</li>
                  <li>Mandatory-to-Specify: No.  It defaults to using the value of the Host: header of the upstream request. This property is available in case the application needs to override that behavior.</li>
                </ul>
              </li>
            </ul>
            <t>Example Auth object for AWSv4 authentication:</t>
            <artwork><![CDATA[{
  "generic-metadata-type": "MI.SourceMetadataExtended",
  "generic-metadata-value": {
    "sources": [
      {
        "endpoints": [ "origin.example.com" ],
        "protocol": "http/1.1",
        "acquisition-auth": {
          "generic-metadata-type": "MI.Auth",
          "generic-metadata-value": {
            "auth-type": "MI.AWSv4Auth",
            "auth-value": {
              "access-key-id": "MYACCESSKEYID",
              "secret-access-key": "SECRETKEYJKSDHFSIUHKWRGHHF",
              "aws-region": "us-west-1"
            }
          }
        }
      }
    ]
  }
}
]]></artwork>
          </section>
        </section>
      </section>
      <section anchor="Edge-Control-Metadata">
        <name>Edge Control Metadata</name>
        <t>CDNs typically require a set of configuration metadata to inform processing of responses downstream (at the edge and in the user agent). This section specifies GenericMetadata objects to meet those requirements.</t>
        <section anchor="MI.CrossOriginPolicy">
          <name>MI.CrossOriginPolicy</name>
          <t>Delegation of traffic between a CDN over an open caching node based on HTTP redirection does change the domain name in the client requests. This represents a cross-origin request that must be managed appropriately using Cross-Origin Resource Sharing (CORS) headers in the responses.</t>
          <t>The dynamic generation of CORS headers is typical in modern HTTP request processing and avoids CORS validation forwarded to the CDN origin servers, particularly with the preflight OPTIONS requests. The CDNI metadata model requires extensions to specify how a CDN or open caching node should generate and evaluate these headers.</t>
          <t>Required capabilities:</t>
          <ol spacing="normal" type="1"><li>Set a default value for CORS response headers independent of the origin request header value.</li>
            <li>Match the origin request header with a list of valid values, including PatternMatch, to return or not return the CORS response headers. </li>
            <li>Set a list of custom headers that can be exposed to the client (expose headers).</li>
            <li>Support for preflight requests using the OPTIONS method, including custom header validation, expose headers, and methods.</li>
            <li>Support for credentials validation within CORS.</li>
          </ol>
          <t>Simple CORS requests are those where both HTTP method and headers in the request are included in the safe list defined by the World Wide Web Consortium <xref target="W3C"/>. The user agent (UA) request can include an origin header set to the URL domain of the webpage that the player runs. Depending on the metadata configuration, the logic to apply by the open caching node (OCN) is:</t>
          <ol spacing="normal" type="1"><li>Validation of the origin header - Metadata can include a list of valid domains to validate the request origin header. If it does not match, the CORS header must not be included in the response.</li>
            <li>WIldcard usage - Depending on the configuration, the resultant CORS header to include in the response will be the same as the request origin header, or a wildcard.</li>
            <li>If no validation of request is included in the origin header, set a default value for CORS response headers independent of the origin request header value.</li>
          </ol>
          <t>When a UA makes a request that includes a method or headers that are not included in the safe-list, the client will make a CORS preflight request using the OPTIONS method to the resource including the origin header. If CORS is enabled and the requests passes the origin validation, the OCN SHOULD respond with the set of headers that indicate what is permitted for that resource, including one or more of the following:</t>
          <ol spacing="normal" type="1"><li>Allowed methods</li>
            <li>Allowed credentials</li>
            <li>Allowed request headers</li>
            <li>Max age that the OPTIONS request is valid</li>
            <li>Headers that can be exposed to the client</li>
          </ol>
          <t>CrossoriginPolicy is a GenericMetadata object that allows for the specification of dynamically generated CORS headers.</t>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property: allow-origin</t>
              <ul spacing="normal">
                <li>Description: Validation of simple CORS requests.</li>
                <li>Type: Object MI.AccessControlAllowOrigin</li>
                <li>Values: One element for each of the following properties.</li>
                <li>Mandatory-to-Specify: Yes</li>
              </ul>
            </li>
            <li>
              <t>Property: expose-headers</t>
              <ul spacing="normal">
                <li>Description: A list of values the OCN will include in the Access-Control-Expose-Headers response header to a preflight request.</li>
                <li>Type: Array of strings</li>
                <li>Mandatory-to-Specify: No</li>
              </ul>
            </li>
            <li>
              <t>Property: allow-methods</t>
              <ul spacing="normal">
                <li>Description: A list of values the OCN will include in the Access-Control-Allow-Methods response header to a preflight request.</li>
                <li>Type: Array of strings</li>
                <li>Mandatory-to-Specify: No</li>
              </ul>
            </li>
            <li>
              <t>Property: allow-headers</t>
              <ul spacing="normal">
                <li>Description: A list of values the OCN will include in the Access-Control-Allow-Headers response header to a preflight request.</li>
                <li>Type: Array of strings</li>
                <li>Mandatory-to-Specify: No</li>
              </ul>
            </li>
            <li>
              <t>Property: allow-credentials</t>
              <ul spacing="normal">
                <li>Description: The value the OCN will include in the Access-Control-Allow-Credentials response header to a preflight request.</li>
                <li>Type: Boolean</li>
                <li>Mandatory-to-Specify: No</li>
              </ul>
            </li>
            <li>
              <t>Property: max-age</t>
              <ul spacing="normal">
                <li>Description: The value the OCN will include in the Access-Control-Max-Age response header to a preflight request.</li>
                <li>Type: Integer</li>
                <li>Mandatory-to-Specify: No</li>
              </ul>
            </li>
          </ul>
          <section anchor="MI.AccessControlAllowOrigin">
            <name>MI.AccessControlAllowOrigin</name>
            <t>The MI.AccessControlAllowOrigin object has the following properties:</t>
            <ul empty="true" spacing="normal">
              <li>
                <t>Property: allow-list</t>
                <ul spacing="normal">
                  <li>Description: List of valid URLs that will be used to match the request origin header. The Origin header is a HTTP extension. Its value is a version of the Referer header in some specific requests, and used for Cross Origin requests. . Permitted values are schema://hostname[:port] </li>
                  <li>Type: Array of PatternMatch objects</li>
                  <li>Mandatory-to-Specify: Yes</li>
                </ul>
              </li>
              <li>
                <t>Property: wildcard-return</t>
                <ul spacing="normal">
                  <li>Description: If "True", the OCN will include a wildcard (*) in the Access-Control-Allow-Origin response header. If "False", the OCN will reflect the request origin header in the Access-Control-Allow-Origin response header.</li>
                  <li>Type: Boolean</li>
                  <li>Mandatory-to-Specify: Yes</li>
                </ul>
              </li>
            </ul>
            <t>The examples below demonstrate how to configure response headers dynamically for CORS validation.</t>
            <t>Example 1: A simple CORS validation configuration:</t>
            <artwork><![CDATA[{
  "generic-metadata-type": "MI.CrossoriginPolicy",
  "generic-metadata-value": {
    "allow-origin": {
      "allow-list": [
        {
          "pattern": "*"
        }
      ],
      "wildcard-return": true
    }
  }
}
]]></artwork>
            <t> </t>
            <t>Example 2: Validation of a preflight request when some of the headers included in the subsequent object request are not included in the CORS specification safelist:</t>
            <artwork><![CDATA[{
  "generic-metadata-type": "MI.CrossoriginPolicy",
  "generic-metadata-value": {
    "allow-origin": {
      "allow-list": [
        {
          "pattern": "*://sourcepage.example.com"
        },
        "wildcard-return": false
      },
      "allow-methods": [ "GET", "POST" ],
      "allow-credentials": true,
      "allow-headers": [ "X-PINGOTHER", "Content-Type" ],
      "expose-headers": [ "X-User", "Authorization" ],
      "max-age": 3600
    }
  }
}
]]></artwork>
          </section>
        </section>
        <section anchor="MI.AllowCompress">
          <name>MI.AllowCompress</name>
          <t>Downstream CDNs often have the ability to compress HTTP response bodies in cases where the client has declared that it can accept compressed responses (via an Accept-Encoding header), but the source/origin has returned an uncompressed response.</t>
          <t>The specific compression algorithm used by the dCDN is negotiated by the client's Accept-Encoding header according to <xref target="RFC7694"/> (including q= preferences) and the compression capabilities available on the dCDN. </t>
          <t>In addition, HeaderTransform allows the uCDN to normalize, or modify, the Accept-Encoding header to allow for fine-grain control over the selection of the compression algorithm (e.g., gzip, compress, deflate, br, etc.).</t>
          <t>AllowCompress is a new GenericMetadata object that allows the dCDN to compress content before sending to the client.</t>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property: allow-compress</t>
              <ul spacing="normal">
                <li>Description:  If set to "True", then the dCDN will try to compress the response to the client based on the Accept-Encoding request header.</li>
                <li>Type: Boolean</li>
                <li>Values: True or False</li>
                <li>Mandatory-to-Specify: No. The default is "False".</li>
              </ul>
            </li>
          </ul>
          <t>Example 1: An MI.AllowCompress that allows manifests (*.m3u8) to be compressed by the dCDN:</t>
          <artwork><![CDATA[{
  "match": {
    "expression": "req.h.uri *= '*.m3u8'"
  },
  "stage-metadata": {
    "generic-metadata": [
      {
        "generic-metadata-type": "MI.AllowCompress",
        "generic-metadata-value": {
          "allow-compress": "true"
        }
      }
    ]
  }
}
]]></artwork>
          <t>Example 2: An MI.AllowCompress that allows manifests (*.m3u8) to be compressed by the dCDN but normalizing the client's Accept-Encoding header:</t>
          <artwork><![CDATA[{
  "match": {
    "expression": "req.h.accept-encoding *= '*gzip*'"
  },
  "stage-metadata": {
    "generic-metadata": [
      {
        "generic-metadata-type": "MI.AllowCompress",
        "generic-metadata-value": {
          "allow-compress": "true"
        }
      }
    ]
  }
}
]]></artwork>
        </section>
        <section anchor="MI.TrafficType">
          <name>MI.TrafficType</name>
          <t>Content delivery networks often apply different infrastructure, network routes, and internal metadata for different types of traffic. Delivery of large static objects (such as software downloads), may, for example, use different network routes than video stream delivery. In an HTTP adaptive bitrate video service, every video title corresponds to a set of video files and descriptors according to different video protocols, and this is independent of the type of service (Video-on-Demand, Live, Catch-up, etc.).</t>
          <t>The way the video service is consumed by the user agents can vary. For instance, a segment that belongs to a Video-on-Demand (VoD) title can be requested for every moment the content is available for the user agents to consume, while a segment of live content will be only requested as long as the time-shift duration is configured for that service. Knowing those differences, a CDN or OCN provider can implement specific strategies that will maximize performance and thereby provide more available capacity to the upstream provider. It should be noted that the dCDNs handling of the traffic types is implementation-specific and not prescribed here.</t>
          <t>TrafficType metadata defines a set of descriptors that characterize either the type or usage of the traffic, enabling CDNs and OCNs to apply any internal configuration rules without exposing an unnecessary number of internal details. Note that the interpretation of these traffic types and application of rules such as rate limiting or delivery pacing are implementation specific.</t>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property: traffic-type</t>
              <ul spacing="normal">
                <li>Description: A literal that defines the traffic type. uCDN will use the literal that is most representative of the traffic being delegated. </li>
                <li>Type: Enumeration [vod, live, object-download] encoded as lowercase string</li>
                <li>Mandatory-to-Specify: Yes</li>
              </ul>
            </li>
            <li>
              <t>Property: hints</t>
              <ul spacing="normal">
                <li>Description: Other traffic characteristics that the uCDN can indicate to the dCDN as suggestions for service optimization. Accepts free-form unconstrained values.</li>
                <li>Type: Array of strings</li>
                <li>Mandatory-to-Specify: No</li>
              </ul>
            </li>
          </ul>
          <t>A TrafficType definition example for HostMetadata:</t>
          <artwork><![CDATA[{
  "generic-metadata-type": "MI.TrafficType",
  "generic-metadata-value": {
    "traffic-type": "vod",
    "hints": [ "low-latency", "catch-up" ]
  }
}
]]></artwork>
        </section>
        <section anchor="MI.OcnSelection">
          <name>MI.OcnSelection</name>
          <t>Configuration metadata is required to permit several levels of OCN selection policies. For example, in a mobile network, several physical locations are possible (i.e., candidates) for hosting the OCN that will take charge in the delegation for the uCDN. This is the case when the cache is virtualized and deployed dynamically. Depending on the OCN selection policy (which may be a cost driver), the dCDN may attempt to favor certain types of caches at the edge, for example. The default OCN selection policy might be "best-effort". Another one might be linked to the network characteristics like "Edge" or ("average latency&lt; 10ms").</t>
          <t>OcnSelection is a new GenericMetadata object that allows the uCDN to indicate to the dCDN a preference in terms of OCN selection.</t>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property: ocn-delivery</t>
              <ul spacing="normal">
                <li>Description: Instructs the dCDN to perform delegation operating a particular medium and/or a transport arrangement.</li>
                <li>Type: Object MI.OcnDelivery</li>
                <li>Mandatory-to-Specify: No. At least one of the two properties, ocn-type or ocn-delivery, must be present.</li>
              </ul>
            </li>
            <li>
              <t>Property: ocn-type</t>
              <ul spacing="normal">
                <li>Description: Instructs the dCDN to perform delegation operating the type of open caching nodes.</li>
                <li>Type: A string corresponding to one of the open caching node types announced by the dCDN through the FCI interface.</li>
                <li>Mandatory-to-Specify: No. At least one of the two properties, ocn-type or ocn-delivery, must be present.</li>
              </ul>
            </li>
            <li>
              <t>Property: ocn-selection</t>
              <ul spacing="normal">
                <li>Description: This property enforces the selection of OCNs, considering the ocn-type and/or the ocn-delivery properties. "False" means best-effort.</li>
                <li>Type: string. "attempt-or-failed" and "attempt-or-besteffort" mean that the delegation must be attempted considering the ocn-type and/or the ocn-delivery properties. If not possible, it is considered as an error and either fails (configuration failure) or the dCDN continues with a best-effort procedure. Last, "best effort" means the dCDN tries its best to fulfil the requested ocn-selection policy.</li>
                <li>Mandatory-to-Specify: No. Best-effort is the default OCN selection policy.</li>
              </ul>
            </li>
          </ul>
          <section anchor="MI.OcnDelivery">
            <name>MI.OcnDelivery</name>
            <t>An ocn-delivery object contains the following properties:</t>
            <ul empty="true" spacing="normal">
              <li>
                <t>Property: ocn-medium</t>
                <ul spacing="normal">
                  <li>Description: Instructs the dCDN to perform delegation operating a particular medium. The following values are specified: "SATELLITE".</li>
                  <li>Type: String</li>
                  <li>Mandatory-to-Specify: No. Either the ocn-medium property or the ocn-transport property must be present.</li>
                </ul>
              </li>
              <li>
                <t>Property: ocn-transport</t>
                <ul spacing="normal">
                  <li>Description: Instructs the dCDN to perform delegation operating a particular transport arrangement. The following values are specified: "MABR".</li>
                  <li>Type: String</li>
                  <li>Mandatory-to-Specify: No. At least one of the two properties (ocn-medium or ocn-transport) must be present.</li>
                </ul>
              </li>
            </ul>
          </section>
        </section>
      </section>
      <section anchor="Processing-Stage-Metadata">
        <name>Processing Stage Metadata</name>
        <t>It is typical in CDN configurations to define matching rules and metadata that are to be applied at specific stages in the request processing pipeline. For example, it may be required to append a host header prior to forwarding a request to an origin, or modify the response returned from an origin prior to storing in the cache.</t>
        <figure>
          <name>Processing stages</name>
          <artwork type="ascii-art"><![CDATA[
        +-------+    +---------------+    +--------+
        |       +--->|A             B+--->|        |
        |       |    |               |    |  uCDN  |
        |  UA   |    |     dCDN      |    |        |
        |       |    |               |    | Source |
        |       |<---+D             C|<---+        |
        +-------+    +---------------+    +--------+
                      ]]></artwork>
        </figure>
        <t>Processing stages:</t>
        <ol spacing="normal" type="1"><li>clientRequest - Rules run on the client request prior to further processing. </li>
          <li>originRequest - Rules run prior to making a request to the origin. </li>
          <li>originResponse - Rules run after a response is received from the origin and before being placed in the cache.</li>
          <li>clientResponse - Rules run prior to sending the response to the client. If the response is from the cache, rules are applied to the response retrieved from the cache prior to sending to the client.</li>
        </ol>
        <t>Requirements:</t>
        <ol spacing="normal" type="1"><li>Header Matching - While CDNI metadata defines some basic matching rules for host names and pattern patching on paths, CDN and open caching use cases often require matching on specific fields in Hypertext Transfer Protocol (HTTP) request and response headers to set metadata. A typical example may be matching on a user agent string to set access controls or matching on a mime-type header to set caching rules. A rich expression matching syntax that allows matching on any combination of host, path, and header values covers most typical use cases.</li>
          <li>Expression  Matching - Header matching alone is not always sufficient for identifying a set of requests or responses that require specific metadata. CDN and open caching systems often require a rich set of matching rules, with full regular expressions and Boolean combinations of matching parameters for host, path, and header elements of a request. In typical CDN implementations, this capability is provided by a rich expression language that can be embedded in the metadata configurations.</li>
          <li>URI Modifications - In processing HTTP requests, modifications to the request Uniform Resource Identifier (URI) are often required for uses such as collapsing multiple paths to a common cache key or normalizing file extension naming conventions before making a request to the origin. In cases where the modified URI needs to be constructed dynamically, an expression language is provided that allows elements of requests and responses to be concatenated with string literals.</li>
          <li>Header Modifications - In processing HTTP requests, it is often required to modify HTTP request or response headers at one of the processing stages, requiring CDNI metadata to have the capability to update any field in an HTTP request or response header. It should be noted that certain HTTP headers (such as Set-Cookie) have multiple occurrences in a request or response, thereby requiring that we allow for add and replace designations for header modification. In cases where a header value needs to be constructed dynamically, an expression language is provided that allows elements of requests and responses to be concatenated with string literals. All of the following capabilities are required at each processing stage:</li>
          <li>Add Request Header Field - Add a header name/value to the request, along with any headers of the same name that may already be present.</li>
          <li>Replace Request Header Field - Add a header name/value to the request, replacing any headers of the same name that may already be present.</li>
          <li>Delete Request Header Field - Delete all occurrences of the named header from the request.</li>
          <li>Add Response Header Field - Add a header name/value to the response, along with any headers of the same name that may already be present.</li>
          <li>Replace Response Header Field - Add a header name/value to the response, replacing any headers of the same name that may already be present.</li>
          <li>Delete Response Header Field - Delete all occurrences of the named header from the response.</li>
          <li>Synthetic Responses - It is quite common in CDN configurations to specify a synthetic response be generated based on inspection of aspects of the original request or the origin response. The synthetic response capability allows for the specification of a set of response headers, a status code, and a response body. In cases where a header value or the synthetic response body needs to be constructed dynamically, an expression language is provided that allows elements of requests and responses to be concatenated with string literals.</li>
        </ol>
        <section anchor="MI.ProcessingStages">
          <name>MI.ProcessingStages</name>
          <t>A ProcessingStages object is a new GenericMetadata which describes the matching rules, metadata, and transformations to be applied at specific stages in the request processing pipeline. The processing rules and transformations are defined as a child data model referenced within a ProcessingStages object, as defined below.</t>
          <figure>
            <name>CDNi ProcessingStages metadata model with contained objects</name>
            <artwork type="ascii-art"><![CDATA[
                        +----------------+
                        |ProcessingStages|
                        +----------------+
                               (*)
                                |
       +----------------+-------+---------+----------------+
       |                |                 |                |
       v                v                 v                v
+-------------+ +-------------+ +--------------+ +--------------+
|ClientRequest| |OriginRequest| |OriginResponse| |ClientResponse|
+-------------+ +-------------+ +--------------+ +--------------+
      (*)             (*)              (*)              (*)
       |               |                |                |
       +---------------+----------------+----------------+
       |
       |                    +---------------+
       |          +-------->|ExpressionMatch|
       |          |         +---------------+
       |          |
       |          |                                 *****************
       |         (*)                           +--->*GenericMetadata*
       |    +----------+    +-------------+    |    *     Objects   *
       +--->+StageRules+--->|StageMetadata+(*)-+    *****************
            +----------+    +-------------+
                             (*)      (*)
                              |        |
                      +-------+        +-----------+
                      |                            |
                      v                            v
            +----------------+              +-----------------+
            |RequestTransform|(*)-+    +-(*)|ResponseTransform|
            +----------------+    |    |    +-----------------+
                    (*)           |    |
                     |            |    |
                     |            v    v
                     |       +---------------+
                     |       |HeaderTransform|(*)-+
                     |       +---------------+    |
                     |                            |
                     v                            |
             +-----------------+                  |
             |SyntheticResponse|(*)--+            v
             +-----------------+     |      +----------+
                                     +----->|HTTPHeader|
                                            +----------+
  ]]></artwork>
          </figure>
          <t>Each of the four processing stages is represented by an array of StageRules objects, with each StageRules object defining criteria along with metadata that MUST be applied if the match applies to "True". It should be noted that the StageRules objects in the array are evaluated and processed in order. A possible future extension to this processing model could allow for an if-else structure, where processing for a stage is halted upon the first match of a StageRules expression.</t>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property: client-request</t>
              <ul spacing="normal">
                <li>Description: Allows for the specification of conditional metadata to be applied at the client request processing stages, as defined in the Rule Processing Stages section. The StageRules in the array are evaluated in order.</li>
                <li>Type: Array of StageRules objects</li>
                <li>Mandatory-to-Specify: No</li>
              </ul>
            </li>
            <li>
              <t>Property: origin-request</t>
              <ul spacing="normal">
                <li>Description: Allows for the specification of conditional metadata to be applied at origin request processing stages, as defined in the Rule Processing Stages section. The StageRules in the array are evaluated in order.</li>
                <li>Type: Array of StageRules objects</li>
                <li>Mandatory-to-Specify: No</li>
              </ul>
            </li>
            <li>
              <t>Property: origin-response</t>
              <ul spacing="normal">
                <li>Description: Allows for the specification of conditional metadata to be applied at origin response processing stages, as defined in the Rule Processing Stages section. The StageRules in the array are evaluated in order.</li>
                <li>Type: Array of StageRules objects</li>
                <li>Mandatory-to-Specify: No</li>
              </ul>
            </li>
            <li>
              <t>Property: client-response</t>
              <ul spacing="normal">
                <li>Description: Allows for the specification of conditional metadata to be applied at client response processing stages, as defined in the Rule Processing Stages section. The StageRules in the array are evaluated in order.</li>
                <li>Type: Array of StageRules objects</li>
                <li>Mandatory-to-Specify: No</li>
              </ul>
            </li>
          </ul>
          <t>Example specifying all four processing stages. In this example, the client-request stage has two StageRules, appling one set of metadata if "ExpressionMatch1" evaluates to "True" and applying another set of metadata if "ExpressionMatch2" evaluates to "True".</t>
          <artwork><![CDATA[{
  "generic-metadata-type": "MI.ProcessingStages",
  "generic-metadata-value": {
    "client-request" : [
      {
        "match" : < ExpressionMatch1 for conditional metadata >
        "stage-metadata" : <StageMetadata1 for clientRequest stage>,
      },
      {
        "match" : <Additional ExpressionMatch2 for conditional metadata >
        "stage-metadata" : <StageMetadata2 for clientRequest stage>,
      }
    ],
    "origin-request" : [{
      "match" : <Optional ExpressionMatch for conditional metadata >
      "stage-metadata" : <StageMetadata for originRequest stage>,
    }],
    "origin-response" : [{
      "match" : <Optional ExpressionMatch for conditional metadata >
      "stage-metadata" : <StageMetadata for originResponse stage>,
    }],
    "client-response" : [{
      "match" : <Optional ExpressionMatch for conditional metadata >
      "stage-metadata" : <StageMetadata for clientResponse stage>,
    }]
  }
}
]]></artwork>
        </section>
        <section anchor="MI.StageRules">
          <name>MI.StageRules</name>
          <t>A StageRules object is used within the context of ProcessingStages to define elements in a list of match rules and stage-specific metadata and transformations that MUST be applied conditionally on a rich expression match.</t>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property: match</t>
              <ul spacing="normal">
                <li>Description: An ExpressionMatch object encapsulating a rich expression using the CDNI Metadata Expression Language [CDNI-MEL] to evaluate aspects of the HTTP request and/or response. The stage-metadata rules are only applied if the match evaluates to "True" or if no match expression is provided</li>
                <li>Type: ExpressionMatch object</li>
                <li>Mandatory-to-Specify: No. The stage-metadata rules are always applied if no match expression is provided. This would be the case when stage-metadata should be applied unconditionally within the context of the higher-level host and path matches.</li>
              </ul>
            </li>
            <li>
              <t>Property: stage-metadata</t>
              <ul spacing="normal">
                <li>Description: Specifies the set of StageMetadata to be applied at the processing stage if the match expression evaluates to "True" or is not present.</li>
                <li>Type: Array of StageMetadata objects, applied in order.</li>
                <li>Mandatory-to-Specify: Yes</li>
              </ul>
            </li>
          </ul>
          <t>An example of StageRules that are applied just after responses are received from the origin. In this example, receipt of a response status code of 304 from the origin indicates that CachePolicy metadata SHOULD be applied (as specified via an external HREF), and that response headers SHOULD be modified (X-custom-response-header added and ETag deleted).</t>
          <artwork><![CDATA[{
  "match": {
    "expression": "resp.status == 304"
  },
  "stage-metadata": {
    "generic-metadata": [
      {
        "type": "MI.CachePolicy",
        "href": "https://metadata.ucdn.example/origin_response_cache"
      }
    ],
    "response-transform": {
      "headers": {
        "add": [
          {
            "name": "X-custom-response-header",
            "value": "header-value"
          }
        ],
        "delete": [ "ETag" ]
      }
    }
  }
}
]]></artwork>
        </section>
        <section anchor="MI.ExpressionMatch">
          <name>MI.ExpressionMatch</name>
          <t>The ExpressionMatch object contains the rich expression that must evaluate to "True" for the StageMetadata to be applied for the specific StageRules. Defining expressions as stand-alone objects allows for sets of reusable match expressions to be reused via metadata reference linking.</t>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property: expression</t>
              <ul spacing="normal">
                <li>Description: A rich expression using CDNI-MEL to evaluate aspects of the HTTP request and/or response. See documentation on the Metadata Expression Language for details on the expression of matching variables and syntax.</li>
                <li>Type: String, using CDNI-MEL syntax. See the METADATA EXPRESSION LANGUAGE (CDNI-MEL) section.</li>
                <li>Mandatory-to-Specify: Yes</li>
              </ul>
            </li>
          </ul>
          <t>Example of ExpressionMatch on the referrer and user agent request headers:</t>
          <artwork><![CDATA[{
  "expression" : "req.h.user-agent *= '*Safari*' and req.h.referrer == 'www.myhost.com'"
}]]></artwork>
        </section>
        <section anchor="MI.StageMetadata">
          <name>MI.StageMetadata</name>
          <t>The StageMetadata object contains GenericMetadata and HTTP request/response transformations that MUST be applied for a StageRules match. The following table defines the processing stages where request and response transformations are possible:</t>
          <table align="left">
            <name>StageMetadata stages</name>
            <thead>
              <tr>
                <th>Stage</th>
                <th>request-transform</th>
                <th>response-transform</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>clientRequest</td>
                <td>yes</td>
                <td>yes</td>
              </tr>
              <tr>
                <td>originRequest</td>
                <td>yes</td>
                <td>yes</td>
              </tr>
              <tr>
                <td>originResponse</td>
                <td>no</td>
                <td>yes</td>
              </tr>
              <tr>
                <td>clientResponse</td>
                <td>no</td>
                <td>yes</td>
              </tr>
            </tbody>
          </table>
          <t>Note that for the stages where both request and response transformations are allowed, it is possible to specify both. This may be the case if, for example, the request URI needs alteration for cache-key generation and the response headers need to be manipulated.</t>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property: generic-metadata</t>
              <ul spacing="normal">
                <li>Description: Specifies the set of GenericMetadata to be applied for a StageRules match. A typical use case would be the application of a CachePolicy or TimeWindowACL conditionally on matching HTTP headers. Support for this capability is optional and can be advertised via feature-flags in the FCI interface.</li>
                <li>Type: Array of GenericMetadata, applied in order. Note that not all GenericMetadata object types may be applicable at all processing stages.</li>
                <li>Mandatory-to-Specify: No. The generic-metadata property would not be needed when StageMetadata is used to only specify request or response transformations, such as modifications of HTTP headers.</li>
              </ul>
            </li>
            <li>
              <t>Property: request-transform</t>
              <ul spacing="normal">
                <li>Description: Specifies a transformation to be applied to the HTTP request for a StageRules match. The transformation can be the modification of any request header and/or the modification of the URI. Modifications are applied such that downstream processing stages receive the modified HTTP request as their input. Support for this capability is optional and can be advertised via feature-flags in the FCI interface.</li>
                <li>Type: RequestTransform object</li>
                <li>Mandatory-to-Specify: No</li>
              </ul>
            </li>
            <li>
              <t>Property: response-transform</t>
              <ul spacing="normal">
                <li>Description: Specifies a transformation to be applied to the HTTP response for a StageRules match. The transformation can be the modification of any response header, HTTP response status code, or the generation of a synthetic response. Modifications are applied such that downstream processing stages receive the modified HTTP response as their input. Support for this capability is optional and can be advertised via feature-flags in the FCI interface.</li>
                <li>Type: ResponseTransform object</li>
                <li>Mandatory-to-Specify: No</li>
              </ul>
            </li>
          </ul>
          <t>Example of a StageMetadata object:</t>
          <artwork><![CDATA[{
  "generic-metadata" :  [{
    < Optional list of generic metadata to apply at this stage >
  }],
  "request-transform" : {
    "headers" : { <list of request headers to add/replace/delete> },
    "uri" : < URI rewrite, either static or dynamically constructed>
  }
  "response-transform" : {
    "headers" : { <list of response headers to add/replace/delete> },
    "response-status" : <Status either static or dynamically constructed >
  }
}
]]></artwork>
        </section>
        <section anchor="MI.RequestTransform">
          <name>MI.RequestTransform</name>
          <t>The RequestTransform object contains metadata for transforming the HTTP request for a specific StageRules object. The transformation can be the modification of any request header and/or the modification of the URI. Modifications are applied such that downstream processing stages receive the modified HTTP request as their input.</t>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property: headers</t>
              <ul spacing="normal">
                <li>Description: A HeaderTransform object specifying HTTP request headers to add, replace, or delete.</li>
                <li>Type: HeaderTransform object</li>
                <li>Mandatory-to-Specify: No</li>
              </ul>
            </li>
            <li>
              <t>Property: uri</t>
              <ul spacing="normal">
                <li>Description: Replacement value for the HTTP request.</li>
                <li>Type: String. Either a literal (static string) or an expression using CDNI-MEL to dynamically construct a URI value from elements of the HTTP request and/or response.</li>
                <li>Mandatory-to-Specify: No</li>
              </ul>
            </li>
            <li>
              <t>Property: uri-is-expression</t>
              <ul spacing="normal">
                <li>Description: Flag to signal whether the URI is a static string literal or a CDNI-MEL expression that needs to be dynamically evaluated.</li>
                <li>Type: Boolean</li>
                <li>Mandatory-to-Specify: No. The default is "False", indicating that the URI is a string literal and does not need to be evaluated.</li>
              </ul>
            </li>
          </ul>
          <t>Example of a RequestTransform object illustrating a dynamically constructed URI rewrite:</t>
          <artwork><![CDATA[{
  "request-transform" : {
    "headers" : { <Optional list of request headers to add/replace/delete> },
    "uri" :    "req.uri.path",
    "uri-is-expression" : true
 }
]]></artwork>
        </section>
        <section anchor="MI.ResponseTransform">
          <name>MI.ResponseTransform</name>
          <t>The ResponseTransform object contains metadata for transforming the HTTP response for a StageRules match. The transformation can be the modification of any response header, HTTP response status code, or the generation of a synthetic response. Modifications are applied such that downstream processing stages receive the modified HTTP response as their input.</t>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property: headers</t>
              <ul spacing="normal">
                <li>Description: A HeaderTransform object specifying HTTP response headers to add, replace, or delete.</li>
                <li>Type: HeaderTransform object</li>
                <li>Mandatory-to-Specify: No</li>
              </ul>
            </li>
            <li>
              <t>Property: response-status</t>
              <ul spacing="normal">
                <li>Description: Replacement value for the HTTP response status code.</li>
                <li>Type: Integer. Either a static integer or an expression using CDNI-MEL that evaluates to an integer to dynamically generate an HTTP status code based on elements of the HTTP request and/or response. Expressions that do not evaluate to an integer shall be considered invalid and result in no override of origin-provided response status.</li>
                <li>Mandatory-to-Specify: No</li>
              </ul>
            </li>
            <li>
              <t>Property: status-is-expression</t>
              <ul spacing="normal">
                <li>Description: Flag to signal whether the response-status is a static integer or a CDNI-MEL expression that needs to be dynamically evaluated to generate an HTTP response status code.</li>
                <li>Type: Boolean</li>
                <li>Mandatory-to-Specify: No. The default is "False", indicating that the response-status is a static integer and does not need to be evaluated.</li>
              </ul>
            </li>
            <li>
              <t>Property: synthetic</t>
              <ul spacing="normal">
                <li>Description: Specification of a complete replacement of any HTTP response that may have been generated in an earlier processing stage with a synthetic response. Use of this property to specify a synthetic response would override any response transformations or status codes specified by other properties.</li>
                <li>Type: SyntheticResponse object</li>
                <li>Mandatory-to-Specify: No</li>
              </ul>
            </li>
          </ul>
          <t>Example of a ResponseTransform object, illustrating a dynamically constructed header value that uses the expression language to concatenate the user agent and host header, and forces a 403 HTTP response status code:</t>
          <artwork><![CDATA[{
  "response-transform": {
    "headers": {
      "add": [
        {
          "name": "X-custom-response-header",
          "value": "req.h.user-agent . &#8216;-&#8216; . req.h.host",
          "value-is-expressions": true
        }
      ]
    },
    "response-status": "403"
  }
}
]]></artwork>
        </section>
        <section anchor="MI.SyntheticResponse">
          <name>MI.SyntheticResponse</name>
          <t>The SyntheticResponse object allows for the specification of a synthetic response to be generated in response to the HTTP request being processed. The synthetic response can contain a set of response headers, a status code, and a response body, and is a complete replacement for any HTTP response elements generated in an earlier processing stage.</t>
          <t> </t>
          <t>A dynamically generated Content-Length HTTP response header is generated based on the length of the generated response body.</t>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property: headers</t>
              <ul spacing="normal">
                <li>Description: An array of HTTP header objects that specify the full set of headers to be applied to the synthetic response.</li>
                <li>Type: Array of HTTP header objects</li>
                <li>Mandatory-to-Specify: No, although it would be unusual to not specify minimal standard response headers, such as Content-Type.</li>
              </ul>
            </li>
            <li>
              <t>Property: response-status</t>
              <ul spacing="normal">
                <li>Description: HTTP response status code.</li>
                <li>Type: Integer. Either a static integer or an expression using CDNI-MEL that evaluates to an integer to dynamically generate an HTTP status code based on elements of the upstream HTTP request and/or response. Expressions that do not evaluate to an integer shall be considered invalid and result in a 500 status for the synthetic response.</li>
                <li>Mandatory-to-Specify: Yes</li>
              </ul>
            </li>
            <li>
              <t>Property: status-is-expression</t>
              <ul spacing="normal">
                <li>Description: Flag to signal whether the response-status is a static integer or a CDNI-MEL expression that needs to be dynamically evaluated to generate an HTTP response status code.</li>
                <li>Type: Boolean</li>
                <li>Mandatory-to-Specify: No. The default is "False", indicating that the response-status is a static integer and does not need to be evaluated.</li>
              </ul>
            </li>
            <li>
              <t>Property: body</t>
              <ul spacing="normal">
                <li>Description: Body for the synthetic HTTP response. The response body can either be static or dynamically constructed from a rich expression.</li>
                <li>Type: String. Either a literal (static string) or an expression using CDNI-MEL to dynamically construct a response body from elements of the HTTP request and/or response.</li>
                <li>Mandatory-to-Specify: No. If absent, an empty HTTP response with a zero-value Content-Length header is generated.</li>
              </ul>
            </li>
            <li>
              <t>Property: body-is-expression</t>
              <ul spacing="normal">
                <li>Description: Flag to signal whether the synthetic response body is a static string literal or a CDNI-MEL expression that needs to be dynamically evaluated.</li>
                <li>Type: Boolean</li>
                <li>Mandatory-to-Specify: No. The default is "False", indicating that the body is a string literal and does not need to be evaluated.</li>
              </ul>
            </li>
          </ul>
          <t>Example of a SyntheticResponse object illustrating a dynamically constructed response body that uses the expression language to combine the request URI with static text and forces a 405 HTTP response status code:</t>
          <artwork><![CDATA[{
  "headers": [
    {
      "name": "content-type",
      "value": "text/plain"
    },
    {
      "name": "X-custom-response-header",
      "value": "some static value"
    }
  ],
  "response-status": "405",
  "response-body": "'Sorry, Access to resource '.req.uri.' not allowed'",
  "body-is-expression": false
}
]]></artwork>
        </section>
        <section anchor="MI.HeaderTransform">
          <name>MI.HeaderTransform</name>
          <t>The HeaderTransform object specifies how HTTP headers MUST be added, replaced, or deleted from HTTP requests and responses.</t>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property: add</t>
              <ul spacing="normal">
                <li>Description: List of HTTP headers (name/value pairs) that MUST be added to the HTTP request or response. Note that any existing headers in the request or response with the same names of those added are not affected, resulting in multiple headers with the same name.</li>
                <li>Type: Array of HTTPHeader objects containing header name/value pairs</li>
                <li>Mandatory-to-Specify: No</li>
              </ul>
            </li>
            <li>
              <t>Property: replace</t>
              <ul spacing="normal">
                <li>Description: List of HTTP headers (name/value pairs) that MUST be added to the HTTP request or response, replacing any previous headers with the same name.</li>
                <li>Type: Array of HTTPHeader objects containing header name/value pairs</li>
                <li>Mandatory-to-Specify: No</li>
              </ul>
            </li>
            <li>
              <t>Property: delete</t>
              <ul spacing="normal">
                <li>Description: List of names of HTTP headers that MUST be deleted from the</li>
                <li>HTTP request or response. If a named header appears multiple times, all occurrences are deleted.</li>
                <li>Type: Array of strings, with each string naming an HTTP header to delete</li>
                <li>Mandatory-to-Specify: No</li>
              </ul>
            </li>
          </ul>
          <t> </t>
          <t>Example of a HeaderTransform object illustrating the addition of two customer headers, the replacement of any previously provided Accept-Encoding header, and the removal of any previously provided Authorization or Accept-Language headers:</t>
          <artwork><![CDATA[{
  "add": [
    {
      "name": "X-custom-header1",
      "value": "header-value 1"
    },
    {
      "name": "X-custom-header2",
      "value": "header-value 2"
    }
  ],
  "replace": [
    {
      "name": "Accept-Encoding",
      "value": "gzip,deflate,br"
    }
  ],
  "delete": [
    "Authorization",
    "Accept-Language"
  ]
}
]]></artwork>
        </section>
        <section anchor="MI.HTTPHeader">
          <name>MI.HTTPHeader</name>
          <t>The HTTPHeader object contains a name/value pair for an HTTP header to add or replace in a request or response. The CDNI-MEL expression language can be used to dynamically generate response values.</t>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property: name</t>
              <ul spacing="normal">
                <li>Description: Name of the HTTP header.</li>
                <li>Type: String</li>
                <li>Mandatory-to-Specify: Yes</li>
              </ul>
            </li>
            <li>
              <t> Property: value</t>
              <ul spacing="normal">
                <li>Description: New value of the named HTTP header.</li>
                <li>Type: String. Either a static string or an expression using [CDNI-MEL] to dynamically construct a header value from elements of the HTTP request and/or response.</li>
                <li>Mandatory-to-Specify: Yes</li>
              </ul>
            </li>
            <li>
              <t>Property: value-is-expression</t>
              <ul spacing="normal">
                <li>Description: Flag to signal whether the value is a static string literal or a [CDNI-MEL] expression that needs to be dynamically evaluated.</li>
                <li>Type: Boolean</li>
                <li>Mandatory-to-Specify: No. The default is "False", indicating that the value is a string literal and does not need to be evaluated.</li>
              </ul>
            </li>
          </ul>
          <t>Example of an HTTPHeader illustrating a dynamically constructed header value that equals the session parameter from the query string:</t>
          <artwork><![CDATA[{
  "name": "X-custom-response-header",
  "value": "req.uri.query.session",
  "value-is-expression": true
}
]]></artwork>
        </section>
      </section>
      <section anchor="General-Metadata">
        <name>General Metadata</name>
        <t>This section documents a set of general purpose GenericMetadata objects whose use and interpretation may be specific to a CDN or Open Caching system's implementation, enabling extensibility and service differentiation for providers.</t>
        <section anchor="MI.ServiceIDs">
          <name>MI.ServiceIDs</name>
          <t>CDN configurations typically have multiple tiers of identifiers that group configurations by customer account to facilitate logging, billing, and support operations. This structure supports two tiers of identifiers (a serviceID which typically identifies a high level customer's service, and a propertyID which typically represents a logical grouping of a set of hosts within a customers' service.  It should be noted, however, that the interpretation of ServiceID and PropertyID are implementation-specific, and may not be used by all CDNs and Open Caching systems.</t>
          <t>This metadata model extension allows for the association service identifier metadata to a host or path match and to allow for these IDs to be dynamically generated via an expression language. For example, it may be necessary to extract a portion of the Request URI path to derive a service identifier (e.g.: /news/* maps to one propertyID and /movies/* maps to a different propertyID). When processing the MI.ServiceIDs metadata for a request, implementations SHOULD override any previously assigned service identifiers with those specified by this metadata.</t>
          <t>MI.ServiceIDs is a new GenericMetadata object that allows for the specification of the two tiers of CDN-specific service identifiers and service names.</t>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property: service-id</t>
              <ul spacing="normal">
                <li>Description: A provider-specific identifier for the service (typically a customer account identifier).</li>
                <li>Type: String. Either a literal (static string) or an expression using CDNI-MEL to dynamically construct the ID from elements of the HTTP request and/or response.</li>
                <li>Mandatory-to-Specify: No</li>
              </ul>
            </li>
            <li>
              <t>Property: service-id-is-expression</t>
              <ul spacing="normal">
                <li>Description: Flag to signal whether the service-id is a static string literal or a CDNI-MEL expression that needs to be dynamically evaluated.</li>
                <li>Type: Boolean</li>
                <li>Mandatory-to-Specify: No. The default is "False", indicating that the service-id is a string literal and does not need to be evaluated.</li>
              </ul>
            </li>
            <li>
              <t>Property: service-name</t>
              <ul spacing="normal">
                <li>Description: Human-readable name for the service-id.</li>
                <li>Type: String</li>
                <li>Mandatory-to-Specify: No</li>
              </ul>
            </li>
            <li>
              <t>Property: property-id</t>
              <ul spacing="normal">
                <li>Description: A provider-specific identifier for the property (typically identifies a child configuration within the parent service-id).</li>
                <li>Type: String. Either a literal (static string) or an expression using CDNI-MEL to dynamically construct the ID from elements of the HTTP request and/or response.</li>
                <li>Mandatory-to-Specify: No</li>
              </ul>
            </li>
            <li>
              <t>Property: property-id-is-expression</t>
              <ul spacing="normal">
                <li>Description: Flag to signal whether the property-id is a static string literal or a CDNI-MEL expression that needs to be dynamically evaluated.</li>
                <li>Type: Boolean</li>
                <li>Mandatory-to-Specify: No. The default is "False", indicating that the property-id is a string literal and does not need to be evaluated.</li>
              </ul>
            </li>
            <li>
              <t>Property: property-name</t>
              <ul spacing="normal">
                <li>Description: Human-readable name for the property-id.</li>
                <li>Type: String</li>
                <li>Mandatory-to-Specify: No</li>
              </ul>
            </li>
          </ul>
          <t>Example illustrating the assignment of a literal service-id along with a dynamically computed property-id that is extracted from the root element of the request URI path.</t>
          <artwork><![CDATA[{
  "generic-metadata-type": "MI.ServiceIDs",
  "generic-metadata-value": {
    "service-id": "12345",
    "service-name": "My Streaming Service",
    "property-id": "path_element(req.uri, 1)",
    "property-id-is-expression": true
  }
}
]]></artwork>
        </section>
        <section anchor="MI.PrivateFeatureList">
          <name>MI.PrivateFeatureList</name>
          <t>The dCDN may gather a certain number of private features (i.e., not [yet] adopted by SVA or considered marginal) that it may want to expose to the content provider and/or the uCDN. Although private, the announcement, selection, and configuration of this private feature could be done through the OC API.</t>
          <t>One example could be the support in OCNs of a new protocol that allows the ability to get additional insight about the user agent status (e.g., CTA Wave CMCD).</t>
          <t>As another example, Broadpeak has developed a feature called S4Streaming, and would like to give the opportunity to control that feature to the uCDN.</t>
          <t>PrivateFeatureListis a GenericMetadata configuration object as a base generic object that permits the control of private features.</t>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property: features</t>
              <ul spacing="normal">
                <li>Description: The list of feature configuration objects.</li>
                <li>Type: List (array) of MI.PrivateFeature objects .</li>
                <li>Mandatory-to-Specify: Yes</li>
              </ul>
            </li>
          </ul>
          <section anchor="MI.PrivateFeature">
            <name>MI.PrivateFeature</name>
            <t>MI.PrivateFeature object contains the following properties:</t>
            <ul empty="true" spacing="normal">
              <li>
                <t>Property: feature-oid</t>
                <ul spacing="normal">
                  <li>Description: The owner/organization that has specified that feature.</li>
                  <li>Type:  String</li>
                  <li>Mandatory-to-Specify: Yes</li>
                </ul>
              </li>
              <li>
                <t>Property: feature-type</t>
                <ul spacing="normal">
                  <li>Description: Indicates the type/name of the private feature configuration object.</li>
                  <li>Type: String</li>
                  <li>Mandatory-to-Specify: Yes</li>
                </ul>
              </li>
              <li>
                <t>Property: feature-value</t>
                <ul spacing="normal">
                  <li>Description: Feature configuration object.</li>
                  <li>Type: Format/type is defined by the value of the feature-type property above.</li>
                  <li>Mandatory-to-Specify: Yes</li>
                </ul>
              </li>
            </ul>
            <t>Note that the private features exposed by the dCDN can be advertised through a dedicated FCI object.</t>
            <t>Example, illustrating the Broadpeak S4 Streaming feature:</t>
            <artwork><![CDATA[{
  "generic-metadata-type": "MI.PrivateFeatureList",
  "generic-metadata-value": {
    "feature": {
      "feature-oid": "Broadpeak",
      "feature-type": "S4Streaming",
      "feature-value": {
        "footprint": {
          "footprint-type": "ipv4cidr",
          "footprint-value": [
            "192.0.2.0/24",
            "198.51.100.0/24"
          ]
        },
        "activation": "ON",
        "mode": "transparent",
        "policy": "bandwidth-max"
      }
    }
  }
}
]]></artwork>
          </section>
        </section>
        <section anchor="MI.RequestRouting">
          <name>MI.RequestRouting</name>
          <t>The uCDN requires the ability to indicate whether HTTP redirect, DNS redirect, and manifest rewrite are allowed, and indicate which is preferable.  This is required in cases where the uCDN would like to delegate the traffic relying on the iterative method but knows the client will not support HTTP redirect. In that case, the uCDN needs a means to force the dCDN to perform request routing based on DNS redirect (or manifest rewrite).</t>
          <t>This configuration possibility is useful only if the dCDN can advertise the mode of redirection it supports. There is an ongoing discussion in the IETF CDNI group to understand the semantics behind the redirection modes currently in Footprint &amp; Capabilities Advertising Interface (I-DNS and I-HTTP). It is not clear whether this indicates that the dCDN supports one or both delegation modes (the request routing performed by the uCDN can only be based on DNS redirect or HTTP redirect or both), or whether it indicates that the dCDN supports, as its own request routing mode, DNS redirect and/or HTTP redirect. The latter is required for this new configuration object to be valid.</t>
          <t>MI.RequestRouting is a new GenericMetadata object that allows the uCDN to force the dCDN request routing mode(s) to be applied when working in iterative redirection mode. The list of redirection modes supported by the dCDN is advertised through the  FCI.RedirectionMode object. The list of request routing modes supported by the dCDN is advertised through the  FCI.RequestRoutingMode object.</t>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property: request-routing-modes</t>
              <ul spacing="normal">
                <li>Description: Instructs the dCDN to perform request routing according to one or more preferred modes among those supported and advertised by the dCDN through the FCI.RequestRouting object. One must understand that forcing (instead of letting the dCDN request router select) one particular request routing mode may trigger some inefficiency in the request routing process. </li>
                <li>Type: List (array) of iterative request routing modes</li>
                <li>Values: "DNS", "HTTP", "MANIFEST_REWRITE"</li>
                <li>Mandatory-to-Specify: No. By default, all request routing modes supported by the dCDN can be used by the dCDN as part of its request routing process.  </li>
              </ul>
            </li>
          </ul>
          <t>Example, illustrating the uCDN forcing the dCDN to use DNS or HTTP as the method for request routing in case the uCDN performs an iterative delegation (i.e., iterative redirection mode):</t>
          <artwork><![CDATA[{
  "generic-metadata-type": "MI.RequestRouting",
  "generic-metadata-value": {
    "request-routing-modes": [ "DNS", "HTTP" ]
  }
}
]]></artwork>
        </section>
      </section>
    </section>
    <section anchor="cdni-mel">
      <name>Metadata Expression Language</name>
      <t>
  The CDNI Metadata Expression Language provides a syntax with a rich set of variables, operators, and built-in functions to facilitate use cases within the extended CDNi metadata model.
</t>
      <ul empty="true" spacing="normal">
        <li>
  Enables expression matching to dynamically determine if <xref target="Processing-Stage-Metadata">StageMetadata</xref> should be applied at a StageRules match.
  </li>
        <li>
  Enables the dynamic construction of a value to be used in scenarios such as constructing a service identifier or cache key, setting an HTTP header, rewriting a request URI, setting a response status code, or dynamically generating a response body for a SyntheticResponse.
  </li>
      </ul>
      <t>
Expressions can evaluate to a Boolean, string, or integer, depending on the use case:
</t>
      <table align="left">
        <name>CDNI MEL expressions</name>
        <thead>
          <tr>
            <th>Usage</th>
            <th>Description</th>
            <th>Evaluation Results</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>ExpressionMatch.expression</td>
            <td>Dynamically determines if StageMetadata should be applied at a specific StageRules.</td>
            <td>Boolean. Expressions that do not evaluate to True or False shall be considered as False.</td>
          </tr>
          <tr>
            <td>RequestTransform.uri</td>
            <td>Rewrites request URI that will be presented to all downstream stages.</td>
            <td>String</td>
          </tr>
          <tr>
            <td>ResponseTransform.response-status</td>
            <td>Dynamically sets a response status code to replace the status-code returned by the origin.</td>
            <td>Integer (HTTP status code)</td>
          </tr>
          <tr>
            <td>SyntheticResponse.response-status</td>
            <td>Dynamically sets a response status code for a synthetically constructed response.</td>
            <td>Integer (HTTP status code)</td>
          </tr>
          <tr>
            <td>SyntheticResponse.body</td>
            <td>Dynamically constructs a response body.</td>
            <td>String</td>
          </tr>
          <tr>
            <td>HTTPHeader.value</td>
            <td>Dynamically constructs a header value.</td>
            <td>String</td>
          </tr>
          <tr>
            <td>ComputedCacheKey.expression</td>
            <td>Dynamically constructs a cache key.</td>
            <td>String</td>
          </tr>
          <tr>
            <td>ServiceIDs.properry-id,ServiceIDs.service-id</td>
            <td>Dynamically constructs service and property identifiers.</td>
            <td>String</td>
          </tr>
        </tbody>
      </table>
      <section anchor="expression-variables">
        <name>Expression Variables</name>
        <table align="left">
          <name>CDNI MEL variables</name>
          <thead>
            <tr>
              <th>Variable</th>
              <th>Meaning</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>req.h.&lt;name&gt;</td>
              <td>Request header &lt;name&gt;</td>
            </tr>
            <tr>
              <td>req.uri</td>
              <td>Request URI (includes query string and fragment identifier, if any)</td>
            </tr>
            <tr>
              <td>req.uri.path</td>
              <td>Request URI path</td>
            </tr>
            <tr>
              <td>req.uri.pathquery</td>
              <td>Request path and query string</td>
            </tr>
            <tr>
              <td>req.uri.query</td>
              <td>Request query string</td>
            </tr>
            <tr>
              <td>req.uri.query.&lt;key&gt;</td>
              <td>Request query string value associated with &lt;key&gt;</td>
            </tr>
            <tr>
              <td>req.method</td>
              <td>Request HTTP method (GET, POST, others)</td>
            </tr>
            <tr>
              <td>resp.h.&lt;name&gt;</td>
              <td>Response header &lt;name&gt;</td>
            </tr>
            <tr>
              <td>resp.status</td>
              <td>Response status code</td>
            </tr>
          </tbody>
        </table>
      </section>
      <section anchor="expression-operators">
        <name>Expression Operators and keywords</name>
        <table align="left">
          <name>CDNI MEL expression operators</name>
          <thead>
            <tr>
              <th>Operator</th>
              <th>Type</th>
              <th>Result Type</th>
              <th>Meaning</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>==</td>
              <td>infix</td>
              <td>Boolean</td>
              <td>Equality test</td>
            </tr>
            <tr>
              <td>!=</td>
              <td>infix</td>
              <td>Boolean</td>
              <td>Inequality test</td>
            </tr>
            <tr>
              <td>!</td>
              <td>infix</td>
              <td>Boolean</td>
              <td>Logical NOT operator</td>
            </tr>
            <tr>
              <td>&gt;</td>
              <td>infix</td>
              <td>Boolean</td>
              <td>Greater than test</td>
            </tr>
            <tr>
              <td>&lt;</td>
              <td>infix</td>
              <td>Boolean</td>
              <td>Less than test</td>
            </tr>
            <tr>
              <td>&gt;=</td>
              <td>infix</td>
              <td>Boolean</td>
              <td>Greater than or equal test</td>
            </tr>
            <tr>
              <td>&lt;=</td>
              <td>infix</td>
              <td>Boolean</td>
              <td>Less than or equal</td>
            </tr>
            <tr>
              <td>*=</td>
              <td>infix</td>
              <td>Boolean</td>
              <td>Glob style match</td>
            </tr>
            <tr>
              <td>~=</td>
              <td>infix</td>
              <td>Boolean</td>
              <td>Regular expression match (see https://www.pcre.org/ for details on PCRE RegEx matching)</td>
            </tr>
            <tr>
              <td>ipmatch</td>
              <td>infix</td>
              <td>Boolean</td>
              <td>Match against IP address or CIDR (IPv4 and IPv6)</td>
            </tr>
            <tr>
              <td>+</td>
              <td>infix</td>
              <td>Numeric</td>
              <td>Addition</td>
            </tr>
            <tr>
              <td>-</td>
              <td>infix</td>
              <td>Numeric</td>
              <td>Subtraction</td>
            </tr>
            <tr>
              <td>*</td>
              <td>infix</td>
              <td>Numeric</td>
              <td>Multiplication</td>
            </tr>
            <tr>
              <td>/</td>
              <td>infix</td>
              <td>Numeric</td>
              <td>Division</td>
            </tr>
            <tr>
              <td>%</td>
              <td>infix</td>
              <td>Unsigned or Integer</td>
              <td>Modulus</td>
            </tr>
            <tr>
              <td>.</td>
              <td>infix</td>
              <td>String</td>
              <td>Concatenation</td>
            </tr>
            <tr>
              <td>? :</td>
              <td>ternary</td>
              <td>*</td>
              <td>Conditional operator: &lt;e&gt; ? &lt;v1&gt; : &lt;v2&gt;
  Evaluates &lt;v1&gt; if &lt;e&gt; is true, &lt;v2&gt; otherwise.</td>
            </tr>
            <tr>
              <td>( )</td>
              <td>grouping</td>
              <td/>
              <td>Used to override precedence and for function calls.</td>
            </tr>
          </tbody>
        </table>
        <table align="left">
          <name>CDNI MEL expression keywords</name>
          <thead>
            <tr>
              <th>Keyword</th>
              <th>Meaning</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>and</td>
              <td>Logical AND</td>
            </tr>
            <tr>
              <td>or</td>
              <td>Logical OR</td>
            </tr>
            <tr>
              <td>not</td>
              <td>Logical NOT (see also the ! operator)</td>
            </tr>
            <tr>
              <td>nil</td>
              <td>No value (distinct from empty value)</td>
            </tr>
            <tr>
              <td>true</td>
              <td>Boolean constant: true</td>
            </tr>
            <tr>
              <td>false</td>
              <td>Boolean constant: false</td>
            </tr>
          </tbody>
        </table>
      </section>
      <section anchor="expression-builtin-functions">
        <name>Expression Built-in Functions</name>
        <section anchor="functions-type-conversion">
          <name>Basic Functions: Type Conversions</name>
          <table align="left">
            <name>CDNI MEL type conversions</name>
            <thead>
              <tr>
                <th>Function</th>
                <th>Action</th>
                <th>Argument(s)</th>
                <th>Returns</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>integer(e)</td>
                <td>Converts expression to integer.</td>
                <td>1</td>
                <td>integer</td>
              </tr>
              <tr>
                <td>real(e)</td>
                <td>Converts expression to real.</td>
                <td>1</td>
                <td>real</td>
              </tr>
              <tr>
                <td>string(e)</td>
                <td>Converts expression to string.</td>
                <td>1</td>
                <td>string</td>
              </tr>
              <tr>
                <td>boolean(e)</td>
                <td>Converts expression to Boolean.</td>
                <td>1</td>
                <td>Boolean</td>
              </tr>
            </tbody>
          </table>
        </section>
        <section anchor="functions-string-conversion">
          <name>Basic Functions: String Conversions</name>
          <table align="left">
            <name>CDNI MEL string conversions</name>
            <thead>
              <tr>
                <th>Function</th>
                <th>Action</th>
                <th>Argument(s)</th>
                <th>Returns</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>upper(e)</td>
                <td>Converts a string to uppercase. Useful for case-insensitive comparisons.</td>
                <td>1</td>
                <td>string</td>
              </tr>
              <tr>
                <td>lower(e)</td>
                <td>Converts a string to lowercase. Useful for case-insensitive comparisons.</td>
                <td>1</td>
                <td>string</td>
              </tr>
            </tbody>
          </table>
        </section>
        <section anchor="functions-convenience">
          <name>Convenience Functions</name>
          <table align="left">
            <name>CDNI MEL convenience functions</name>
            <thead>
              <tr>
                <th>Function</th>
                <th>Action</th>
                <th>Argument(s)</th>
                <th>Returns</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>match(string Input, string Match)</td>
                <td>Regular expression Match is applied to Input and the matching element (if any) is returned. Empty string is returned if there is no match.
  See https://www.pcre.org/ for details on PCRE RegEx matching.</td>
                <td>2</td>
                <td>string</td>
              </tr>
              <tr>
                <td>match_replace(string Input, string Match, string Replace)</td>
                <td>Regular expression Match is applied to Input arg and replaced with the Replace arg upon successful match. Returns updated (replaced) version of Input.</td>
                <td>3</td>
                <td>string</td>
              </tr>
              <tr>
                <td>add_query(string Input, string q, string v)</td>
                <td>Add query string element q with value v to the Input string. If v is nil, then just add the query string element q.
  The query element q and value v must conform to the format defined in:  https://datatracker.ietf.org/doc/html/rfc3986</td>
                <td>2</td>
                <td>string</td>
              </tr>
              <tr>
                <td>remove_query(string Input, string q)</td>
                <td>Remove (all occurrences of) query string element q from the Input string.</td>
                <td>2</td>
                <td>string</td>
              </tr>
              <tr>
                <td>path_element(string Input, integer n)</td>
                <td>Return the path element n from Input. -1 returns the last element.</td>
                <td>2</td>
                <td>string</td>
              </tr>
              <tr>
                <td>path_element(string Input, integer n, integer m)</td>
                <td>Return the path elements from position n to m.</td>
                <td>3</td>
                <td>string</td>
              </tr>
            </tbody>
          </table>
        </section>
      </section>
      <section anchor="error-handling">
        <name>Error Handling</name>
        <section anchor="compile-error">
          <name>Compile Time Errors</name>
          <t>
  To ensure reliable service, all CDNI Metadata configurations MUST be validated for syntax errors before they are ingested into a dCDN.  That is, existing configurations should be kept as the live running configuration until the new configuration has passed validation.  If errors are detected in a new configuration, the configuration MUST be rejected.  A HTTP 500 Internal Server Error should be returned with a message that indicates the source of the error (line number, and configuration element that caused the error).
          </t>
          <t>
  Examples of compile-time errors:
          </t>
          <ol spacing="normal" type="1"><li>
  Configuration does not parse relative to the CDNI Metadata JSON schema
  </li>
            <li>
  Unknown CDNI Metadata object referenced in the configuration
  </li>
            <li>
              <t>
  CDNI Metadata object parse error
              </t>
              <ol spacing="normal" type="a"><li>
  Missing mandatory CDNI Metadata property
  </li>
                <li>
  Unknown CDNI Metadata property
  </li>
                <li>
  Incorrect type for a CDNI Metadata property value
  </li>
              </ol>
            </li>
            <li>
              <t>
  CDNI-MEL
              </t>
              <ol spacing="normal" type="a"><li>
  Unknown CDNI-MEL variable name referenced in an expression
  </li>
                <li>
  Unknown CDNI-MEL operator, key-word, or functions referenced in an expression
  </li>
                <li>
  Incorrect number of arguments used in a CDNI-MEL expression operator or function
  </li>
                <li>
  Incorrect type of argument used in a CDNI-MEL expression operator or function
  </li>
              </ol>
            </li>
          </ol>
        </section>
        <section anchor="runtime-error">
          <name>Runtime Errors</name>
          <t>
  If a runtime error is detected when processing a request, the request should be terminated, and a HTTP 500 'Internal Server Error' returned to the caller.  To avoid security leaks, sensitive information MUST be removed from the error message before it is returned to an external client.  In addition to returning the HTTP 500 error, the dCDN SHOULD log additional diagnostics information to assist in troubleshooting.
          </t>
          <t>
  Examples of runtime errors:
          </t>
          <ol spacing="normal" type="1"><li>
  Failure to allocate memory (or other server resources) when evaluating a CDNI-MEL expression
  </li>
            <li>
  Incorrect runtime argument type in a CDNI-MEL expression.  E.g., trying to convert a non-numeric string to a number
  </li>
          </ol>
        </section>
      </section>
      <section anchor="expression-examples">
        <name>Expression Examples</name>
        <section>
          <name>ComputedCacheKey</name>
          <t>Sets the MI.ComputedCacheKey to the value of the X-Cache-Key header from the client request.</t>
          <artwork><![CDATA[
{
  "generic-metadata-type": "MI.ComputedCacheKey",
  "generic-metadata-value": {
    "expression": "req.h.x-cache-key"
  }
}
  ]]></artwork>
          <t>Sets the MI.ComputedCacheKey to the lowercase version of the URI.</t>
          <artwork><![CDATA[
{
  "generic-metadata-type":  "MI.ComputedCacheKey",
  "generic-metadata-value": {
    "expression": "lower(req.uri)"
  }
}
  ]]></artwork>
        </section>
        <section>
          <name>ExpressionMatch</name>
          <t>
  ExpressionMatch where the expression is true if the user-agent (glob) matches *Safari* and the referrer equals www.example.com.
          </t>
          <artwork><![CDATA[
{
  "expression": "req.h.user-agent *= '*Safari*'
    and req.h.referrer == 'www.example.com'"
}
  ]]></artwork>
        </section>
        <section>
          <name>ResponseTransform</name>
          <t>
  Adds X-custom-response-header with a value equal to the value of user-agent - host header.
          </t>
          <artwork><![CDATA[
{
  "response-transform": {
    "headers": {
      "add": [
        {
          "name": "X-custom-response-header",
          "value": "req.h.user-agent . ' - ' . req.h.host",
          "value-is-expression": true
        }
      ],
      "response-status": "403"
  }
  }
}
  ]]></artwork>
          <t>
  Adds a Set-Cookie header with a dynamically computed cookie value (concatenating user agent and host name) and forces a 403 response.
          </t>
          <artwork><![CDATA[
{
  "response-transform":{
    "headers":{
      "add":[
      {
      "name":"Set-Cookie",
      "value":"req.h.user-agent . ' - ' . req.h.host",
      "value-is-expression":true
      }
      ]
    }
  }
}
  ]]></artwork>
        </section>
        <section>
          <name>MI.ServiceIDs</name>
          <t>
  Extracts the first path element from the URI. For example, if the URI = /789/second/third/test.txt, property-id is set to the first-path (789).
          </t>
          <artwork><![CDATA[
{
  "generic-metadata-type":"MI.ServiceIDs",
  "generic-metadata-value":{
    "service-id":"12345",
    "service-name":"My Streaming Service",
    "property-id":"path_element(req.uri, 1)",
    "property-id-is-expression":true
  }
}
  ]]></artwork>
        </section>
      </section>
    </section>
    <section anchor="CDNI-Capabilities-Extensions">
      <name>CDNI Capabilities Extensions</name>
      <t>Since not all dCDNs will be capable of supporting all the extensions proposed in this document, they need the ability to inform uCDNs about their capabilities. <xref target="RFC8008"/> (the CDNI Footprint &amp; Capabilities Interface) was designed for this purpose and is extended here to express these new capabilities.</t>
      <section anchor="FCI-Metadata-Object">
        <name>FCI Metadata Object</name>
        <t>Whenever a capability is represented as a top-level GenericMetadata object, a dCDN will be able to declare its support simply by including that object name in the capability-value list of the standard FCI.Metadata object.</t>
        <t>For each of the new GenericMetadata objects documented within the SVA Configuration Interface, the default assumption should be that the capability is not supported by the dCDN unless named within the FCI metadata object.</t>
        <t>Example: A capabilities object declaring support for several of the newly defined GenericMetadata types:</t>
        <artwork><![CDATA[{
  "capabilities": [
    {
      "capability-type": "FCI.Metadata",
      "capability-value": {
        "metadata": [
          "MI.SourceMetadataExtended",
          "MI.ProcessingStages",
          "MI.CrossoriginPolicy",
          "MI.CachePolicy",
          "MI.NegativeCachePolicy",
          "MI.PrivateFeatureList",
          "MI.RequestRouting"
        ]
      },
      "footprints": [
         < Footprint Objects >
      ]
    }
  ]
}
]]></artwork>
      </section>
      <section anchor="FCI-Model-Extensions">
        <name>FCI Model Extensions</name>
        <t>In most cases, the presence or absence of a GenericMetadata object name in FCI.Metadata (as described above), is sufficient to convey support for a capability. There are cases, however, where more fine-grained capabilities declarations are required. Specifically, a dCDN may support some, but not all, of the capabilities specified by one of the new GenericMetadata objects. In these cases, new FCI objects will be created to allow a dCDN to express these fine-grained capabilities.</t>
        <section anchor="FCI.AuthTypes">
          <name>FCI.AuthTypes</name>
          <t>The AuthTypes object is used to indicate the support of authentication methods to be used for content acquisition (while interacting with an origin server) and authorization methods to be used for content delivery.</t>
          <t>This specification document defines two new authentication methods (see MI.Auth) while there is one authorization method currently under specification in CDNI called <xref target="URI.signing"/></t>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property: stage-metadata </t>
              <ul spacing="normal">
                <li>Description: Specifies the set of StageMetadata to be applied at the processing stage if the match expression evaluates to "True" or is not present.</li>
                <li>Type: Array of StageMetadata objects, applied in order.</li>
                <li>Mandatory-to-Specify: Yes</li>
              </ul>
            </li>
            <li>
              <t>Property: authe-types</t>
              <ul spacing="normal">
                <li>Description: List of supported authentication methods (possibly required for content acquisition) </li>
                <li>Type: Array of strings</li>
                <li>Values: "AWSv4Auth", "HeaderAuth"</li>
                <li>Mandatory-to-Specify: No.  No authentication method is supported in this case.</li>
              </ul>
            </li>
            <li>
              <t>Property: autho-types</t>
              <ul spacing="normal">
                <li>Description: List of supported authorization methods (possibly required for content delivery) </li>
                <li>Type: Array of strings</li>
                <li>Values: "UriSigning"</li>
                <li>Mandatory-to-Specify: No.  No authorization method is supported in this case.</li>
              </ul>
            </li>
          </ul>
          <t>FCI.AuthTypes example:</t>
          <artwork><![CDATA[{
  "capabilities": [
    {
      "capability-type": "FCI.AuthTypes",
      "capability-value": {
        "authe-types": [
          "AWSv4Auth",
          "HeaderAuth"
        ],
        "autho-types": [
          "UriSigning"
        ]
      }
    }
  ]
}
]]></artwork>
        </section>
        <section anchor="FCI.ProcessingStages">
          <name>FCI.ProcessingStages</name>
          <t>This object is used to signal the set of features that are supported in relation to the ProcessingStages configuration object (see MI.ProcessingStages). Those optional features depend on the CDNI-MEL language support.</t>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property: features</t>
              <ul spacing="normal">
                <li>Description: List of supported optional processing stages features. Note that these features all have some dependencies on support of the CDNI MEL expression language. </li>
                <li>Type: Array of strings</li>
                <li>Values: "ExpressionMatch", "RequestTransform",  "ResponseTransform"</li>
                <li>Mandatory-to-Specify: No. None of these optional features are supported in this case.</li>
              </ul>
            </li>
          </ul>
          <t>Example:</t>
          <artwork><![CDATA[{
  "capabilities": [
    {
       "capability-type": "FCI.ProcessingStages",
       "capability-value": {
         "features": [
           "ExpressionMatch",
           "RequestTransform",
           "ResponseTransform"
         ]
       }
     }
  ]
}
]]></artwork>
        </section>
        <section anchor="FCI.SourceMetadataExtended">
          <name>FCI.SourceMetadataExtended</name>
          <t>This object is used to signal the supported features related to the SourceMetadataExtended configuration object. </t>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property: load-balance  </t>
              <ul spacing="normal">
                <li>Description: List of supported load balancing algorithms in relation to the SourceMetadataExtended configuration object (see MI.SourceMetadataExtended)</li>
                <li>Type: Array of strings</li>
                <li>Values: "random", "content-hash", "ip-hash</li>
                <li>Mandatory-to-Specify: No. load balancing is not supported among sources.</li>
              </ul>
            </li>
          </ul>
          <t>If the FCI.SourceMetadtaExtended object is not exposed/advertised or if the "load-balance" array is empty, the dCDN does not support the usage of the load-balance property attached to the SourceMetadataExtended configuration object (see MI.SourceMetadataExtended).</t>
          <t>Example:</t>
          <artwork><![CDATA[{
  "capabilities": [
    {
      "capability-type": "FCI.SourceMetadataExtended",
      "capability-value": {
        "load-balance": [
          "random",
          "content-hash",
          "ip-hash"
        ]
      }
    }
  ]
}
]]></artwork>
        </section>
        <section anchor="FCI.RequestRouting">
          <name>FCI.RequestRouting</name>
          <t>This object is used by the dCDN to signal/announce the supported request routing modes. This can be optionally used by the uCDN to further select a subset of those modes when operating one of the iterative delegation modes. See the section on the GenericMetadata RequestRouting object..</t>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property: request-routing-modes</t>
              <ul spacing="normal">
                <li>Description: List of supported request routing modes by the dCDN. This information is useful when the uCDN decides to perform a delegation in iterative mode.</li>
                <li>Type: Array of strings</li>
                <li>Values: "DNS", "HTTP-R", "MANIFEST_REWRITE"</li>
                <li>Mandatory-to-Specify: No. If the dCDN does not advertise the supported request routing modes, they are all supported by default.</li>
              </ul>
            </li>
          </ul>
          <t>Example:</t>
          <artwork><![CDATA[{
  "capabilities": [
    {
      "capability-type": "FCI.RequestRouting",
      "capability-value": {
        "request-routing-modes": [
          "DNS",
          "HTTP",
          "MANIFEST_REWRITE"
        ]
      }
    }
  ]
}
]]></artwork>
        </section>
        <section anchor="FCI.PrivateFeatures">
          <name>FCI.PrivateFeatures</name>
          <t>This object is used by the dCDN to signal/announce the list of supported private features. See the section on the GenericMetadata PrivateFeatureList object.</t>
          <ul empty="true" spacing="normal">
            <li>
              <t>Property: features</t>
              <ul spacing="normal">
                <li>Description: The list of supported private feature</li>
                <li>Type: List nested objects of FCI.PrivateFeature</li>
              </ul>
            </li>
          </ul>
          <t> </t>
          <t>Example:</t>
          <artwork><![CDATA[{
  "capabilities": [
    {
      "capability-type": "FCI.PrivateFeatures",
      "capability-value": {
        "features": [
          {
            "feature-oid": "Broadpeak",
            "feature-type": "S4Streaming"
         }
        ]
      }
    }
  ]
}
]]></artwork>
          <section anchor="FCI.PrivateFeature">
            <name>FCI.PrivateFeature</name>
            <t>This object contains the following properties:</t>
            <ul empty="true" spacing="normal">
              <li>
                <t>Property: feature-oid</t>
                <ul spacing="normal">
                  <li>Description: The owner/organization that has specified the feature.</li>
                  <li>Type:  String</li>
                  <li>Mandatory-to-Specify: Yes</li>
                </ul>
              </li>
              <li>
                <t>Property: feature-type</t>
                <ul spacing="normal">
                  <li>Description: Indicates the type/name of the private feature configuration object.</li>
                  <li>Type: String</li>
                  <li>Mandatory-to-Specify: Yes</li>
                </ul>
              </li>
            </ul>
          </section>
        </section>
        <section anchor="FCI.OcnSelection">
          <name>FCI.OcnSelection</name>
          <t>This object is used by the dCDN to signal/announce the supported OCN types and/or  their transport arrangement and/or medium supported by OCNs.</t>
          <t>Property ocn-delivery-list</t>
          <ol spacing="normal" type="1"><li>Description: List of supported medium and/or transport arrangements.</li>
            <li>Type: Array of nested objects, each containing the following properties:</li>
          </ol>
          <ul empty="true" spacing="normal">
            <li>
              <t>o   Property: ocn-medium</t>
              <ul spacing="normal">
                <li>Description: This property lists the supported mediums.</li>
                <li>Type: Array of strings. The following values are specified: "SATELLITE"</li>
                <li>Mandatory-to-Specify: No</li>
              </ul>
            </li>
            <li>
              <t>o   Property: ocn-transport</t>
              <ul spacing="normal">
                <li>Description: Instructs the dCDN to perform delegation operating a particular transport arrangement. The following values are specified: "MABR".</li>
                <li>Type: Array of strings</li>
                <li>Mandatory-to-Specify: No</li>
              </ul>
            </li>
            <li>.....Property: ocn-type-list</li>
          </ul>
          <t>o   Description: List of supported OCN types. Examples include: "HOME" or "EDGE".</t>
          <t>o   Type: Array of strings</t>
          <t>o   Mandatory-to-Specify: No</t>
        </section>
      </section>
    </section>
    <section anchor="IANA">
      <name>IANA Considerations</name>
      <section anchor="IANA.cdni.payload.types">
        <name>CDNI Payload Types</name>
        <t>
          This document requests the registration of the following entries under the "CDNI Payload Types" registry hosted by IANA
        </t>
        <table align="left">
          <name>Payload Types</name>
          <thead>
            <tr>
              <th>Payload type</th>
              <th>Specification</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>MI.CachePolicy</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.NegativeCachePolicy</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.StaleContentCachePolicy</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.CacheBypassPolicy</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.ComputedCacheKey</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.AllowCompress</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.SourceMetadataExtended</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.SourceExtended</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.LoadBalanceMetadata</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.HeaderAuth</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.AWSv4Auth</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.CrossOriginPolicy</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.AuthTokenMetadata (TBD)</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.CertificateMetadata (TBD)</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.OcnSelection</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.RequestRouting</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.ProcessingStages</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.StageRules</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.ExpressionMatch</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.StageMetadata</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.RequestTransform</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.ResponseTransform</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.SyntheticResponse</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.HeaderTransform</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.HTTPHeader</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.ServiceIDs</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.TrafficType</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.LoggingMetadata (TBD)</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>MI.PrivateFeatureList</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>FCI.AuthTypes</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>FCI.ProcessingStages</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>FCI.SourceMetadataExtended</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>FCI.RequestRouting</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>FCI.PrivateFeatures</td>
              <td>RFCthis</td>
            </tr>
            <tr>
              <td>FCI.OcnSelection</td>
              <td>RFCthis</td>
            </tr>
          </tbody>
        </table>
      </section>
    </section>
    <section anchor="Security">
      <name>Security Considerations</name>
      <t>
        This specification is in accordance with the CDNI Request Routing:
        Footprint and Capabilities Semantics. As such, it is subject to the security and privacy considerations as
        defined in Section 8 of
        <xref target="RFC8006"/>
        and in Section 7 of
        <xref target="RFC8008"/>
        respectively.
      </t>
    </section>
    <section anchor="Conclusion">
      <name>Conclusion</name>
      <t>This document presents requirements and extensions to the CDNI metadata model to cover typical use cases found in the commercial CDN and Open Caching ecosystems. By limiting the scope of these extensions to new GenericMetadata objects, backward compatibility can be maintained with any existing CDNI Metadata Interface implementations.</t>
    </section>
  </middle>
  <back>
    <references>
      <name>References</name>
      <references>
        <name>Normative References</name>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.1034.xml"/>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.1123.xml"/>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml"/>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7231.xml"/>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8006.xml"/>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8007.xml"/>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8008.xml"/>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml"/>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8804.xml"/>
        <reference anchor="W3C" target="https://www.w3.org/TR/2020/SPSD-cors-20200602/">
          <front>
            <title>Cross-Origin Resource Sharing</title>
            <author/>
            <date/>
          </front>
        </reference>
        <reference anchor="URI.signing" target="http://www.ietf.org/internet-drafts/draft-ietf-cdni-uri-signing-19.txt">
          <front>
            <title>URI Signing for CDN Interconnection (CDNI)</title>
            <author initials="R." surname="van Brandenburg" fullname="Ray van Brandenburg"/>
            <author initials="K." surname="Leung" fullname="Kent Leung"/>
            <author initials="P." surname="Sorber" fullname="Phil Sorber"/>
            <date month="10" year="2019" day="08"/>
          </front>
        </reference>
      </references>
      <references>
        <name>Informative References</name>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.5861.xml"/>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.6707.xml"/>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7336.xml"/>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7694.xml"/>
        <reference anchor="SVA" target="https://www.streamingvideoalliance.org">
          <front>
            <title>Streaming Video Alliance Home Page</title>
            <author/>
            <date/>
          </front>
        </reference>
        <reference anchor="AWSv4Method" target="https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html">
          <front>
            <title>Authenticating Requests (AWS Signature Version 4)</title>
            <author/>
            <date/>
          </front>
        </reference>
        <reference anchor="OC-CI" target="">
          <front>
            <title>Open Caching - Configuration Interface Functional Specification (Parts 1,2,3)</title>
            <author initials="G." surname="Goldstein" fullname="Glenn Goldstein" role="editor">
              <organization>Lumen Technologies</organization>
            </author>
            <author initials="W." surname="Power" fullname="Will Power">
              <organization>Lumen Technologies</organization>
            </author>
            <author initials="G." surname="Bichot" fullname="Guillaume Bichot">
              <organization>Broadpeak</organization>
            </author>
            <author initials="A." surname="Siloniz" fullname="Alfonso Siloniz">
              <organization>Telefonica</organization>
            </author>
            <date day="2" month="July" year="2021"/>
          </front>
          <seriesInfo name="Version" value="0.1"/>
        </reference>
      </references>
    </references>
  </back>
</rfc>
