RFC 8007

Content Delivery Network Interconnection (CDNI) Control Interface / Triggers

๐Ÿ“… published December 2016, from ietf

RFC 8007: Content Delivery Network Interconnection (CDNI) Control Interface / Triggers ๐ŸŽ€

okay bestie, this is the title block ๐Ÿ’…

  • Series: Internet Engineering Task Force (IETF) ๐ŸŒธ
  • Request for Comments: 8007 โœจ
  • Authors: R. Murray and B. Niven-Jenkins, both at Nokia ๐Ÿซถ
  • Category: Standards Track (so it's an actual Internet standard, not just a suggestion ๐Ÿ‘‘)
  • ISSN: 2070-1721
  • Date: December 2016 ๐ŸŽ„
  • Obsoletes / Updates: nothing listed in the title block ๐Ÿฆ‹

Abstract ๐ŸŒธ

so this doc is about the bit of the Content Delivery Network Interconnection (CDNI) Control interface that lets one CDN trigger stuff in another CDN that's delivering content on its behalf ๐Ÿงš. the upstream CDN can ask the downstream CDN to pre-position metadata or content, or to invalidate or purge metadata or content ๐Ÿ’–. and the upstream CDN can keep an eye on how that triggered activity is going in the downstream CDN ๐Ÿ‘€. main character energy, honestly ๐Ÿ’…

Status of This Memo ๐Ÿ“œ

this is an Internet Standards Track document ๐Ÿ”ฅ

it's a product of the Internet Engineering Task Force (IETF) and it represents the consensus of the IETF community ๐Ÿซถ. it got public review and was approved for publication by the Internet Engineering Steering Group (IESG) โœจ. if you want more info on Internet Standards, check Section 2 of RFC 7841 ๐ŸŒˆ

for the current status of this document, any errata, and how to send feedback, go to http://www.rfc-editor.org/info/rfc8007 ๐Ÿฆ‹

Copyright (c) 2016 IETF Trust and the persons identified as the document authors. All rights reserved. ๐Ÿ’œ

this document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) as in effect on the date of publication ๐Ÿ“š. please actually read these, bestie, because they explain your rights and restrictions for this doc ๐Ÿ™ˆ. code components pulled out of this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions, and they come without warranty as described in the Simplified BSD License ๐Ÿ“

Table of Contents ๐Ÿ—‚๏ธ

1. Introduction ....................................................3
   1.1. Terminology ................................................4
2. Model for CDNI Triggers .........................................4
   2.1. Timing of Triggered Activity ...............................6
   2.2. Scope of Triggered Activity ................................7
        2.2.1. Multiple Interconnected CDNs ........................7
   2.3. Trigger Results ............................................8
3. Collections of Trigger Status Resources .........................9
4. CDNI Trigger Interface .........................................10
   4.1. Creating Triggers .........................................11
   4.2. Checking Status ...........................................12
        4.2.1. Polling Trigger Status Resource Collections ........12
        4.2.2. Polling Trigger Status Resources ...................13
   4.3. Canceling Triggers ........................................13
   4.4. Deleting Triggers .........................................14
   4.5. Expiry of Trigger Status Resources ........................14
   4.6. Loop Detection and Prevention .............................15
   4.7. Error Handling ............................................15
   4.8. Content URLs ..............................................16
5. CI/T Object Properties and Encoding ............................17
   5.1. CI/T Objects ..............................................17
        5.1.1. CI/T Commands ......................................17
        5.1.2. Trigger Status Resources ...........................18
        5.1.3. Trigger Collections ................................20
   5.2. Properties of CI/T Objects ................................21
        5.2.1. Trigger Specification ..............................21
        5.2.2. Trigger Type .......................................23
        5.2.3. Trigger Status .....................................24
        5.2.4. PatternMatch .......................................24
        5.2.5. Absolute Time ......................................25
        5.2.6. Error Description ..................................26
        5.2.7. Error Code .........................................26
6. Examples .......................................................27
   6.1. Creating Triggers .........................................28
        6.1.1. Preposition ........................................28
        6.1.2. Invalidate .........................................30
   6.2. Examining Trigger Status ..................................32
        6.2.1. Collection of All Triggers .........................32
        6.2.2. Filtered Collections of Trigger Status Resources ...33
        6.2.3. Individual Trigger Status Resources ................34
        6.2.4. Polling for Changes in Status ......................36
        6.2.5. Deleting Trigger Status Resources ..................38
        6.2.6. Error Reporting ....................................39

7. IANA Considerations ............................................40
   7.1. CDNI Payload Type Parameter Registrations .................40
   7.2. "CDNI CI/T Trigger Types" Registry ........................41
   7.3. "CDNI CI/T Error Codes" Registry ..........................41
8. Security Considerations ........................................41
   8.1. Authentication, Authorization, Confidentiality,
        Integrity Protection ......................................42
   8.2. Denial of Service .........................................43
   8.3. Privacy ...................................................44
9. References .....................................................44
   9.1. Normative References ......................................44
   9.2. Informative References ....................................45
Appendix A. Formalization of the JSON Data ........................47
Acknowledgments ...................................................49
Authors' Addresses ................................................49

1. Introduction โœจ

okay so [RFC6707] sets up the problem scope for Content Delivery Network Interconnection (CDNI) and lists the four categories of interfaces that may be used to put a CDNI solution together: Control, Metadata, Request Routing, and Logging ๐Ÿงฉ

then [RFC7336] builds on [RFC6707] and goes deeper into each interface and how they relate to each other ๐Ÿฆ‹

this document is all about the "CI/T" interface, which is "CDNI Control interface / Triggers" ๐Ÿ’–. it doesn't cover the parts of the Control interface about configuration, bootstrapping, or authentication of CDN Interconnect interfaces ๐Ÿ™ˆ. Section 4 of [RFC7337] lists the requirements specific to the CI/T interface, and the ones that apply to it are CI-1 to CI-6 ๐Ÿ”ฅ

here's the vibe of the rest of the doc:

  • Section 2 gives the high-level model for the CI/T interface ๐ŸŒˆ
  • Section 3 covers collections of Trigger Status Resources ๐ŸŽ€
  • Section 4 defines the web service the downstream CDN provides ๐Ÿงš
  • Section 5 lists the properties of CI/T Commands and Status Resources ๐Ÿ’…
  • Section 6 has example messages ๐Ÿ“

1.1. Terminology ๐Ÿ“š

this doc reuses the terminology from [RFC6707], and it uses "uCDN" and "dCDN" as shorthand for "upstream CDN" and "downstream CDN", respectively ๐Ÿซถ

the key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 [RFC2119] ๐Ÿ” (these are the official requirement words, so they keep their exact meaning, no vibes-based interpretation allowed ๐Ÿ’€)

2. Model for CDNI Triggers โœจ

okay so bestie, a CI/T Command is basically the uCDN asking the dCDN to go do some work on data tied to content requests that came from the uCDN ๐Ÿ’…

There are two kinds of CI/T Commands: CI/T Trigger Commands and CI/T Cancel Commands. The Cancel one is how you ask to stop an earlier Trigger Command ๐Ÿ›‘ A CI/T Trigger Command is one of these three types:

  • preposition - used to instruct the dCDN to fetch metadata from the uCDN, or content from any origin including the uCDN. ๐Ÿšš
  • invalidate - used to instruct the dCDN to revalidate specific metadata or content before reusing it. ๐Ÿ”
  • purge - used to instruct the dCDN to delete specific metadata or content. ๐Ÿ—‘๏ธ

The CI/T interface is a web service run by the dCDN ๐ŸŒ It's where CI/T Commands get issued and where you can track what they triggered. It's built on top of HTTP/1.1 [RFC7230]. When this document says URL, it means HTTP/HTTPS URIs, same as Section 2.7 of [RFC7230] ๐Ÿฆ‹

When the dCDN accepts a CI/T Command, it makes a resource that shows the status of the triggered activity, called a Trigger Status Resource ๐Ÿ“Š The uCDN can poll Trigger Status Resources to see how things are going.

The dCDN keeps at least one collection of Trigger Status Resources for each uCDN ๐Ÿ—‚๏ธ Each uCDN can only see its own collections, and the locations get shared when CDNI is set up. Very private, very iconic ๐Ÿ”’

To trigger something, the uCDN POSTs a CI/T Command to the collection of Trigger Status Resources. If the dCDN says yes, it makes a brand-new Trigger Status Resource and sends back its location โœจ To check progress, the uCDN can GET that Trigger Status Resource. Want to cancel a CI/T Trigger Command? The uCDN can POST to the collection of Trigger Status Resources, or just delete the Trigger Status Resource ๐Ÿ™ˆ

On top of the full collection of Trigger Status Resources for the uCDN, the dCDN can also keep filtered views ๐Ÿ’œ Those are defined in Section 3, and they include collections for active and completed CI/T Trigger Commands. They're super handy when you want to poll the status of a bunch of jobs at once ๐ŸŽ€

Here's Figure 1, the basic message flow for the uCDN triggering activity in the dCDN and then checking on it. Only the successful path is shown, and examples of the actual messages are in Section 6 ๐ŸŒธ

   uCDN                                                   dCDN
    |    (1) POST https://dcdn.example.com/triggers/uCDN    |
   [ ] --------------------------------------------------> [ ]--+
    |                                                      [ ]  | (2)
    |    (3) HTTP 201 Response                             [ ]<-+
   [ ] <-------------------------------------------------- [ ]
    |     Loc: https://dcdn.example.com/triggers/uCDN/123   |
    |                                                       |
    .                           .                           .
    .                           .                           .
    .                           .                           .
    |                                                       |
    |   (4) GET https://dcdn.example.com/triggers/uCDN/123  |
   [ ] --------------------------------------------------> [ ]
    |                                                      [ ]
    |   (5) HTTP 200 Trigger Status Resource               [ ]
   [ ] <-------------------------------------------------- [ ]
    |                                                       |
    |                                                       |

Figure 1: Basic CDNI Message Flow for Triggers ๐Ÿฆ‹

So the steps in Figure 1 go like this ๐Ÿ‘€

  1. The uCDN triggers action in the dCDN by POSTing a CI/T Command to a collection of Trigger Status Resources, which is https://dcdn.example.com/triggers/uCDN. The uCDN got this URL when the CI/T interface was set up ๐Ÿ”‘
  2. The dCDN authenticates the request, validates the CI/T Command, and if it accepts, makes a new Trigger Status Resource ๐Ÿ›ก๏ธ
  3. The dCDN replies to the uCDN with an HTTP 201 response status and the location of the Trigger Status Resource ๐Ÿ“ฎ
  4. The uCDN can poll the Trigger Status Resource in the dCDN, and it can do that again and again if it wants ๐Ÿ”
  5. The dCDN responds with the Trigger Status Resource, which describes the progress or results of the CI/T Trigger Command ๐Ÿ“ˆ

The rest of this document goes deeper on the messages, Trigger Status Resources, and collections of Trigger Status Resources ๐Ÿงš


2.1. Timing of Triggered Activity

Timing of CI/T Command execution is totally up to the dCDN ๐Ÿ•ฐ๏ธ That includes when things start and how the activity gets paced across the network.

CI/T "invalidate" and "purge" commands MUST be applied to all data acquired before the command was accepted by the dCDN. The dCDN SHOULD NOT apply CI/T "invalidate" and "purge" commands to data acquired after the CI/T Command was accepted, but this may not always be achievable, so the uCDN cannot count on that. ๐Ÿ˜ฌ

Real talk: the uCDN can't count on the dCDN skipping newer data. Don't build your whole plan around that one ๐Ÿ™ƒ

If the uCDN wants to invalidate or purge content and then immediately pre-position replacement content at the same URLs, it SHOULD ensure that the dCDN has completed the invalidate/purge before initiating the pre-positioning. Otherwise, there is a risk that the dCDN pre-positions the new content, then immediately invalidates or purges it (as a result of the two uCDN requests running in parallel). That's the classic race-condition plot twist ๐Ÿ’€

Because the dCDN controls CI/T Command timing, the dCDN implementation gets to choose whether it applies CI/T "invalidate" and "purge" commands to content acquisition that already started when the command came in ๐ŸŽ›๏ธ


2.2. Scope of Triggered Activity

Each CI/T Command can operate on multiple metadata and content URLs ๐Ÿ—บ๏ธ

Multiple representations of an HTTP resource can share the same URL ๐ŸŽจ CI/T Trigger Commands that invalidate or purge metadata or content apply to all resource representations with matching URLs. So one command can hit a whole bunch of versions at once ๐Ÿ’ฅ

2.2.1. Multiple Interconnected CDNs

In a network of interconnected CDNs, one uCDN originates a given item of metadata and its associated content ๐ŸŒ That uCDN can distribute the metadata and content to more than one dCDN, and those dCDNs can pass it further downstream to other CDNs ๐ŸŒŠ

An intermediate CDN is a dCDN that passes CDNI Metadata and content on to dCDNs further downstream ๐Ÿ”—

A "diamond" configuration is when a dCDN can acquire metadata and content that started in one uCDN, either straight from that uCDN or through an intermediate CDN, or through more than one intermediate CDN ๐Ÿ’Ž

CI/T Commands from the single source uCDN affect metadata and content in all dCDNs. But in a diamond configuration, the dCDN might not be able to figure out which uCDN it got the content from ๐Ÿคทโ€โ™€๏ธ In that case, a dCDN MUST allow each uCDN it may have acquired the content from to act on that content using CI/T Commands.

In all other cases, a dCDN MUST reject CI/T Commands from a uCDN that tries to act on another uCDN's content, for example with HTTP 403 ("Forbidden") ๐Ÿšซ Nobody touches somebody else's stuff, periodt ๐Ÿ’…

Security considerations are covered in more detail in Section 8 ๐Ÿ”

The diamond configuration can lead to inefficient interactions, but they're otherwise harmless. For example:

  • When the uCDN issues an "invalidate" CI/T Command, a dCDN will receive that command from multiple directly connected uCDNs. The dCDN may schedule multiple such commands separately, and the last scheduled command may affect content already revalidated following execution of the "invalidate" command that was scheduled first. ๐Ÿ”
  • If one of a dCDN's directly connected uCDNs loses its rights to distribute content, it may issue a CI/T "purge" command. That purge may affect content the dCDN could retain because it's distributed by another directly connected uCDN. But, that content can be reacquired by the dCDN from the remaining uCDN. ๐Ÿ”„
  • When the uCDN originating an item of content issues a CI/T purge followed by a pre-position, two directly connected uCDNs will pass those commands to a dCDN. That dCDN implementation need not merge those operations or notice the repetition, in which case the purge issued by one uCDN will complete before the other. The first uCDN to finish its purge may then forward the "preposition" trigger, and content pre-positioned as a result might be affected by the still-running purge issued by the other uCDN. However, the dCDN will reacquire that content as needed, or when it's asked to pre-position the content by the second uCDN. A dCDN implementation could avoid this interaction by knowing which uCDN it acquired the content from, or it could minimize the consequences by recording the time at which the "invalidate"/"purge" command was received and not applying it to content acquired after that time. ๐Ÿซ 

2.3. Trigger Results

Possible states for a Trigger Status Resource are defined in Section 5.2.3 ๐Ÿšฆ

The CI/T Trigger Command MUST NOT be reported as "complete" until all actions have been completed successfully. The reasons for failure, and URLs or patterns affected, SHOULD be enumerated in the Trigger Status Resource. For more details, see Section 4.7 ๐Ÿ“

If a dCDN is also acting as a uCDN in a cascade, it MUST forward CI/T Commands to any dCDNs that may be affected. The CI/T Trigger Command MUST NOT be reported as "complete" in a CDN until it is "complete" in all of its dCDNs. If a CI/T Trigger Command is reported as "processed" in any dCDN, intermediate CDNs MUST NOT report "complete"; instead, they MUST also report "processed". A CI/T Command MAY be reported as "failed" as soon as it fails in a CDN or in any of its dCDNs. A canceled CI/T Trigger Command MUST be reported as "cancelling" until it has been reported as "cancelled", "complete", or "failed" by all dCDNs in a cascade. ๐ŸŒŠโœจ

3. Collections of Trigger Status Resources ๐Ÿ—‚๏ธ

Okay so, like we talked about in Section 2, Trigger Status Resources live in the dCDN so they can keep everyone posted on the activity each uCDN triggered ๐Ÿ‘€

A collection of Trigger Status Resources is basically a resource that holds a reference to every Trigger Status Resource in that collection. It's like a little playlist of links ๐ŸŽ€

The dCDN MUST make a collection of a uCDN's Trigger Status Resources available to that uCDN. This collection has everything created for CI/T Commands from that uCDN that the dCDN accepted, and that the uCDN hasn't deleted yet, or that the dCDN hasn't expired and removed (as described in Section 4.4). Trigger Status Resources belonging to a uCDN MUST NOT be visible to any other CDN. Not me, not sharing your stuff ๐Ÿ™…โ€โ™€๏ธ For example, the dCDN could do this by giving each uCDN its own collection URL and filtering the response based on which uCDN the HTTP client is connected with ๐Ÿ’…

To trigger activity in a dCDN or to cancel triggered activity, the uCDN POSTs a CI/T Command to the dCDN's collection of the uCDN's Trigger Status Resources. Simple as that ๐Ÿซถ

Now, so the uCDN can check on a bunch of jobs in one request, the dCDN MAY also keep collections that are filtered views of the collection of all Trigger Status Resources. These filtered collections are "optional-to-implement," but if the dCDN does build them, it MUST include links to them in the collection of all Trigger Status Resources. The filtered collections are:

  • Pending - Trigger Status Resources for CI/T Trigger Commands that have been accepted but not yet acted upon โณ
  • Active - Trigger Status Resources for CI/T Trigger Commands that are currently being processed in the dCDN ๐Ÿ”ฅ
  • Complete - Trigger Status Resources representing activity that completed successfully, plus processed CI/T Trigger Commands for which the dCDN will make no further status updates โœจ
  • Failed - Trigger Status Resources representing CI/T Commands that failed or were canceled by the uCDN ๐Ÿ’€

4. CDNI Trigger Interface ๐Ÿฆ‹

This section describes an interface that lets a uCDN trigger activity in a dCDN. It's giving protocol ๐ŸŒธ

The CI/T interface is built on top of HTTP, so dCDNs can make use of any HTTP feature when they implement the CI/T interface. For example, a dCDN SHOULD make use of HTTP's caching mechanisms to indicate that a requested response or representation has not been modified. That way the uCDN doesn't have to do as much work figuring out whether the status of triggered activity has changed ๐Ÿง 

All dCDNs implementing CI/T MUST support the HTTP GET, HEAD, POST, and DELETE methods as defined in [RFC7231]. ๐Ÿ’–

The only representation specified in this document is JSON [RFC7159]. It MUST be supported by the uCDN and by the dCDN. Both sides need to speak it, bestie ๐Ÿค

The URL of the dCDN's collection of all Trigger Status Resources needs to be either discovered by the uCDN or configured in it. How the discovery happens is outside the scope of this document, so that's a different story ๐Ÿ—บ๏ธ

CI/T Commands are POSTed to the dCDN's collection of all Trigger Status Resources. If the dCDN accepts a CI/T Trigger Command, it creates a new Trigger Status Resource and sends its URI back to the uCDN in an HTTP 201 response. After that, the uCDN can keep an eye on the triggered activity using that resource and the collections described in Section 3 ๐Ÿ‘€โœจ

The URI of each Trigger Status Resource gets returned to the uCDN when it's created, and the URIs of all Trigger Status Resources are listed in the dCDN's collection of all Trigger Status Resources. So the uCDN can discover every single one, which means dCDNs are free to structure their CI/T URIs however they like ๐ŸŽจ That's why uCDNs MUST NOT make any assumptions about the structure of CI/T URIs or how CI/T objects map to their URIs. The URIs in this document's examples are purely illustrative and are not meant to force a particular structure on CI/T implementations ๐Ÿ™ˆ

4.1. Creating Triggers ๐Ÿš€

To issue a CI/T Command, the uCDN makes an HTTP POST to the dCDN's collection of all of the uCDN's Trigger Status Resources. The body of that POST is a CI/T Command, as described in Section 5.1.1 ๐Ÿ“ฎ

The dCDN validates the CI/T Command. If the command is malformed or the uCDN doesn't have sufficient access rights, the dCDN MUST either respond with an appropriate 4xx HTTP error code and not create a Trigger Status Resource, or create a failed Trigger Status Resource containing an appropriate Error Description. Rejected, but make it make sense ๐Ÿ’…

When a CI/T Trigger Command is accepted, the uCDN MUST create a new Trigger Status Resource that conveys a specification of the CI/T Command and its current status. The HTTP response to the dCDN MUST have status code 201 and MUST convey the URI of the Trigger Status Resource in the Location header field [RFC7231]. The HTTP response SHOULD include the content of the newly created Trigger Status Resource. This matters most when the CI/T Trigger Command has already completed immediately, so it's a big deal โšก

Once a Trigger Status Resource has been created, the dCDN MUST NOT reuse its URI, even after that Trigger Status Resource has been removed. No recycling URIs, ever ๐Ÿ™…โ€โ™€๏ธ

The dCDN SHOULD track and report on the progress of CI/T Trigger Commands using a Trigger Status Resource (Section 5.1.2). If the dCDN can't do that, it MUST indicate that it accepted the request but won't be providing further status updates. To do this, it sets the status of the Trigger Status Resource to processed. In this case, CI/T processing should carry on as it would for a complete request, so the Trigger Status Resource MUST be added to the dCDN's collection of complete Trigger Status Resources. The dCDN SHOULD also give an estimated completion time for the request using the etime property of the Trigger Status Resource. This lets the uCDN schedule pre-positioning for after an earlier delete of the same URLs is expected to have finished โฐ

If the dCDN can track the execution of CI/T Commands and a CI/T Command gets queued for later action, the status property of the Trigger Status Resource MUST be pending. Once processing has started, the status MUST be active. Finally, once the CI/T Command is complete, the status MUST be set to complete or failed ๐Ÿ

A CI/T Trigger Command might result in no activity in the dCDN at all. For example, that happens with an invalidate or purge request for data the dCDN hasn't acquired yet, or a preposition request for data it already has and that is still valid. In this case, the status of the Trigger Status Resource MUST be processed or complete, and the Trigger Status Resource MUST be added to the dCDN's collection of complete Trigger Status Resources. Nothing to do, but still acknowledged ๐ŸŒˆ

Once created, Trigger Status Resources can be canceled or deleted by the uCDN, but they can't be modified. The dCDN MUST reject PUT and POST requests from the uCDN to Trigger Status Resources by responding with an appropriate HTTP status code, for example 405 ("Method Not Allowed") ๐Ÿ”’

4.2. Checking Status ๐Ÿ‘€

The uCDN has two ways to check on the progress of CI/T Commands it has issued to the dCDN, as described in Sections 4.2.1 and 4.2.2 ๐Ÿงš

To let the uCDN check for changes in the status of a Trigger Status Resource or a collection of them without refetching the whole thing, the dCDN SHOULD include entity-tags (ETags) for the uCDN to use as cache validators, as defined in [RFC7232]. โœจ

The dCDN SHOULD use the cache control headers on responses to GETs for Trigger Status Resources and Collections to indicate how often it recommends the uCDN poll for changes ๐Ÿ•ฐ๏ธ

4.2.1. Polling Trigger Status Resource Collections ๐Ÿงบ

The uCDN can fetch its collection of Trigger Status Resources, or filtered views of that collection.

This makes it possible to poll the status of every CI/T Trigger Command in a single request. If the dCDN moves a Trigger Status Resource from the active collection to the completed one, the uCDN can fetch the result of that activity ๐ŸŽ‰

When polling this way, the uCDN SHOULD use HTTP ETags to watch for changes, rather than fetching the whole collection over and over. An example of this is given in Section 6.2.4 ๐Ÿ’œ

4.2.2. Polling Trigger Status Resources ๐Ÿ”

The uCDN has a URI, provided by the dCDN, for each Trigger Status Resource it has created. It may fetch that Trigger Status Resource at any time ๐Ÿ’ซ

This can be used to retrieve progress information and to fetch the result of the CI/T Command ๐ŸŽ

When polling this way, the uCDN SHOULD use HTTP ETags to watch for changes, rather than repeatedly fetching the Trigger Status Resource ๐Ÿซถ

4.3. Canceling Triggers ๐Ÿ™…โ€โ™€๏ธ

The uCDN can request cancellation of a CI/T Trigger Command by POSTing a CI/T Cancel Command to the collection of all Trigger Status Resources ๐Ÿ“ฃ

The dCDN is required to accept and respond to the CI/T Cancel Command, but actually canceling a CI/T Trigger Command is optional-to-implement ๐Ÿฅบ

The dCDN MUST respond to the CI/T Cancel Command appropriately. For example, it responds with HTTP status code 200 ("OK") if the cancellation has been processed and the CI/T Command is inactive, 202 ("Accepted") if the command was accepted but is still active, or 501 ("Not Implemented") if the dCDN doesn't support cancellation ๐Ÿšฆ

If the dCDN accepts cancellation of a pending Trigger Status Resource, the dCDN SHOULD NOT start processing that activity. Still, issuing a CI/T Cancel Command for a pending Trigger Status Resource doesn't guarantee the corresponding activity won't start, because the uCDN can't control the timing of that activity. Processing could, for example, begin after the uCDN sends the POST but before the dCDN handles that request ๐Ÿ˜ฌ

If the dCDN accepts cancellation of an active or processed Trigger Status Resource, the dCDN SHOULD stop processing the CI/T Command. But, just like with a pending CI/T Command, the dCDN doesn't guarantee that ๐Ÿคทโ€โ™€๏ธ

If the CI/T Command can't be stopped immediately, the status in the corresponding Trigger Status Resource MUST be set to cancelling, and the Trigger Status Resource MUST remain in the collection of Trigger Status Resources for active CI/T Commands. If processing stops before normal completion, the status value in the Trigger Status Resource MUST be set to cancelled, and the Trigger Status Resource MUST be included in the collection of failed CI/T Trigger Commands ๐Ÿ›‘

Canceling a complete or failed Trigger Status Resource doesn't need any processing in the dCDN. Its status MUST NOT be changed to cancelled ๐ŸงŠ

4.4. Deleting Triggers โœจ

okay so the uCDN can delete Trigger Status Resources whenever it wants ๐Ÿ’…, using the HTTP DELETE method. It's kinda like cancelling, except after a delete there's no Trigger Status Resource left hanging around ๐Ÿซง

once something is deleted, every reference to that Trigger Status Resource MUST be removed from all Trigger Status Resource collections ๐Ÿงน. if anyone tries to GET it later, the dCDN SHOULD reject that with an HTTP error ๐Ÿ™…โ€โ™€๏ธ

if a "pending" Trigger Status Resource gets deleted, the dCDN SHOULD NOT start processing that activity ๐Ÿ›‘. BUT deleting a "pending" one does not guarantee it hasn't started already ๐Ÿ˜ญ, because the uCDN can't control the timing of that activity. for example, processing could kick off after the uCDN sends the DELETE but before the dCDN actually handles that request. not me getting caught in a timing gap ๐Ÿ’€

if an "active" or "processed" Trigger Status Resource is deleted, the dCDN SHOULD stop processing the CI/T Command. however, just like with a "pending" one, the dCDN doesn't guarantee this ๐Ÿซถ

deleting a "complete" or "failed" Trigger Status Resource requires no processing in the dCDN other than deleting the Trigger Status Resource itself. easy breezy ๐ŸŒธ

4.5. Expiry of Trigger Status Resources โณ

the dCDN can choose to automatically delete Trigger Status Resources some time after they become "complete", "processed", "failed", or "cancelled" ๐Ÿ“. when that happens, the dCDN removes the Trigger Status Resource and answers any later requests for it with an HTTP error.

if the dCDN does remove Trigger Status Resources automatically, it MUST report the length of time after which it will do so ๐Ÿ“ฃ, using a property of the collection of all Trigger Status Resources. no hiding the timer, bestie ๐Ÿ™ˆ

it is RECOMMENDED that Trigger Status Resources are not automatically deleted by the dCDN for at least 24 hours after they become "complete", "processed", "failed", or "cancelled" ๐ŸŒˆ that's the vibe the spec is going for.

to make sure the uCDN can still check on its Trigger Status Resources for completed and failed CI/T Commands, it is RECOMMENDED that the uCDN polling interval is less than the time after which records for completed activity will be deleted. timing is everything โฐโœจ

4.6. Loop Detection and Prevention ๐Ÿ”

okay picture this: three CDNs, A, B, and C. if CDNs B and C keep handing CDN A's content back and forth to each other, CDN A's CI/T Commands could get passed between B and C in a loop ๐Ÿ˜ตโ€๐Ÿ’ซ. more complicated networks of CDNs could have similar loops with more hops. a whole spiral situation ๐ŸŒ€

so to prevent and detect these CI/T loops, each CDN uses a CDN Provider ID (PID) to uniquely identify itself ๐Ÿชช. in every CI/T Command it originates or cascades, each CDN MUST append an array element containing its CDN PID to a JSON array under an entry named cdn-path โœ๏ธ.

when receiving CI/T Commands, a dCDN MUST check the cdn-path and reject any CI/T Command that already contains its own CDN PID in the cdn-path ๐Ÿšซ. transit CDNs MUST check the cdn-path and not cascade the CI/T Command to dCDNs that are already listed in the cdn-path ๐Ÿ›‘. no going in circles, periodt ๐Ÿ’…

the CDN PID is the two characters "AS" followed by the CDN provider's Autonomous System number [RFC1930], then a colon (":") and an additional qualifier ๐ŸŽ€. that qualifier exists to guarantee uniqueness in case a particular AS has multiple independent CDNs deployed. for example, AS64496:0 ๐Ÿงš

if the CDN provider has multiple ASes, the same AS number SHOULD be used in all messages from that CDN provider, unless there are multiple distinct CDNs ๐Ÿฆ‹

and if the CDNI Request Routing Redirection interface (RI) described in [RFC7975] is implemented by the dCDN, the CI/T interface and the RI SHOULD use the same CDN PID. matching energy โœจ

4.7. Error Handling ๐Ÿšจ

a dCDN can signal rejection of a CI/T Command using HTTP status codes ๐Ÿ™…. for example, 400 ("Bad Request") if the request is malformed, or 403 ("Forbidden") or 404 ("Not Found") if the uCDN doesn't have permission to issue CI/T Commands or it's trying to act on another CDN's data ๐Ÿ‘€. bad vibes, all of them ๐Ÿ˜ค

if any part of the CI/T Trigger Command fails, the trigger SHOULD be reported as "failed" once its activity is complete or if no further errors will be reported ๐Ÿ’”. the errors property in the Trigger Status Resource is where the failed actions and their reasons get listed ๐Ÿ“‹. it can show up while the Trigger Status Resource is still "pending" or "active", if the CI/T Trigger Command is still running for some of the URLs or patterns in the Trigger Specification ๐Ÿƒโ€โ™€๏ธ

once a request has been accepted, processing errors get reported in the Trigger Status Resource as a list of Error Descriptions ๐Ÿ“. each Error Description reports errors against one or more of the URLs or patterns in the Trigger Specification.

if a Surrogate affected by a CI/T Trigger Command is offline in the dCDN, or the dCDN can't pass a CI/T Command on to any of its cascaded dCDNs, here's the breakdown ๐Ÿ‘‡

  • if the CI/T Command is abandoned by the dCDN, the dCDN SHOULD report an error.
  • a CI/T "invalidate" command may be reported as "complete" when Surrogates that may have the data are offline. in this case, Surrogates MUST NOT use the affected data without first revalidating it when they are back online ๐Ÿ™…โ€โ™€๏ธ revalidate first, no shortcuts.
  • CI/T "preposition" and "purge" commands can be reported as "processed" if affected caches are offline, and the activity will complete when they return to service ๐Ÿ”„
  • otherwise, the dCDN SHOULD keep the Trigger Status Resource in state "pending" or "active" until either the CI/T Command is acted upon or the uCDN chooses to cancel it โธ๏ธ

4.8. Content URLs ๐Ÿ”—

if content URLs get transformed by an intermediate CDN in a cascade, that intermediate CDN MUST similarly transform URLs in the CI/T Commands it passes to its dCDN ๐Ÿช„. consistency is iconic.

when processing Trigger Specifications, CDNs MUST ignore the URL scheme (HTTP or HTTPS) when comparing URLs ๐Ÿ™Œ. for example, for a CI/T "invalidate" or "purge" command, content MUST be invalidated or purged regardless of the protocol clients used to request it. http or https, the content gets handled either way ๐ŸŒˆ


5. CI/T Object Properties and Encoding ๐Ÿ’œ

the CI/T Commands, Trigger Status Resources, and Trigger Collections, plus all of their properties, are encoded using JSON, as defined in Sections 5.1.1, 5.1.2, and 5.1.3 ๐Ÿง. they MUST use the MIME media type "application/cdni", with "ptype" parameter values as defined below and in Section 7.1.

names in JSON are case sensitive ๐Ÿ” . the names and literal values specified in the present document MUST always use lowercase, no exceptions ๐Ÿซถ

JSON types, including "object", "array", "number", and "string", are defined in [RFC7159] ๐Ÿ“–.

unrecognized name/value pairs in JSON objects SHOULD NOT be treated as an error by either the uCDN or dCDN ๐Ÿคทโ€โ™€๏ธ. they SHOULD be ignored during processing and passed on by the dCDN to any further dCDNs in a cascade. so nothing gets dropped on the floor ๐Ÿฆ‹

5.1. CI/T Objects ๐Ÿงฉ

the top-level objects defined by the CI/T interface are described in this section โœจ. the encoding of the values used by these objects is described in Section 5.2.

5.1.1. CI/T Commands ๐Ÿ“ฎ

CI/T Commands MUST use a MIME media type of application/cdni; ptype=ci-trigger-command.

a CI/T Command is encoded as a JSON object containing the following name/value pairs ๐Ÿ’Œ

  • Name: trigger
    • Description: A specification of the trigger type and a set of data to act upon.
    • Value: A Trigger Specification, as defined in Section 5.2.1.
    • Mandatory: No, but exactly one of "trigger" or "cancel" MUST be present in a CI/T Command.
  • Name: cancel
    • Description: The URLs of Trigger Status Resources for CI/T Trigger Commands that the uCDN wants to cancel ๐Ÿšซ.
    • Value: A non-empty JSON array of URLs represented as JSON strings.
    • Mandatory: No, but exactly one of "trigger" or "cancel" MUST be present in a CI/T Command.
  • Name: cdn-path
    • Description: The CDN PIDs of CDNs that have already issued the CI/T Command to their dCDNs ๐Ÿ›ค๏ธ.
    • Value: A non-empty JSON array of JSON strings, where each string is a CDN PID as defined in Section 4.6.
    • Mandatory: Yes.

5.1.2. Trigger Status Resources ๐Ÿ“Š

Trigger Status Resources MUST use a MIME media type of application/cdni; ptype=ci-trigger-status.

a Trigger Status Resource is encoded as a JSON object containing the following name/value pairs ๐ŸŽ€

  • Name: trigger
    • Description: The Trigger Specification POSTed in the body of the CI/T Command. Note that this need not be a byte-for-byte copy. For example, in the JSON representation the dCDN may re-serialize the information differently ๐Ÿง .
    • Value: A Trigger Specification, as defined in Section 5.2.1.
    • Mandatory: Yes.
  • Name: ctime
    • Description: Time at which the CI/T Command was received by the dCDN. Time is determined by the dCDN; there is no requirement to synchronize clocks between interconnected CDNs โฑ๏ธ.
    • Value: Absolute Time, as defined in Section 5.2.5.
    • Mandatory: Yes.
  • Name: mtime
    • Description: Time at which the Trigger Status Resource was last modified. Time is determined by the dCDN; there is no requirement to synchronize clocks between interconnected CDNs ๐Ÿ•ฐ๏ธ.
    • Value: Absolute Time, as defined in Section 5.2.5.
    • Mandatory: Yes.
  • Name: etime
    • Description: Estimate of the time at which the dCDN expects to complete the activity. Time is determined by the dCDN; there is no requirement to synchronize clocks between interconnected CDNs ๐Ÿ”ฎ.
    • Value: Absolute Time, as defined in Section 5.2.5.
    • Mandatory: No.
  • Name: status
    • Description: Current status of the triggered activity ๐Ÿ“ถ.
    • Value: Trigger Status, as defined in Section 5.2.3.
    • Mandatory: Yes.
  • Name: errors
    • Description: Descriptions of errors that have occurred while processing a Trigger Command ๐Ÿ˜ฌ.
    • Value: An array of Error Descriptions, as defined in Section 5.2.6. An empty array is allowed and is equivalent to omitting "errors" from the object.
    • Mandatory: No.

5.1.3. Trigger Collections ๐ŸŽ€

Okay bestie, Trigger Collections MUST use the MIME media type application/cdni; ptype=ci-trigger-collection ๐Ÿ’… no exceptions, no cap.

A Trigger Collection is encoded as a JSON object containing the following name/value pairs. Here's the whole lineup ๐Ÿงš

  • triggers ๐Ÿ’–
    • Description: Links to Trigger Status Resources in the collection.
    • Value: A JSON array of zero or more URLs, represented as JSON strings.
    • Mandatory: Yes.
  • staleresourcetime โณ
    • Description: This is how long the dCDN promises to keep a completed Trigger Status Resource. After that time, the dCDN SHOULD delete the Trigger Status Resource and all references to it from collections. ๐Ÿ’€ tea spill
    • Value: A JSON number, which must be a positive integer, representing time in seconds.
    • Mandatory: Yes, in the collection of all Trigger Status Resources if the dCDN deletes stale entries. If the property is present in the filtered collections, it MUST have the same value as in the collection of all Trigger Status Resources.
  • coll-all, coll-pending, coll-active, coll-complete, coll-failed ๐ŸŒˆ
    • Description: Link to a Trigger Collection.
    • Value: A URL represented as a JSON string.
    • Mandatory: Links to all of the filtered collections are mandatory in the collection of all Trigger Status Resources, if the dCDN implements the filtered collections. Otherwise, optional.
  • cdn-id ๐Ÿ“
    • Description: The CDN PID of the dCDN.
    • Value: A JSON string, the dCDN's CDN PID, as defined in Section 4.6.
    • Mandatory: Only in the collection of all Trigger Status Resources, if the dCDN implements the filtered collections. Optional in the filtered collections (the uCDN can always find the dCDN's cdn-id in the collection of all Trigger Status Resources, but the dCDN can choose to repeat that information in its implementation of filtered collections).

5.2. Properties of CI/T Objects ๐Ÿฆ‹

This section is where we spell out the values that can show up in the top-level objects from Section 5.1, plus how they get encoded. Let's gooo โœจ

5.2.1. Trigger Specification ๐Ÿ’œ

A Trigger Collection is encoded as a JSON object containing the following name/value pairs.

An unrecognized name/value pair in the Trigger Specification object contained in a CI/T Command SHOULD be preserved in the Trigger Specification of any Trigger Status Resource it creates.

  • type ๐Ÿ”ฅ
    • Description: Defines the type of the CI/T Trigger Command.
    • Value: Trigger Type, as defined in Section 5.2.2.
    • Mandatory: Yes.
  • metadata.urls ๐Ÿ“ฆ
    • Description: The uCDN URLs of the metadata the CI/T Trigger Command applies to.
    • Value: A JSON array of URLs represented as JSON strings.
    • Mandatory: No, but at least one of "metadata." or "content." MUST be present and non-empty.
  • content.urls ๐ŸŽฌ
    • Description: URLs of content the CI/T Trigger Command applies to. See Section 4.8.
    • Value: A JSON array of URLs represented as JSON strings.
    • Mandatory: No, but at least one of "metadata." or "content." MUST be present and non-empty.
  • content.ccid ๐Ÿงฉ
    • Description: The Content Collection IDentifier of content the trigger applies to. The "ccid" is a grouping of content, as defined by [RFC8006].
    • Value: A JSON array of strings, where each string is a Content Collection IDentifier.
    • Mandatory: No, but at least one of "metadata." or "content." MUST be present and non-empty.
  • metadata.patterns ๐Ÿช„
    • Description: The metadata the trigger applies to.
    • Value: A JSON array of PatternMatch objects, as defined in Section 5.2.4.
    • Mandatory: No, but at least one of "metadata." or "content." MUST be present and non-empty, and metadata.patterns MUST NOT be present if the Trigger Type is "preposition".
  • content.patterns ๐ŸŒธ
    • Description: The content data the trigger applies to.
    • Value: A JSON array of PatternMatch objects, as defined in Section 5.2.4.
    • Mandatory: No, but at least one of "metadata." or "content." MUST be present and non-empty, and content.patterns MUST NOT be present if the Trigger Type is "preposition".

5.2.2. Trigger Type ๐Ÿ”ฅ

Trigger Type is the bit that lives inside a Trigger Specification and says what action the trigger is asking for. Main character energy ๐Ÿ‘‘

All trigger types MUST be registered in the IANA "CDNI CI/T Trigger Types" registry (see Section 7.2).

A dCDN receiving a request containing a trigger type it does not recognize or does not support MUST reject the request by creating a Trigger Status Resource with a status of "failed" and the "errors" array containing an Error Description with error "eunsupported". ๐Ÿ’€ that's a hard no, bestie.

The following trigger types are defined by this document:

+-------------+-----------------------------------------------------+
| JSON String | Description                                         |
+-------------+-----------------------------------------------------+
| preposition | A request for the dCDN to acquire metadata or       |
|             | content.                                            |
| invalidate  | A request for the dCDN to invalidate metadata or    |
|             | content.  After servicing this request, the dCDN    |
|             | will not use the specified data without first       |
|             | revalidating it using, for example, an              |
|             | "If-None-Match" HTTP request.  The dCDN need not    |
|             | erase the associated data.                          |
| purge       | A request for the dCDN to erase metadata or         |
|             | content.  After servicing the request, the          |
|             | specified data MUST NOT be held on the dCDN (the    |
|             | dCDN should reacquire the metadata or content from  |
|             | the uCDN if it needs it).                           |
+-------------+-----------------------------------------------------+

5.2.3. Trigger Status โœจ

Trigger Status tells you how the triggered activity is doing right now. It MUST be one of the JSON strings in the following table:

+-----------+-------------------------------------------------------+
| JSON      | Description                                           |
| String    |                                                       |
+-----------+-------------------------------------------------------+
| pending   | The CI/T Trigger Command has not yet been acted upon. |
| active    | The CI/T Trigger Command is currently being acted     |
|           | upon.                                                 |
| complete  | The CI/T Trigger Command completed successfully.      |
| processed | The CI/T Trigger Command has been accepted, and no    |
|           | further status update will be made (can be used in    |
|           | cases where completion cannot be confirmed).          |
| failed    | The CI/T Trigger Command could not be completed.      |
| canceling | Processing of the CI/T Trigger Command is still in    |
|           | progress, but the CI/T Trigger Command has been       |
|           | canceled by the uCDN.                                 |
| canceled  | The CI/T Trigger Command was canceled by the uCDN.    |
+-----------+-------------------------------------------------------+

5.2.4. PatternMatch ๐Ÿฆ‹

A PatternMatch is a string pattern you match against a URI, plus some flags that describe how the matching should go. ๐Ÿง  It's encoded as a JSON object with these name/value pairs:

  • pattern ๐ŸŽฏ
    • Description: A pattern for URI matching.
    • Value: A JSON string representing the pattern. The pattern can contain the wildcards * and ?, where * matches any sequence of [RFC3986] pchar or "/" characters (including the empty string) and ? matches exactly one [RFC3986] pchar character. The three literals $, * and ? MUST be escaped as $$, $* and $? (where $ is the designated escape character). All other characters are treated as literals.
    • Mandatory: Yes.
  • case-sensitive ๐Ÿ”ค
    • Description: Flag indicating whether or not case-sensitive matching should be used.
    • Value: One of the JSON values "true" (the matching is case sensitive) or "false" (the matching is case insensitive).
    • Mandatory: No; default is case-insensitive match.
  • match-query-string โ“
    • Description: Flag indicating whether to include the query part of the URI when comparing against the pattern.
    • Value: One of the JSON values "true" (the full URI, including the query part, should be compared against the given pattern) or "false" (the query part of the URI should be dropped before comparison with the given pattern).
    • Mandatory: No; default is "false". The query part of the URI should be dropped before comparison with the given pattern.

Here's an example of a case-sensitive prefix match against https://www.example.com/trailers/ ๐ŸŽ€

{
    "pattern": "https://www.example.com/trailers/*",
    "case-sensitive": true
}

5.2.5. Absolute Time โฐ

It's a JSON number: seconds since the UNIX epoch (00:00:00 UTC on 1 January 1970). Time is a whole vibe ๐ŸŒˆ

5.2.6. Error Description ๐Ÿ’€

An Error Description is how we report that a CI/T Command failed, or that the activity it triggered failed. ๐Ÿ™ˆ It's encoded as a JSON object with these name/value pairs:

  • error ๐Ÿšจ
    • Value: Error Code, as defined in Section 5.2.7.
    • Mandatory: Yes.
  • metadata.urls, content.urls, metadata.patterns, content.patterns ๐Ÿซถ
    • Description: Metadata and content references copied from the Trigger Specification. Only those URLs and patterns to which the error applies are included in each property, but those URLs and patterns MUST be exactly as they appear in the request; the dCDN MUST NOT generalize the URLs. (For example, if the uCDN requests pre-positioning of URLs "https://content.example.com/a" and "https://content.example.com/b", the dCDN must not generalize its error report to the pattern "https://content.example.com/*".)
    • Value: A JSON array of JSON strings, where each string is copied from a "content." or "metadata." value in the corresponding Trigger Specification.
    • Mandatory: At least one of these name/value pairs is mandatory in each Error Description object.
  • description ๐Ÿ“
    • Description: A human-readable description of the error.
    • Value: A JSON string, the human-readable description.
    • Mandatory: No.
โš ๏ธ Bestie, don't generalize the URLs in your error reports. Copy them exactly as they came in or the whole report gets messy ๐Ÿ’…

Okay that's the vibe for Section 5.2! ๐Ÿƒ

5.2.7. Error Code ๐Ÿšจ

okay so this type is how the dCDN tells the uCDN that something went wrong while processing a trigger ๐Ÿ˜ญ. Every Error Code MUST be registered in the IANA "CDNI CI/T Error Codes" registry (see Section 7.3) ๐Ÿ“‹. Unknown Error Codes MUST be treated as fatal errors ๐Ÿ’€, and the request MUST NOT be automatically retried without modification ๐Ÿ™…โ€โ™€๏ธ. no cap, that part is serious!!

These are the Error Codes this document defines, and every single one MUST be supported by an implementation of the CI/T interface ๐Ÿซถ:

+--------------+----------------------------------------------------+
| Error Code   | Description                                        |
+--------------+----------------------------------------------------+
| emeta        | The dCDN was unable to acquire metadata required   |
|              | to fulfill the request.                            |
| econtent     | The dCDN was unable to acquire content (CI/T       |
|              | "preposition" commands only).                      |
| eperm        | The uCDN does not have permission to issue the     |
|              | CI/T Command (for example, the data is owned by    |
|              | another CDN).                                      |
| ereject      | The dCDN is not willing to fulfill the CI/T        |
|              | Command (for example, a "preposition" request for  |
|              | content at a time when the dCDN would not accept   |
|              | Request Routing requests from the uCDN).           |
| ecdn         | An internal error in the dCDN or one of its dCDNs. |
| ecanceled    | The uCDN canceled the request.                     |
| eunsupported | The Trigger Specification contained a "type" that  |
|              | is not supported by the dCDN.  No action was taken |
|              | by the dCDN other than to create a Trigger Status  |
|              | Resource in state "failed".                        |
+--------------+----------------------------------------------------+

6. Examples ๐ŸŽ€

okay the next bit is all examples ๐Ÿงš of different CI/T objects encoded as JSON, so you can see what they actually look like!!

Discovery of the CI/T interface is out of scope for this document ๐Ÿ™ˆ. In an implementation, all CI/T URLs are under the control of the dCDN. The uCDN MUST NOT attempt to ascribe any meaning to individual elements of the path. hard rule, bestie, don't go reading tea leaves in the URL ๐Ÿšซ

In the examples in this section, https://dcdn.example.com/triggers is the location of the collection of all Trigger Status Resources, and the CDN PID of the uCDN is AS64496:1 ๐Ÿ’œ

6.1. Creating Triggers ๐Ÿฆ‹

This is the uCDN triggering activity in the dCDN, bestie:

6.1.1. Preposition ๐ŸŒธ

Here's a CI/T "preposition" command ๐Ÿ’–, which is a POST to the collection of all Trigger Status Resources.

Note that metadata.patterns and content.patterns are not allowed in a pre-position Trigger Specification โš ๏ธ.

REQUEST:

POST /triggers HTTP/1.1
User-Agent: example-user-agent/0.1
Host: dcdn.example.com
Accept: */*
Content-Type: application/cdni; ptype=ci-trigger-command
Content-Length: 352

{
  "trigger": {
    "type": "preposition",

    "metadata.urls": [ "https://metadata.example.com/a/b/c" ],
    "content.urls": [
        "https://www.example.com/a/b/c/1",
        "https://www.example.com/a/b/c/2",
        "https://www.example.com/a/b/c/3",
        "https://www.example.com/a/b/c/4"
      ]
  },
  "cdn-path": [ "AS64496:1" ]
}

RESPONSE:

HTTP/1.1 201 Created
Date: Wed, 04 May 2016 08:48:10 GMT
Content-Length: 467
Content-Type: application/cdni; ptype=ci-trigger-status
Location: https://dcdn.example.com/triggers/0
Server: example-server/0.1

{
    "ctime": 1462351690,
    "etime": 1462351698,
    "mtime": 1462351690,
    "status": "pending",
    "trigger": {
        "content.urls": [
            "https://www.example.com/a/b/c/1",
            "https://www.example.com/a/b/c/2",
            "https://www.example.com/a/b/c/3",
            "https://www.example.com/a/b/c/4"
        ],
        "metadata.urls": [
            "https://metadata.example.com/a/b/c"
        ],
        "type": "preposition"
    }
}

6.1.2. Invalidate ๐Ÿงน

Next up is a CI/T "invalidate" command ๐Ÿ’…, another POST to the collection of all Trigger Status Resources. This one tells the dCDN to revalidate the content at https://www.example.com/a/index.html, plus any metadata and content whose URLs are prefixed by https://metadata.example.com/a/b/ using case-insensitive matching, and https://www.example.com/a/b/ using case-sensitive matching, respectively. the matching rules are doing a lot here ๐Ÿค“

REQUEST:

POST /triggers HTTP/1.1
User-Agent: example-user-agent/0.1
Host: dcdn.example.com
Accept: */*
Content-Type: application/cdni; ptype=ci-trigger-command
Content-Length: 387

{
  "trigger": {
    "type": "invalidate",

    "metadata.patterns": [
        { "pattern": "https://metadata.example.com/a/b/*" }
      ],

    "content.urls": [ "https://www.example.com/a/index.html" ],
    "content.patterns": [
        { "pattern": "https://www.example.com/a/b/*",
          "case-sensitive": true
        }
      ]
  },
  "cdn-path": [ "AS64496:1" ]
}

RESPONSE:

HTTP/1.1 201 Created
Date: Wed, 04 May 2016 08:48:11 GMT
Content-Length: 545
Content-Type: application/cdni; ptype=ci-trigger-status
Location: https://dcdn.example.com/triggers/1
Server: example-server/0.1

{
    "ctime": 1462351691,
    "etime": 1462351699,
    "mtime": 1462351691,
    "status": "pending",
    "trigger": {
        "content.patterns": [
            {
                "case-sensitive": true,
                "pattern": "https://www.example.com/a/b/*"
            }
        ],
        "content.urls": [
            "https://www.example.com/a/index.html"
        ],
        "metadata.patterns": [
            {
                "pattern": "https://metadata.example.com/a/b/*"
            }
        ],
        "type": "invalidate"
    }
}

6.2. Examining Trigger Status ๐Ÿ”

Once Trigger Status Resources exist, the uCDN can check their status like this ๐Ÿ‘€.

6.2.1. Collection of All Triggers ๐Ÿ“š

The uCDN can fetch the collection of all Trigger Status Resources it has created that have not yet been deleted or removed as expired โœจ. After creating the "preposition" and "invalidate" triggers from above, this collection might look like this:

REQUEST:

GET /triggers HTTP/1.1
User-Agent: example-user-agent/0.1
Host: dcdn.example.com
Accept: */*

RESPONSE:

HTTP/1.1 200 OK
Content-Length: 341
Expires: Wed, 04 May 2016 08:49:11 GMT
Server: example-server/0.1
ETag: "-936094426920308378"
Cache-Control: max-age=60
Date: Wed, 04 May 2016 08:48:11 GMT
Content-Type: application/cdni; ptype=ci-trigger-collection

{
    "cdn-id": "AS64496:0",
    "coll-active": "/triggers/active",
    "coll-complete": "/triggers/complete",
    "coll-failed": "/triggers/failed",
    "coll-pending": "/triggers/pending",
    "staleresourcetime": 86400,
    "triggers": [
        "https://dcdn.example.com/triggers/0",
        "https://dcdn.example.com/triggers/1"
    ]
}

6.2.2. Filtered Collections of Trigger Status Resources ๐Ÿ—‚๏ธ

The filtered collections are available to the uCDN too ๐Ÿซง. Before the dCDN starts processing the two CI/T Trigger Commands from above, both of them will show up in the collection of pending triggers. For example:

REQUEST:

GET /triggers/pending HTTP/1.1
User-Agent: example-user-agent/0.1
Host: dcdn.example.com
Accept: */*

RESPONSE:

HTTP/1.1 200 OK
Content-Length: 152
Expires: Wed, 04 May 2016 08:49:11 GMT
Server: example-server/0.1
ETag: "4331492443626270781"
Cache-Control: max-age=60
Date: Wed, 04 May 2016 08:48:11 GMT
Content-Type: application/cdni; ptype=ci-trigger-collection

{
    "staleresourcetime": 86400,
    "triggers": [
        "https://dcdn.example.com/triggers/0",
        "https://dcdn.example.com/triggers/1"
    ]
}

At this point, if no other Trigger Status Resources had been created, the other filtered views would be empty ๐Ÿซฅ. For example:

REQUEST:

GET /triggers/complete HTTP/1.1
User-Agent: example-user-agent/0.1
Host: dcdn.example.com
Accept: */*

RESPONSE:

HTTP/1.1 200 OK
Content-Length: 54
Expires: Wed, 04 May 2016 08:49:11 GMT
Server: example-server/0.1
ETag: "7958041393922269003"
Cache-Control: max-age=60
Date: Wed, 04 May 2016 08:48:11 GMT
Content-Type: application/cdni; ptype=ci-trigger-collection

{
    "staleresourcetime": 86400,
    "triggers": []
}

6.2.3. Individual Trigger Status Resources ๐Ÿ”Ž

You can also look at the Trigger Status Resources for the details of individual CI/T Trigger Commands ๐Ÿฅฐ. Here they are for the CI/T "preposition" and "invalidate" commands from the earlier examples:

REQUEST:

GET /triggers/0 HTTP/1.1
User-Agent: example-user-agent/0.1
Host: dcdn.example.com
Accept: */*

RESPONSE:

HTTP/1.1 200 OK
Content-Length: 467
Expires: Wed, 04 May 2016 08:49:10 GMT
Server: example-server/0.1
ETag: "6990548174277557683"
Cache-Control: max-age=60
Date: Wed, 04 May 2016 08:48:10 GMT
Content-Type: application/cdni; ptype=ci-trigger-status

{
    "ctime": 1462351690,
    "etime": 1462351698,
    "mtime": 1462351690,
    "status": "pending",
    "trigger": {
        "content.urls": [
            "https://www.example.com/a/b/c/1",
            "https://www.example.com/a/b/c/2",
            "https://www.example.com/a/b/c/3",
            "https://www.example.com/a/b/c/4"
        ],
        "metadata.urls": [
            "https://metadata.example.com/a/b/c"
        ],
        "type": "preposition"
    }
}

REQUEST:

GET /triggers/1 HTTP/1.1
User-Agent: example-user-agent/0.1
Host: dcdn.example.com
Accept: */*

RESPONSE:

HTTP/1.1 200 OK
Content-Length: 545
Expires: Wed, 04 May 2016 08:49:11 GMT
Server: example-server/0.1
ETag: "-554385204989405469"
Cache-Control: max-age=60
Date: Wed, 04 May 2016 08:48:11 GMT
Content-Type: application/cdni; ptype=ci-trigger-status
{
    "ctime": 1462351691,
    "etime": 1462351699,
    "mtime": 1462351691,
    "status": "pending",
    "trigger": {
        "content.patterns": [
            {
                "case-sensitive": true,
                "pattern": "https://www.example.com/a/b/*"
            }
        ],
        "content.urls": [
            "https://www.example.com/a/index.html"
        ],
        "metadata.patterns": [
            {
                "pattern": "https://metadata.example.com/a/b/*"
            }
        ],
        "type": "invalidate"
    }
}

6.2.4. Polling for Changes in Status โœจ

okay so the uCDN SHOULD use the ETags of collections or Trigger Status Resources when it's polling for changes in status ๐Ÿ”„ here's how that looks bestie ๐Ÿ’–

REQUEST:

GET /triggers/pending HTTP/1.1
User-Agent: example-user-agent/0.1
Host: dcdn.example.com
Accept: */*
If-None-Match: "4331492443626270781"

RESPONSE:

HTTP/1.1 304 Not Modified
Content-Length: 0
Expires: Wed, 04 May 2016 08:49:11 GMT
Server: example-server/0.1
ETag: "4331492443626270781"
Cache-Control: max-age=60
Date: Wed, 04 May 2016 08:48:11 GMT
Content-Type: application/cdni; ptype=ci-trigger-collection

REQUEST:

GET /triggers/0 HTTP/1.1
User-Agent: example-user-agent/0.1
Host: dcdn.example.com
Accept: */*
If-None-Match: "6990548174277557683"

RESPONSE:

HTTP/1.1 304 Not Modified
Content-Length: 0
Expires: Wed, 04 May 2016 08:49:10 GMT
Server: example-server/0.1
ETag: "6990548174277557683"
Cache-Control: max-age=60
Date: Wed, 04 May 2016 08:48:10 GMT
Content-Type: application/cdni; ptype=ci-trigger-status

Once the CI/T Trigger Command is complete, the contents of the filtered collections get updated along with their ETags ๐ŸŽ€ For example, once both example CI/T Trigger Commands are complete, the collections of pending and complete Trigger Status Resources might look like this ๐Ÿ‘€

REQUEST:

GET /triggers/pending HTTP/1.1
User-Agent: example-user-agent/0.1
Host: dcdn.example.com
Accept: */*

RESPONSE:

HTTP/1.1 200 OK
Content-Length: 54
Expires: Wed, 04 May 2016 08:49:15 GMT
Server: example-server/0.1
ETag: "1337503181677633762"
Cache-Control: max-age=60
Date: Wed, 04 May 2016 08:48:15 GMT
Content-Type: application/cdni; ptype=ci-trigger-collection

{
    "staleresourcetime": 86400,
    "triggers": []
}

REQUEST:

GET /triggers/complete HTTP/1.1
User-Agent: example-user-agent/0.1
Host: dcdn.example.com
Accept: */*

RESPONSE:

HTTP/1.1 200 OK
Content-Length: 152
Expires: Wed, 04 May 2016 08:49:22 GMT
Server: example-server/0.1
ETag: "4481489539378529796"
Cache-Control: max-age=60
Date: Wed, 04 May 2016 08:48:22 GMT
Content-Type: application/cdni; ptype=ci-trigger-collection

{
    "staleresourcetime": 86400,
    "triggers": [
        "https://dcdn.example.com/triggers/0",
        "https://dcdn.example.com/triggers/1"
    ]
}

6.2.5. Deleting Trigger Status Resources ๐Ÿ—‘๏ธ

okay so the uCDN can delete completed and failed Trigger Status Resources to shrink the collections ๐Ÿงน, as described in Section 4.4. For example, to delete the "preposition" request from the earlier examples ๐Ÿ’…:

REQUEST:

DELETE /triggers/0 HTTP/1.1
User-Agent: example-user-agent/0.1
Host: dcdn.example.com
Accept: */*

RESPONSE:

HTTP/1.1 204 No Content
Date: Wed, 04 May 2016 08:48:22 GMT
Content-Length: 0
Content-Type: text/html; charset=UTF-8
Server: example-server/0.1

This would, for example, cause the collection of completed Trigger Status Resources shown in the example above to be updated to ๐Ÿฅฐ

REQUEST:

GET /triggers/complete HTTP/1.1
User-Agent: example-user-agent/0.1
Host: dcdn.example.com
Accept: */*

RESPONSE:

HTTP/1.1 200 OK
Content-Length: 105
Expires: Wed, 04 May 2016 08:49:22 GMT
Server: example-server/0.1
ETag: "-6938620031669085677"
Cache-Control: max-age=60
Date: Wed, 04 May 2016 08:48:22 GMT
Content-Type: application/cdni; ptype=ci-trigger-collection

{
    "staleresourcetime": 86400,
    "triggers": [
        "https://dcdn.example.com/triggers/1"
    ]
}

6.2.6. Error Reporting ๐Ÿšจ

okay this one is so real ๐Ÿ˜ญ in this example the uCDN asked for pre-positioning of "https://newsite.example.com/index.html", but the dCDN couldn't find metadata for that site ๐Ÿ’€

REQUEST:

GET /triggers/2 HTTP/1.1
User-Agent: example-user-agent/0.1
Host: dcdn.example.com
Accept: */*

RESPONSE:

HTTP/1.1 200 OK
Content-Length: 486
Expires: Wed, 04 May 2016 08:49:26 GMT
Server: example-server/0.1
ETag: "5182824839919043757"
Cache-Control: max-age=60
Date: Wed, 04 May 2016 08:48:26 GMT
Content-Type: application/cdni; ptype=ci-trigger-status

{
    "ctime": 1462351702,
    "errors": [
        {
            "content.urls": [
                "https://newsite.example.com/index.html"
            ],
            "description": "newsite.example.com not in HostIndex",
            "error": "emeta"
        }
    ],
    "etime": 1462351710,
    "mtime": 1462351706,
    "status": "active",
    "trigger": {
        "content.urls": [
            "https://newsite.example.com/index.html"
        ],
        "type": "preposition"
    }
}

7. IANA Considerations ๐ŸŒธ

7.1. CDNI Payload Type Parameter Registrations ๐ŸŽ€

The IANA is requested to register the following new Payload Types in the "CDNI Payload Types" registry defined by [RFC7736], for use with the "application/cdni" MIME media type.

+-----------------------+---------------+
| Payload Type          | Specification |
+-----------------------+---------------+
| ci-trigger-command    | RFC 8007      |
| ci-trigger-status     | RFC 8007      |
| ci-trigger-collection | RFC 8007      |
+-----------------------+---------------+

7.2. "CDNI CI/T Trigger Types" Registry ๐Ÿงš

The IANA is requested to create a new "CDNI CI/T Trigger Types" subregistry under the "Content Delivery Network Interconnection (CDNI) Parameters" registry.

Additions to the "CDNI CI/T Trigger Types" registry will be made via the RFC Required policy as defined in [RFC5226].

The initial contents of the "CDNI CI/T Trigger Types" registry comprise the names and descriptions listed in Section 5.2.2 of this document, with this document acting as the specification.

7.3. "CDNI CI/T Error Codes" Registry ๐Ÿ’œ

The IANA is requested to create a new "CDNI CI/T Error Codes" subregistry under the "Content Delivery Network Interconnection (CDNI) Parameters" registry.

Additions to the "CDNI CI/T Error Codes" registry will be made via the Specification Required policy as defined in [RFC5226]. The Designated Expert will verify that new Error Code registrations do not duplicate existing Error Code definitions (in name or functionality), prevent gratuitous additions to the namespace, and prevent any additions to the namespace that would impair the interoperability of CDNI implementations.

The initial contents of the "CDNI CI/T Error Codes" registry comprise the names and descriptions of the Error Codes listed in Section 5.2.7 of this document, with this document acting as the specification.


8. Security Considerations ๐Ÿ”ฅ

okay this section is SERIOUS bestie, read it all ๐Ÿ™ˆ

The CI/T interface provides a mechanism to allow a uCDN to generate requests into the dCDN and to inspect its own CI/T requests and their current states. The CI/T interface does not allow access to, or modification of, the uCDN or dCDN metadata relating to content delivery or to the content itself. It can only control the presence of that metadata in the dCDN, and the processing work and network utilization involved in ensuring that presence.

By examining "preposition" requests to a dCDN, and correctly interpreting content and metadata URLs, an attacker could learn the uCDN's or content owner's predictions for future content popularity. By examining "invalidate" or "purge" requests, an attacker could learn about changes in the content owner's catalog.

By injecting CI/T Commands, an attacker or a misbehaving uCDN would generate work in the dCDN and uCDN as they process those requests. So would a man-in-the-middle attacker modifying valid CI/T Commands generated by the uCDN. In both cases, that would decrease the dCDN's caching efficiency by causing it to unnecessarily acquire or reacquire content metadata and/or content.

A dCDN implementation of CI/T MUST restrict the actions of a uCDN to the data corresponding to that uCDN. Failure to do so would allow uCDNs to detrimentally affect each other's efficiency by generating unnecessary acquisition or reacquisition load.

An origin that chooses to delegate its delivery to a CDN is trusting that CDN to deliver content on its behalf; the interconnection of CDNs is an extension of that trust to dCDNs. That trust relationship is a commercial arrangement, outside the scope of the CDNI protocols. So, while a malicious CDN could deliberately generate load on a dCDN using the CI/T interface, the protocol does not otherwise attempt to address malicious behavior between interconnected CDNs.

8.1. Authentication, Authorization, Confidentiality, Integrity Protection ๐Ÿ”

A CI/T implementation MUST support Transport Layer Security (TLS) transport for HTTP (HTTPS) as per [RFC2818] and [RFC7230].

TLS MUST be used by the server side (dCDN) and the client side (uCDN) of the CI/T interface, including authentication of the remote end, unless alternate methods are used for ensuring the security of the information in the CI/T interface requests and responses (such as setting up an IPsec tunnel between the two CDNs or using a physically secured internal network between two CDNs that are owned by the same corporate entity).

The use of TLS for transport of the CI/T interface allows the dCDN and the uCDN to authenticate each other using TLS client authentication and TLS server authentication.

Once the dCDN and the uCDN have mutually authenticated each other, TLS allows:

  • The dCDN and the uCDN to authorize each other (to ensure that they are receiving CI/T Commands from, or reporting status to, an authorized CDN).
  • CDNI commands and responses to be transmitted with confidentiality.
  • Protection of the integrity of CDNI commands and responses.

When TLS is used, the general TLS usage guidance in [RFC7525] MUST be followed.

The mechanisms for access control are dCDN-specific and are not standardized as part of this CI/T specification.

HTTP requests that attempt to access or operate on CI/T data belonging to another CDN MUST be rejected using, for example, HTTP 403 ("Forbidden") or 404 ("Not Found"). This is intended to prevent unauthorized users from generating unnecessary load in dCDNs or uCDNs due to revalidation, reacquisition, or unnecessary acquisition.

When deploying a network of interconnected CDNs, the possible inefficiencies related to the diamond configuration discussed in Section 2.2.1 should be considered.

8.2. Denial of Service ๐Ÿ›ก๏ธ

This document does not define a specific mechanism to protect against Denial-of-Service (DoS) attacks on the CI/T interface. However, CI/T endpoints can be protected against DoS attacks through the use of TLS transport and/or via mechanisms outside the scope of the CI/T interface, such as firewalling or the use of Virtual Private Networks (VPNs).

Depending on the implementation, triggered activity may consume significant processing and bandwidth in the dCDN. A malicious or faulty uCDN could use this to generate unnecessary load in the dCDN. The dCDN should consider mechanisms to avoid overload -- for example, by rate-limiting acceptance or processing of CI/T Commands, or by performing batch processing.

8.3. Privacy โœจ

okay so bestie, the CI/T protocol does NOT carry any info about individual end users of a CDN ๐Ÿ™ˆ so there are no privacy concerns for end users. slay, we're safe on that front ๐Ÿซถ

BUT ๐Ÿ˜ญ the CI/T protocol does carry stuff that CDN operators and content owners could consider commercially sensitive ๐Ÿ’ผ that's the tea. the good news is mutually authenticated TLS ๐Ÿ” (the setup we talked about in Section 8.1) keeps that data confidential while it's zipping around in transit ๐Ÿฆ‹ and it stops anyone who isn't the authorized dCDN from peeking at it ๐Ÿ‘€ literally main character energy for security ๐Ÿ‘‘

the dCDN MUST ensure that it only exposes CI/T data related to a uCDN to clients it has authenticated as belonging to that uCDN. no sharing the tea with randos, periodt ๐Ÿ’…

9. References ๐Ÿ“š

9.1. Normative References ๐Ÿ’–

9.2. Informative References ๐ŸŒธ

Appendix A. Formalization of the JSON Data ๐Ÿงš

This appendix is non-normative. ๐Ÿ“

The JSON data described in this document has been formalized using the CBOR Data Definition Language (CDDL) [CBOR-CDDL] (where "CBOR" means "Concise Binary Object Representation"), as follows: ๐Ÿ’œ

 CIT-object = CIT-command / Trigger-Status-Resource / Trigger-Collection

 CIT-command ; use media type application/cdni; ptype=ci-trigger-command
 = {
   ? trigger: Triggerspec
   ? cancel: [* URI]
   cdn-path: [* Cdn-PID]
 }

 Trigger-Status-Resource ; application/cdni; ptype=ci-trigger-status
 = {
   trigger: Triggerspec
   ctime: Absolute-Time
   mtime: Absolute-Time
   ? etime: Absolute-Time
   status: Trigger-Status
   ? errors: [* Error-Description]
 }

 Trigger-Collection ; application/cdni; ptype=ci-trigger-collection
 = {
   triggers: [* URI]
   ? staleresourcetime: int ; time in seconds
   ? coll-all: URI
   ? coll-pending: URI
   ? coll-active: URI
   ? coll-complete: URI
   ? coll-failed: URI
   ? cdn-id: Cdn-PID
 }

 Triggerspec = { ; see Section 5.2.1
   type: Trigger-Type
   ? metadata.urls: [* URI]
   ? content.urls: [* URI]
   ? content.ccid: [* Ccid]
   ? metadata.patterns: [* Pattern-Match]
   ? content.patterns: [* Pattern-Match]
 }
 Trigger-Type = "preposition" / "invalidate"
    / "purge" ; see Section 5.2.2

 Trigger-Status = "pending" / "active" / "complete" / "processed"
    / "failed" / "cancelling" / "cancelled" ; see Section 5.2.3

 Pattern-Match = { ; see Section 5.2.4
   pattern: tstr
   ? case-sensitive: bool
   ? match-query-string: bool
 }

 Absolute-Time = number ; seconds since UNIX epoch (Section 5.2.5)

 Error-Description = { ; see Section 5.2.6
   error: Error-Code
   ? metadata.urls: [* URI]
   ? content.urls: [* URI]
   ? metadata.patterns: [* Pattern-Match]
   ? content.patterns: [* Pattern-Match]
   ? description: tstr
 }

 Error-Code = "emeta" / "econtent" / "eperm" / "ereject"
    / "ecdn" / "ecanceled"  ; see Section 5.2.7

 Ccid = tstr ; see RFC 8006

 Cdn-PID = tstr .regexp "AS[0-9]+:[0-9]+"

 URI = tstr

Acknowledgments ๐Ÿ’–

The authors thank Kevin Ma for his input, and Carsten Bormann for his review and formalization of the JSON data. ๐Ÿซถ

Authors' Addresses ๐ŸŽ€

Rob Murray Nokia 3 Ely Road Milton, Cambridge CB24 6DD United Kingdom

Email: rob.murray@nokia.com

Ben Niven-Jenkins Nokia 3 Ely Road Milton, Cambridge CB24 6DD United Kingdom

Email: ben.niven-jenkins@nokia.com

๐Ÿ“ฆ where this page comes from