idnits 2.17.1 draft-ietf-alto-incr-update-sse-22.txt: Checking boilerplate required by RFC 5378 and the IETF Trust (see https://trustee.ietf.org/license-info): ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/1id-guidelines.txt: ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/checklist : ---------------------------------------------------------------------------- ** The abstract seems to contain references ([RFC7285]), which it shouldn't. Please replace those with straight textual mentions of the documents in question. Miscellaneous warnings: ---------------------------------------------------------------------------- == The copyright year in the IETF Trust and authors Copyright Line does not match the current year == Line 1002 has weird spacing: '...atesReq add;...' == Line 1012 has weird spacing: '...NString tag;]...' -- The document date (March 20, 2020) is 1498 days in the past. Is this intentional? Checking references for intended status: Proposed Standard ---------------------------------------------------------------------------- (See RFCs 3967 and 4897 for information about using normative references to lower-maturity documents in RFCs) == Missing Reference: 'RFCthis' is mentioned on line 2364, but not defined -- Possible downref: Non-RFC (?) normative reference: ref. 'SSE' -- Obsolete informational reference (is this intentional?): RFC 4960 (Obsoleted by RFC 9260) -- Obsolete informational reference (is this intentional?): RFC 7230 (Obsoleted by RFC 9110, RFC 9112) -- Obsolete informational reference (is this intentional?): RFC 7231 (Obsoleted by RFC 9110) -- Obsolete informational reference (is this intentional?): RFC 7540 (Obsoleted by RFC 9113) Summary: 1 error (**), 0 flaws (~~), 4 warnings (==), 6 comments (--). Run idnits with the --verbose option for more detailed information about the items above. -------------------------------------------------------------------------------- 2 ALTO WG W. Roome 3 Internet-Draft Nokia Bell Labs 4 Intended status: Standards Track Y. Yang 5 Expires: September 21, 2020 Yale University 6 March 20, 2020 8 ALTO Incremental Updates Using Server-Sent Events (SSE) 9 draft-ietf-alto-incr-update-sse-22 11 Abstract 13 The Application-Layer Traffic Optimization (ALTO) [RFC7285] protocol 14 provides network related information, called network information 15 resources, to client applications so that clients can make informed 16 decisions in utilizing network resources. This document presents a 17 mechanism to allow an ALTO server to push updates to ALTO clients, to 18 achieve two benefits: (1) updates can be incremental, in that if only 19 a small section of an information resource changes, the ALTO server 20 can send just the changes; and (2) updates can be immediate, in that 21 the ALTO server can send updates as soon as they are available. 23 Requirements Language 25 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 26 "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and 27 "OPTIONAL" in this document are to be interpreted as described in BCP 28 14 [RFC2119][RFC8174] when, and only when, they appear in all 29 capitals, as shown here. 31 Status of This Memo 33 This Internet-Draft is submitted in full conformance with the 34 provisions of BCP 78 and BCP 79. 36 Internet-Drafts are working documents of the Internet Engineering 37 Task Force (IETF). Note that other groups may also distribute 38 working documents as Internet-Drafts. The list of current Internet- 39 Drafts is at http://datatracker.ietf.org/drafts/current/. 41 Internet-Drafts are draft documents valid for a maximum of six months 42 and may be updated, replaced, or obsoleted by other documents at any 43 time. It is inappropriate to use Internet-Drafts as reference 44 material or to cite them other than as "work in progress." 46 This Internet-Draft will expire on September 21, 2020. 48 Copyright Notice 50 Copyright (c) 2020 IETF Trust and the persons identified as the 51 document authors. All rights reserved. 53 This document is subject to BCP 78 and the IETF Trust's Legal 54 Provisions Relating to IETF Documents 55 (http://trustee.ietf.org/license-info) in effect on the date of 56 publication of this document. Please review these documents 57 carefully, as they describe your rights and restrictions with respect 58 to this document. Code Components extracted from this document must 59 include Simplified BSD License text as described in Section 4.e of 60 the Trust Legal Provisions and are provided without warranty as 61 described in the Simplified BSD License. 63 Table of Contents 65 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 66 2. Terms . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 67 3. Background . . . . . . . . . . . . . . . . . . . . . . . . . 6 68 3.1. Incremental Encoding: JSON Merge Patch . . . . . . . . . 6 69 3.1.1. JSON Merge Patch Encoding . . . . . . . . . . . . . . 6 70 3.1.2. JSON Merge Patch ALTO Messages . . . . . . . . . . . 7 71 3.2. Incremental Encoding: JSON Patch . . . . . . . . . . . . 10 72 3.2.1. JSON Patch Encoding . . . . . . . . . . . . . . . . . 11 73 3.2.2. JSON Patch ALTO Messages . . . . . . . . . . . . . . 11 74 3.3. Multiplexing and Server Push: HTTP/2 . . . . . . . . . . 13 75 3.4. Server Push: Server-Sent Event . . . . . . . . . . . . . 14 76 4. Overview of Approach and High-level Protocol Message Flow . . 15 77 4.1. Update Stream Service Message Flow . . . . . . . . . . . 16 78 4.2. Stream Control Service Message Flow . . . . . . . . . . . 17 79 4.3. Service Announcement and Management Message Flow . . . . 18 80 5. Update Messages: Data Update and Control Update Messages . . 19 81 5.1. Generic ALTO Update Message Structure . . . . . . . . . . 19 82 5.2. ALTO Data Update Message . . . . . . . . . . . . . . . . 19 83 5.3. ALTO Control Update Message . . . . . . . . . . . . . . . 21 84 6. Update Stream Service . . . . . . . . . . . . . . . . . . . . 22 85 6.1. Media Type . . . . . . . . . . . . . . . . . . . . . . . 22 86 6.2. HTTP Method . . . . . . . . . . . . . . . . . . . . . . . 22 87 6.3. Capabilities . . . . . . . . . . . . . . . . . . . . . . 22 88 6.4. Uses . . . . . . . . . . . . . . . . . . . . . . . . . . 23 89 6.5. Request: Accept Input Parameters . . . . . . . . . . . . 23 90 6.6. Response . . . . . . . . . . . . . . . . . . . . . . . . 25 91 6.7. Additional Requirements on Update Stream Service . . . . 27 92 6.7.1. Event Sequence Requirements . . . . . . . . . . . . . 27 93 6.7.2. Cross-Stream Consistency Requirements . . . . . . . . 27 94 6.7.3. Multipart Update Requirements . . . . . . . . . . . . 28 95 6.8. Keep-Alive Messages . . . . . . . . . . . . . . . . . . . 28 97 7. Stream Control Service . . . . . . . . . . . . . . . . . . . 29 98 7.1. URI . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 99 7.2. Media Type . . . . . . . . . . . . . . . . . . . . . . . 30 100 7.3. HTTP Method . . . . . . . . . . . . . . . . . . . . . . . 30 101 7.4. IRD Capabilities & Uses . . . . . . . . . . . . . . . . . 30 102 7.5. Request: Accept Input Parameters . . . . . . . . . . . . 30 103 7.6. Response . . . . . . . . . . . . . . . . . . . . . . . . 31 104 8. Examples . . . . . . . . . . . . . . . . . . . . . . . . . . 32 105 8.1. Example: IRD Announcing Update Stream Services . . . . . 32 106 8.2. Example: Simple Network and Cost Map Updates . . . . . . 35 107 8.3. Example: Advanced Network and Cost Map Updates . . . . . 38 108 8.4. Example: Endpoint Property Updates . . . . . . . . . . . 41 109 8.5. Example: Multipart Message Updates . . . . . . . . . . . 45 110 9. Operation and Processing Considerations . . . . . . . . . . . 47 111 9.1. Considerations for Choosing Data Update Messages . . . . 47 112 9.2. Considerations for Client Processing Data Update Messages 48 113 9.3. Considerations for Updates to Filtered Cost Maps . . . . 49 114 9.4. Considerations for Updates to Ordinal Mode Costs . . . . 50 115 9.5. Considerations for SSE Text Formatting and Processing . . 50 116 10. Security Considerations . . . . . . . . . . . . . . . . . . . 51 117 10.1. Update Stream Server: Denial-of-Service Attacks . . . . 51 118 10.2. ALTO Client: Update Overloading or Instability . . . . . 52 119 10.3. Stream Control: Spoofed Control Requests and Information 120 Breakdown . . . . . . . . . . . . . . . . . . . . . . . 52 121 11. Requirements on Future ALTO Services to Use this Design . . . 52 122 12. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 53 123 12.1. application/alto-updatestreamparams+json Media Type . . 53 124 12.2. application/alto-updatestreamcontrol+json Media Type . . 54 125 13. Contributors . . . . . . . . . . . . . . . . . . . . . . . . 55 126 14. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 55 127 15. Appendix: Design Decision: Not Allowing Stream Restart . . . 56 128 16. References . . . . . . . . . . . . . . . . . . . . . . . . . 57 129 16.1. Normative References . . . . . . . . . . . . . . . . . . 57 130 16.2. Informative References . . . . . . . . . . . . . . . . . 57 131 Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 58 133 1. Introduction 135 The Application-Layer Traffic Optimization (ALTO) [RFC7285] protocol 136 provides network related information called network information 137 resources to client applications so that clients may make informed 138 decisions in utilizing network resources. For example, an ALTO 139 server provides network and cost maps, where a network map partitions 140 the set of endpoints into a manageable number of sets each defined by 141 a Provider-Defined Identifier (PID), and a cost map provides directed 142 costs between PIDs. Given network and cost maps, an ALTO client can 143 obtain costs between endpoints by first using the network map to get 144 the PID for each endpoint, and then using the cost map to get the 145 costs between those PIDs. Such costs can be used by the client to 146 choose communicating endpoints with low network costs. 148 The ALTO protocol defines only an ALTO client pull model, without 149 defining a mechanism to allow an ALTO client to obtain updates to 150 network information resources, other than by periodically re-fetching 151 them. In settings where an information resource may be large but 152 only parts of it may change frequently (e.g., some entries of a cost 153 map), complete re-fetching can be inefficient. 155 This document presents a mechanism to allow an ALTO server to push 156 incremental updates to ALTO clients. Integrating server-push and 157 incremental updates provides two benefits: (1) updates can be small, 158 in that if only a small section of an information resource changes, 159 the ALTO server can send just the changes; and (2) updates can be 160 immediate, in that the ALTO server can send updates as soon as they 161 are available. 163 While primarily intended to provide updates to GET-mode network and 164 cost maps, the mechanism defined in this document can also provide 165 updates to POST-mode ALTO services, such as the ALTO endpoint 166 property and endpoint cost services. The mechanism can also support 167 new ALTO services to be defined by future extensions, but a future 168 service needs to satisfy requirements specified in Section 11. 170 The rest of this document is organized as follows. Section 3 gives 171 background on the basic techniques used in this design: (1) JSON 172 merge patch and JSON patch to allow incremental update; and (2) 173 Server-Sent Events (SSE) [SSE] to allow server push. With the 174 background, Section 4 gives a non-normative overview of the design. 175 Section 5 defines individual messages in an update stream. Section 6 176 defines the update stream service; Section 7 defines the stream 177 control service; Section 8 gives several examples to illustrate the 178 two types of services. Section 9 describes operation and processing 179 considerations by both ALTO servers and clients; Section 15 discusses 180 a design feature that is not supported; Section 10 discusses security 181 issues; Section 11 and Section 12 review the requirements for future 182 ALTO services to use SSE and IANA considerations, respectively. 184 2. Terms 186 Besides the terminologies as defined in [RFC7285], this document also 187 uses additional terminologies defined as follows: 189 Update Stream: A reliable, in-order HTTP/1.x compatible connection 190 between an ALTO client and an ALTO server so that the server can push 191 a sequence of update messages using [SSE] to the client. 193 Update Stream Server: This document refers to an ALTO server 194 providing an update stream as an ALTO update stream server, or update 195 stream server for short. Note that the ALTO server mentioned in this 196 document refers to a general server that provides various kinds of 197 services; it can be an update stream server or stream control server 198 (see below); it can also be a server providing ALTO Information 199 Resource Directory (IRD). 201 Update Message: A message that is either a data update message or a 202 control update message. 204 Data Update Message: An update message that is for a single ALTO 205 information resource and sent from the update stream server to the 206 ALTO client when the resource changes. A data update message can be 207 either a full-replacement message or an incremental-change message. 208 Full replacement is a shorthand for a full-replacement message, and 209 incremental change is a shorthand for an incremental-change message. 211 Full Replacement: A data update message for a resource that encodes 212 the content of the resource in its original ALTO encoding. 214 Incremental Change: An data update message that specifies only the 215 difference between the new content and the previous version. An 216 incremental change can be encoded using either JSON merge patch or 217 JSON patch in this document. 219 Stream Control Service: A service that provides an HTTP URI so that 220 the ALTO client of an update stream can use it to send stream control 221 requests to the ALTO server on the addition or removal of resources 222 receiving update messages from the update stream. The ALTO server 223 creates a new stream control resource for each update stream 224 instance, assigns a unique URI to it, and sends the URI to the client 225 as the first event in the stream. (Note that the Stream Control 226 Service in ALTO has no association with the similarly named Stream 227 Control Transmission Protocol [RFC4960].) 229 Stream Control: A shorthand for stream control service. 231 Stream Control Server: An ALTO server providing the stream control 232 service. 234 Substream-ID: An ALTO client can assign a unique substream-id when 235 requesting the addition of a resource receiving update messages from 236 an update stream. The server puts the substream-id in each update 237 event for that resource. Substream-id allows a client to use one 238 update stream to receive updates to multiple requests for the same 239 resource (i.e., with the same resource-id in an ALTO IRD), for 240 example, for a POST-mode resource with different input parameters. 242 Data-ID: A subfield of the `event` field of [SSE] to identify the 243 ALTO data (object) to be updated. For an ALTO resource returning a 244 multipart response, the data-id to identify the data (object) is the 245 substream-id, in addition to the content-id of the object in the 246 multipart response. The data-id of a single part response is just 247 the substream-id. 249 Control Update Message: An update message for the update stream 250 server to notify the ALTO client of related control information of 251 the update stream. A control update message may be triggered by an 252 internal event at the server, such as server overloading and hence 253 the update stream server will no longer send updates for an 254 information resource, or as a result of a client sending a request 255 through the stream control service. The first message of an update 256 stream is a control update message and provides the URI using which 257 the ALTO client can send stream control requests to the stream 258 control server. 260 3. Background 262 The design requires two basic techniques: encoding of incremental 263 changes and server push. For incremental changes, existing 264 techniques include JSON merge patch and JSON patch; this design uses 265 both. For server push, existing techniques include HTTP/2 and [SSE]; 266 this design adopts some design features of HTTP/2 but uses [SSE] as 267 the basic server-push design. The rest of this section gives a non- 268 normative summary of JSON merge patch, JSON patch, HTTP/2 and [SSE]. 270 3.1. Incremental Encoding: JSON Merge Patch 272 To avoid always sending complete data, a server needs mechanisms to 273 encode incremental changes, and JSON merge patch is one mechanism. 274 [RFC7396] defines the encoding of incremental changes (called JSON 275 merge patch objects) to be used by the HTTP PATCH method [RFC5789]. 276 This document adopts from [RFC7396] only the JSON merge patch object 277 encoding and does not use the HTTP PATCH method, as the updates are 278 sent as events, instead of HTTP methods; also the updates are server- 279 to-client in the updates, and PATCH semantics is more for client-to- 280 server. Below is a non-normative summary of JSON merge patch 281 objects; see [RFC7396] for the normative definition. 283 3.1.1. JSON Merge Patch Encoding 285 Informally, a JSON merge patch message consists of a JSON merge patch 286 object (referred to as a patch in [RFC7396]), which defines how to 287 transform one JSON value into another using a recursive merge patch 288 algorithm. Specifically, the patch is computed by treating two JSON 289 values (first one being the original, and the second being the 290 updated) as trees of nested JSON objects (dictionaries of name-value 291 pairs), where the leaves are values (e.g., JSON arrays, strings, 292 numbers) other than JSON objects and the path for each leaf is the 293 sequence of keys leading to that leaf. When the second tree has a 294 different value for a leaf at a path, or adds a new leaf, the patch 295 has a leaf, at that path, with the new value. When a leaf in the 296 first tree does not exist in the second tree, the JSON merge patch 297 tree has a leaf with a JSON "null" value. Hence, in the patch, null 298 as the value of a name/value pair will delete the element with "name" 299 in the original JSON value. The patch does not have an entry for any 300 leaf that has the same value in both versions. See the MergePatch 301 pseudocode at the beginning of Section 2 of [RFC7396] for the formal 302 specification of how to apply a given patch. As a result, if all 303 leaf values are simple scalars, JSON merge patch is a quite efficient 304 representation of incremental changes. It is less efficient when 305 leaf values are arrays, because JSON merge patch replaces arrays in 306 their entirety, even if only one entry changes. 308 3.1.2. JSON Merge Patch ALTO Messages 310 To provide both examples of JSON merge patch and a demonstration of 311 the feasibility of applying JSON merge patch to ALTO, the sections 312 below show the application of JSON merge patch to two key ALTO 313 messages. 315 3.1.2.1. JSON Merge Patch Network Map Messages 317 Section 11.2.1.6 of [RFC7285] defines the format of an ALTO network 318 map message. Assume a simple example ALTO message sending an initial 319 network map: 321 { 322 "meta" : { 323 "vtag": { 324 "resource-id" : "my-network-map", 325 "tag" : "da65eca2eb7a10ce8b059740b0b2e3f8eb1d4785" 326 } 327 }, 328 "network-map" : { 329 "PID1" : { 330 "ipv4" : [ "192.0.2.0/24", "198.51.100.0/25" ] 331 }, 332 "PID2" : { 333 "ipv4" : [ "198.51.100.128/25" ] 334 }, 335 "PID3" : { 336 "ipv4" : [ "0.0.0.0/0" ], 337 "ipv6" : [ "::/0" ] 338 } 339 } 340 } 342 Consider the following JSON merge patch update message, which (1) 343 adds an ipv4 prefix "203.0.113.0/25" and an ipv6 prefix 344 "2001:db8:8000::/33" to "PID1", (2) deletes "PID2", and (3) assigns a 345 new "tag" to the network map: 347 { 348 "meta" : { 349 "vtag" : { 350 "tag" : "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 351 } 352 }, 353 "network-map": { 354 "PID1" : { 355 "ipv4" : [ "192.0.2.0/24", "198.51.100.0/25", 356 "203.0.113.0/25" ], 357 "ipv6" : [ "2001:db8:8000::/33" ] 358 }, 359 "PID2" : null 360 } 361 } 363 Applying the JSON merge patch update to the initial network map is 364 equivalent to the following ALTO network map: 366 { 367 "meta" : { 368 "vtag": { 369 "resource-id" : "my-network-map", 370 "tag" : "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 371 } 372 }, 373 "network-map" : { 374 "PID1" : { 375 "ipv4" : [ "192.0.2.0/24", "198.51.100.0/25", 376 "203.0.113.0/25" ], 377 "ipv6" : [ "2001:db8:8000::/33" ] 378 }, 379 "PID3" : { 380 "ipv4" : [ "0.0.0.0/0" ], 381 "ipv6" : [ "::/0" ] 382 } 383 } 384 } 386 3.1.2.2. JSON Merge Patch Cost Map Messages 388 Section 11.2.3.6 of [RFC7285] defines the format of an ALTO cost map 389 message. Assume a simple example ALTO message for an initial cost 390 map: 392 { 393 "meta" : { 394 "dependent-vtags" : [ 395 {"resource-id": "my-network-map", 396 "tag": "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 397 } 398 ], 399 "cost-type" : { 400 "cost-mode" : "numerical", 401 "cost-metric": "routingcost" 402 }, 403 "vtag": { 404 "resource-id" : "my-cost-map", 405 "tag" : "3ee2cb7e8d63d9fab71b9b34cbf764436315542e" 406 } 407 }, 408 "cost-map" : { 409 "PID1": { "PID1": 1, "PID2": 5, "PID3": 10 }, 410 "PID2": { "PID1": 5, "PID2": 1, "PID3": 15 }, 411 "PID3": { "PID1": 20, "PID2": 15 } 412 } 413 } 415 The following JSON merge patch message updates the example cost map 416 so that (1) the "tag" field of the cost map is updated, (2) the cost 417 of PID1->PID2 is 9 instead of 5, (3) the cost of PID3->PID1 is no 418 longer available, and (4) the cost of PID3->PID3 is defined as 1. 420 { 421 "meta" : { 422 "vtag": { 423 "tag": "c0ce023b8678a7b9ec00324673b98e54656d1f6d" 424 } 425 } 426 "cost-map" : { 427 "PID1" : { "PID2" : 9 }, 428 "PID3" : { "PID1" : null, "PID3" : 1 } 429 } 430 } 432 Hence applying the JSON merge patch to the initial cost map is 433 equivalent to the following ALTO cost map: 435 { 436 "meta" : { 437 "dependent-vtags" : [ 438 {"resource-id": "my-network-map", 439 "tag": "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 440 } 441 ], 442 "cost-type" : { 443 "cost-mode" : "numerical", 444 "cost-metric": "routingcost" 445 }, 446 "vtag": { 447 "resource-id": "my-cost-map", 448 "tag": "c0ce023b8678a7b9ec00324673b98e54656d1f6d" 449 } 450 }, 451 "cost-map" : { 452 "PID1": { "PID1": 1, "PID2": 9, "PID3": 10 }, 453 "PID2": { "PID1": 5, "PID2": 1, "PID3": 15 }, 454 "PID3": { "PID2": 15, "PID3": 1 } 455 } 456 } 458 3.2. Incremental Encoding: JSON Patch 459 3.2.1. JSON Patch Encoding 461 One issue of JSON merge patch is that it does not handle array 462 changes well. In particular, JSON merge patch considers an array as 463 a single object and hence can only replace an array in its entirety. 464 When the change is to make a small change to an array such as the 465 deletion of an element from a large array, whole-array replacement is 466 inefficient. Consider the example in Section 3.1.2.1. To add a new 467 entry to the ipv4 array for PID1, the server needs to send a whole 468 new array. Another issue is that JSON merge patch cannot change a 469 value to be null, as the JSON merge patch processing algorithm 470 (MergePatch in Section 3.1.1) interprets a null as a removal 471 instruction. On the other hand, some ALTO resources can have null 472 values, and it is possible that the update will want to change the 473 new value to be null. 475 JSON patch [RFC6902] can address the preceding issues. It defines a 476 set of operators to modify a JSON object. See [RFC6902] for the 477 normative definition. 479 3.2.2. JSON Patch ALTO Messages 481 To provide both examples of JSON patch and a demonstration of the 482 difference between JSON patch and JSON merge patch, the sections 483 below show the application of JSON patch to the same updates shown in 484 Section 3.1.2. 486 3.2.2.1. JSON Patch Network Map Messages 488 First consider the same update as in Section 3.1.2.1 for the network 489 map. Below is the encoding using JSON patch: 491 [ 492 { 493 "op": "replace", 494 "path": "/meta/vtag/tag", 495 "value": "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 496 }, 497 { 498 "op": "add", 499 "path": "/network-map/PID1/ipv4/2", 500 "value": "203.0.113.0/25" 501 } 502 { 503 "op": "add", 504 "path": "/network-map/PID1/ipv6", 505 "value": ["2001:db8:8000::/33"] 506 }, 507 { 508 "op": "remove", 509 "path": "/network-map/PID2" 510 } 511 ] 513 3.2.2.2. JSON Patch Cost Map Messages 515 Compared with JSON merge patch, JSON patch does not encode cost map 516 updates efficiently. Consider the cost map update shown in 517 Section 3.1.2.2, the encoding using JSON patch is: 519 [ 520 { 521 "op": "replace", 522 "path": "/meta/vtag/tag", 523 "value": "c0ce023b8678a7b9ec00324673b98e54656d1f6d" 524 }, 525 { 526 "op": "replace", 527 "path": "/cost-map/PID1/PID2", 528 "value": 9 529 }, 530 { 531 "op": "remove", 532 "path": "/cost-map/PID3/PID1" 533 }, 534 { 535 "op": "replace", 536 "path": "/cost-map/PID3/PID3", 537 "value": 1 538 } 539 ] 541 3.3. Multiplexing and Server Push: HTTP/2 543 HTTP/2 ([RFC7540]) provides two related features: multiplexing and 544 server push. In particular, HTTP/2 allows a client and a server to 545 multiplex multiple HTTP requests and responses over a single TCP 546 connection. The requests and responses can be interleaved on a block 547 (frame) by block (frame) basis, by indicating the requests and 548 responses in HTTP/2 messages, avoiding the head-of-line blocking 549 problem encountered with HTTP/1.1. To achieve the same goal, this 550 design introduces substream-id to allow a client to receive updates 551 to multiple resources. HTTP/2 also provides a Server Push facility, 552 to allow a server to send asynchronous updates. 554 Despite the two features of HTTP/2, this design chooses an 555 HTTP/1.x-compatible design for the simplicity of HTTP/1.x. An HTTP/2 556 based design may more likely need to be implemented using a more 557 complex HTTP/2 client library. In such a case, one approach for 558 using Server Push for updates is for the update stream server to send 559 each data update message as a separate Server Push item and let the 560 client apply those updates as they arrive. An HTTP/2 client library 561 may not necessarily inform a client application when the server 562 pushes a resource. Instead, the library might cache the pushed 563 resource, and only deliver it to the client when the client 564 explicitly requests that URI. Further, it is more likely that an 565 HTTP/2 based design may encounter issues with a proxy between the 566 client and the server, in that Server Push is optional and can be 567 disabled by any proxy between the client and the server. This is not 568 a problem for the intended use of Server Push: eventually the client 569 will request those resources, so disabling Server Push just adds a 570 delay. But this means that Server Push is not suitable for resources 571 which the client does not know to request. 573 Thus this design leaves an HTTP/2 based design as a future work and 574 focuses on ALTO updates on HTTP/1.x and [SSE]. 576 3.4. Server Push: Server-Sent Event 578 Server-Sent Events (SSE) is a technique which can work with HTTP/1.1. 579 The following is a non-normative summary of SSE; see [SSE] for its 580 normative definition. 582 SSE enable a server to send new data to a client by "server-push". 583 The client establishes an HTTP ([RFC7230], [RFC7231]) connection to 584 the server and keeps the connection open. The server continually 585 sends messages. Each message has one or more lines, where a line is 586 terminated by a carriage-return immediately followed by a new-line, a 587 carriage-return not immediately followed by a new-line, or a new-line 588 not immediately preceded by a carriage-return. A message is 589 terminated by a blank line (two line terminators in a row). 591 Each line in a message is of the form "field-name: string value". 592 Lines with a blank field-name (that is, lines which start with a 593 colon) are ignored, as are lines which do not have a colon. The 594 protocol defines three field names: event, id, and data. If a 595 message has more than one "data" line, the value of the data field is 596 the concatenation of the values on those lines. There can be only 597 one "event" and "id" line per message. The "data" field is required; 598 the others are optional. 600 Figure 1 is a sample SSE stream, starting with the client request. 601 The server sends three events and then closes the stream. 603 (Client request) 604 GET /stream HTTP/1.1 605 Host: example.com 606 Accept: text/event-stream 608 (Server response) 609 HTTP/1.1 200 OK 610 Connection: keep-alive 611 Content-Type: text/event-stream 613 event: start 614 id: 1 615 data: hello there 617 event: middle 618 id: 2 619 data: let's chat some more ... 620 data: and more and more and ... 622 event: end 623 id: 3 624 data: goodbye 626 Figure 1: A Sample SSE stream. 628 4. Overview of Approach and High-level Protocol Message Flow 630 With the preceding background, this section now gives a non-normative 631 overview of the update mechanisms and message flow to be defined in 632 later sections of this document. Figure 2 gives the main components 633 and overall message flow. 635 ------------------------------------------------------------------ 636 | | 637 | +-------+ +-------+ 1. init request +------+ | 638 | | | | | <------------- | | | 639 | | | | | -------------> | | | 640 | 3.add/ | | | | 1'. control uri | | | 641 | remove | | | | | | | 642 | resource |Stream | |Update | | | | 643 -------->|Control| private |Stream | 2a. data update |Client| -- 644 |Server |<------->|Server | messages | | 645 -------- | | | | --------------> | | <- 646 | response | | | | --------------> | | | 647 | | | | | 2b.control update| | | 648 | +-------+ +-------+ messages +------+ | 649 | | 650 ------------------------------------------------------------------ 652 Figure 2: ALTO SSE Architecture and Message Flow. 654 4.1. Update Stream Service Message Flow 656 The building block of the update mechanism defined in this document 657 is the update stream service (defined in Section 6), where each 658 update stream service is a POST-mode service that provides update 659 streams. 661 Note that the lines of the format "** ... **" are used to describe 662 message flows in this section and the following sections. 664 ** Initial request: client -> update server **: 666 When an ALTO client requests an update stream service, the ALTO 667 client establishes a persistent connection to the update stream 668 server and submits an initial update-stream request (defined in 669 Section 6.5), creating an update stream. This initial request 670 creating the update stream is labeled "1. init request" in Figure 2. 672 An update stream can provide updates to both GET-mode resources, such 673 as ALTO network and cost maps, and POST-mode resources, such as ALTO 674 endpoint property service. Also, to avoid creating too many update 675 streams, this design allows an ALTO client to use one update stream 676 to receive updates to multiple requests. In particular, the client 677 may request to receive updates for the same resource but with 678 different parameters for a POST-mode resource, in addition to being 679 able to consolidate updates for multiple resources into a single 680 stream. The updates for each request is called a substream, and 681 hence, the update server needs an identifier to indicate the 682 substream when sending an update. To achieve this goal, the client 683 assigns a unique substream-id when requesting updates to a resource 684 in an update stream, and the server puts the substream-id in each 685 update. 687 ** Data updates: update server -> client **: 689 The objective of an update stream is to continuously push to an ALTO 690 client data value changes to a set of resources, where the set of 691 resources is specified by the ALTO client's requests. This document 692 refers to messages sending such data-value changes as data update 693 messages (defined in Section 5.2). Although an update stream may 694 update one or more requests, each data update message updates only 695 one request and is sent as a Server-Sent Event (SSE), as defined by 696 [SSE]. A data update message is encoded either as a full replacement 697 or as an incremental change. A full replacement uses the JSON 698 message format defined by the ALTO protocol. There can be multiple 699 encodings for incremental changes. The current design supports 700 incremental changes using JSON merge patch ([RFC7396]) or JSON patch 701 ([RFC6902]) to describe the changes of the resource. Future 702 documents may define additional mechanisms for incremental changes. 703 The update stream server decides when to send data update messages, 704 and whether to send full replacements or incremental changes. These 705 decisions can vary from resource to resource and from update to 706 update. Since the transport is a HTTP/1.x compatible design, data 707 update messages are delivered reliably and in order, and the 708 lossless, sequential delivery of its messages allows the server to 709 know the exact state of the client to compute the correct incremental 710 updates. Figure 2 shows examples of data update messages (labeled 711 "2a. data update messages")in the overall message flow. 713 ** Control updates: update server -> client **: 715 An update stream can run for a long time, and hence there can be 716 status changes at the update stream server side during the lifetime 717 of an update stream; for example, the update stream server may 718 encounter an error or need to shut down for maintenance. To support 719 robust, flexible protocol design, this document allows the update 720 stream server to send control update messages (defined in 721 Section 5.3) in addition to data update messages to the ALTO client. 722 Figure 2 shows that both data updates and control updates can be sent 723 by the server to the client (labeled "2b. control update messages"). 725 4.2. Stream Control Service Message Flow 727 ** Stream control: client -> stream control server **: 729 In addition to control changes triggered from the update stream 730 server side, in a flexible design, an ALTO client may initiate 731 control changes as well, in particular, by adding or removing ALTO 732 resources receiving updates. An ALTO client initiates such changes 733 using the stream control service (defined in Section 7). Although 734 one may use a design that the client uses the same HTTP connection to 735 send the control requests, it requires stronger server support such 736 as HTTP pipeline. For more flexibility, this document introduces 737 stream control service. In particular, the update stream server of 738 an update stream uses the first message to provide the URI of the 739 stream control service (labeled "1': control uri" in Figure 2). 741 The ALTO client can then use the URI to ask the stream control server 742 specified in the URI to request the update stream server to (1) send 743 data update messages for additional resources, (2) stop sending data 744 update messages for previously requested resources, or (3) gracefully 745 stop and close the update stream altogether. 747 4.3. Service Announcement and Management Message Flow 749 ** Service announcements: IRD server -> client **: 751 An update server may provide any number of update stream services, 752 where each update stream may provide updates for a given subset of 753 the ALTO server's resources. An ALTO server's Information Resource 754 Directory (IRD) defines the update stream services and declares the 755 set of resources for which each update stream service provides 756 updates. The ALTO server selects the resource set for each update 757 stream service. It is recommended that if a resource depends on one 758 or more other resource(s) (indicated with the "uses" attribute 759 defined in [RFC7285]), these other resource(s) should also be part of 760 that update stream. Thus the update stream for a cost map should 761 also provide updates for the network map on which that cost map 762 depends. 764 ** Service management (server) **: 766 An ALTO client may request any number of update streams 767 simultaneously. Because each update stream consumes resources on the 768 update stream server, an update stream server may require client 769 authorization and/or authentication, limit the number of open update 770 streams, close inactive streams, or redirect an ALTO client to 771 another update stream server. 773 5. Update Messages: Data Update and Control Update Messages 775 This section defines the format of update messages sent from the 776 server to the client. It first defines the generic structure of 777 update messages (Section 5.1). It then defines the details of the 778 data update messages (Section 5.2) and the control update messages 779 (Section 5.3). These messages will be used in the next two sections 780 to define the Update Stream Service (Section 6) and the Stream 781 Control Service (Section 7). 783 5.1. Generic ALTO Update Message Structure 785 Both data update and control update messages from the server to the 786 client have the same basic structure: each message includes a data 787 field to provide data information, which is typically a JSON object; 788 and an event field preceding the data field, to specify the media 789 type indicating the encoding of the data field. 791 A data update message needs additional information to identify the 792 ALTO data (object) to which the update message applies. To be 793 generic, this document use a data-id to identify the ALTO data 794 (object) to be updated; see below. 796 Hence, the event field of ALTO update message can include two sub- 797 fields (media-type and data-id), where the two sub-fields are 798 separated by a comma (',', U+002C): 800 media-type [ ',' data-id ] 802 According to Section 4.2 of [RFC6838], the comma character is not 803 allowed in a media-type name. So there is no ambiguous when decoding 804 of the two sub-fields. 806 Note that an update message does not use the SSE "id" field. 808 5.2. ALTO Data Update Message 810 A data update message is sent when a monitored resource changes. As 811 discussed in the preceding section, the event field of a data update 812 message includes two sub-fields: 'media-type' and 'data-id'. 814 The 'media-type' sub-field depends on whether the data update is a 815 complete specification of the identified data, or an incremental 816 patch (e.g., a JSON merge patch or JSON patch), if possible, 817 describing the changes from the last version of the data. This 818 document refers to these as full replacement and incremental change, 819 respectively. The encoding of a full replacement is defined by its 820 defining document (e.g., network and cost map messages by [RFC7285]), 821 and uses the media type defined in that document. The encoding of 822 JSON merge patch is defined by [RFC7396], with the media type 823 "application/merge-patch+json"; the encoding of JSON patch is defined 824 by [RFC6902], with media type "application/json-patch+json". 826 The `data-id` sub-field identifies the ALTO data to which the data 827 update message applies. 829 First consider the case that the resource containing only a single 830 JSON object. For example, since an ALTO client can request data 831 updates for both a cost map resource (object) and its dependent 832 network map resource (object) in the same update stream, to 833 distinguish the updates, the client assigns a substream-id for each 834 resource receiving data updates. Substream-ids MUST be unique within 835 an update stream, but need not be globally unique. A substream-id is 836 encoded as a JSON string with the same format as that of the type 837 ResourceID (Section 10.2 of [RFC7285]). The type SubstreamID is used 838 in this document to indicate a string of this format. The substream- 839 id of a single JSON object is the 'data-id'. 841 As an example, assume that the ALTO client assigns substream-id "1" 842 in its request to receive updates to the network map; and substream- 843 id "2" to the cost map. Then the substream-ids are the data-ids 844 indicating which objects will be updated. Figure 3 shows some 845 examples of ALTO data update messages: 847 event: application/alto-networkmap+json,1 848 data: { ... full network map message ... } 850 event: application/alto-costmap+json,2 851 data: { ... full cost map message ... } 853 event: application/merge-patch+json,2 854 data: { ... JSON merge patch update for the cost map ... } 856 Figure 3: Examples of ALTO data update messages. 858 Next consider the case that a resource may include multiple JSON 859 objects. This document considers the case that a resource may 860 contain multiple components (parts) and they are encoded using the 861 media type "multipart/related" [RFC2387]. Each part of this 862 multipart response MUST be an HTTP message including a Content-ID 863 header and a JSON object body. Each component requiring the update 864 stream service (defined in Section 6) MUST be identified by a unique 865 Content-ID to be defined in its defining document. 867 For a resource using the media type "multipart/related", the `data- 868 id` sub-field MUST be the concatenation of the substream-id, the '.' 869 separator (U+002E) and the unique Content-ID in order. 871 5.3. ALTO Control Update Message 873 Control update messages have the media type "application/alto- 874 updatestreamcontrol+json", and the data is of type 875 UpdateStreamControlEvent: 877 object { 878 [String control-uri;] 879 [SubstreamID started<1..*>;] 880 [SubstreamID stopped<1..*>;] 881 [String description;] 882 } UpdateStreamControlEvent; 884 control-uri: the URI providing stream control for this update stream 885 (see Section 7). The server sends a control update message 886 notifying the client of the control-uri. This control update 887 message notifying the control-uri will be sent once and MUST be 888 the first event in an update stream. If the URI value is NULL, 889 the update stream server does not support stream control for 890 this update stream; otherwise, the update stream server provides 891 stream control through the given URI. 893 started: a list of substream-ids of resources. It notifies the ALTO 894 client that the update stream server will start sending data 895 update messages for each resource listed. 897 stopped: a list of substream-ids of resources. It notifies the ALTO 898 client that the update stream server will no longer send data 899 update messages for the listed resources. There can be multiple 900 reasons for an update stream server to stop sending data update 901 messages for a resource, including a request from the ALTO 902 client using stream control (Section 6.7.1) or an internal 903 server event. 905 description: a non-normative, human-readable text providing an 906 explanation for the control event. When an update stream server 907 stops sending data update messages for a resource, it is 908 RECOMMENDED that the update stream server use the description 909 field to provide details. There can be multiple reasons which 910 trigger a "stopped" event; see above. The intention of this 911 field is to provide a human-readable text for the developer and/ 912 or the administrator to diagnose potential problems. 914 6. Update Stream Service 916 An update stream service returns a stream of update messages, as 917 defined in Section 5. An ALTO server's IRD (Information Resource 918 Directory) MAY define one or more update stream services, which ALTO 919 clients use to request new update stream instances. An IRD entry 920 defining an update stream service MUST define the media type, HTTP 921 method, and capabilities & uses as follows. 923 6.1. Media Type 925 The media type of an ALTO update stream service is "text/event- 926 stream", as defined by [SSE]. 928 6.2. HTTP Method 930 An ALTO update stream service is requested using the HTTP POST 931 method. 933 6.3. Capabilities 935 The capabilities are defined as an object of type 936 UpdateStreamCapabilities: 938 object { 939 IncrementalUpdateMediaTypes incremental-change-media-types; 940 Boolean support-stream-control; 941 } UpdateStreamCapabilities; 943 object-map { 944 ResourceID -> String; 945 } IncrementalUpdateMediaTypes; 947 If this update stream can provide data update messages with 948 incremental changes for a resource, the "incremental-change-media- 949 types" field has an entry for that resource-id, and the value is the 950 supported media types of the incremental change separated by commas. 951 Normally this will be "application/merge-patch+json", "application/ 952 json-patch+json", or "application/merge-patch+json,application/json- 953 patch+json", because, as described in Section 5, they are the only 954 incremental change types defined by this document. However future 955 extensions may define other types of incremental changes. 957 When choosing the media-types to encode incremental changes for a 958 resource, the update stream server MUST consider the limitations of 959 the encoding. For example, when a JSON merge patch specifies that 960 the value of a field is null, its semantics is that the field is 961 removed from the target, and hence the field is no longer defined 962 (i.e., undefined); see the MergePatch algorithm in Section 3.1.1 on 963 how null value is processed. This, however, may not be the intended 964 result for the resource, when null and undefined have different 965 semantics for the resource. In such a case, the update stream server 966 MUST choose JSON patch over JSON merge patch, if JSON patch is 967 indicated as a capability of the update stream server; If the the 968 server does not support JSON patch to handle such a case, the server 969 then need to send a full replacement. 971 The "support-stream-control" field specifies whether the given update 972 stream supports stream control. If "support-stream-control" field is 973 "true", the update stream server will use the stream control 974 specified in this document; else, the update stream server may use 975 other mechanisms to provide the same functionality as stream control. 977 6.4. Uses 979 The "uses" attribute MUST be an array with the resource-ids of every 980 resource for which this update stream can provide updates. Each 981 resource specified in the "uses" MUST support full replacement: the 982 update stream server can always send full replacement, and the ALTO 983 client MUST accept full replacement. 985 This set may be any subset of the ALTO server's resources, and may 986 include resources defined in linked IRDs. However, it is RECOMMENDED 987 that the ALTO server selects a set that is closed under the resource 988 dependency relationship. That is, if an update stream's "uses" set 989 includes resource R1, and resource R1 depends on ("uses") resource 990 R0, then the update stream's "uses" set SHOULD include R0 as well as 991 R1. For example, an update stream for a cost map SHOULD also provide 992 updates for the network map upon which that cost map depends. 994 6.5. Request: Accept Input Parameters 996 An ALTO client specifies the parameters for the new update stream by 997 sending an HTTP POST body with the media type "application/alto- 998 updatestreamparams+json". That body contains a JSON Object of type 999 UpdateStreamReq, where: 1001 object { 1002 [AddUpdatesReq add;] 1003 [SubstreamID remove<0..*>;] 1004 } UpdateStreamReq; 1006 object-map { 1007 SubstreamID -> AddUpdateReq; 1008 } AddUpdatesReq; 1010 object { 1011 ResourceID resource-id; 1012 [JSONString tag;] 1013 [Boolean incremental-changes;] 1014 [Object input;] 1015 } AddUpdateReq; 1017 add: specifies the resources (and the parameters for the resources) 1018 for which the ALTO client wants updates. In the scope of the 1019 same update stream, the ALTO client MUST assign a substream-id 1020 that is unique in the scope of the update stream (Section 5.2) 1021 for each entry, and use those substream-ids as the keys in the 1022 "add" field. 1024 resource-id: the resource-id of an ALTO resource, and MUST be in the 1025 update stream's "uses" list (Section 6.4). If the resource-id 1026 is a GET-mode resource with a version tag (or "vtag"), as 1027 defined in Section 6.3 and Section 10.3 of [RFC7285], and the 1028 ALTO client has previously retrieved a version of that resource 1029 from the update stream server, the ALTO client MAY set the "tag" 1030 field to the tag part of the client's version of that resource. 1031 If that version is not current, the update stream server MUST 1032 send a full replacement before sending any incremental changes, 1033 as described in Section 6.7.1. If that version is still 1034 current, the update stream server MAY omit the initial full 1035 replacement. 1037 incremental-changes: the ALTO client specifies whether it is willing 1038 to receive incremental changes from the update stream server for 1039 this substream. If the "incremental-changes" field is "true", 1040 the update stream server MAY send incremental changes for this 1041 substream. In this case, the client MUST support all 1042 incremental methods from the set announced in the server's 1043 capabilities for this resource; see Section 6.3 for server's 1044 announcement of potential incremental methods. If a client does 1045 not support all incremental methods from the set announced in 1046 the server's capabilities, the client can set "incremental- 1047 changes" to "false", and the update stream server then MUST NOT 1048 send incremental changes for that substream. The default value 1049 for "incremental-changes" is "true", so to suppress incremental 1050 changes, the ALTO client MUST explicitly set "incremental- 1051 changes" to "false". An alternative design of incremental- 1052 changes control is a more fine-grained control, by allowing a 1053 client to select a subset of incremental methods from the set 1054 announced in the server's capabilities. But this alternative 1055 design is not adopted in this document, because it adds 1056 complexity to the server, which is more likely to be the 1057 bottleneck. Note that the ALTO client cannot suppress full 1058 replacement. When the ALTO client sets "incremental-changes" to 1059 "false", the update stream server MUST send a full replacement 1060 instead of an incremental change to the ALTO client. The update 1061 stream server MAY wait until more changes are available, and 1062 send a single full replacement with those changes. Thus an ALTO 1063 client which declines to accept incremental changes may not get 1064 updates as quickly as an ALTO client which does. 1066 input: If the resource is a POST-mode service which requires input, 1067 the ALTO client MUST set the "input" field to a JSON Object with 1068 the parameters that the resource expects. 1070 remove: it is used in update stream control requests (Section 7), 1071 and is not allowed in the update stream request. The update 1072 stream server SHOULD ignore this field if it is included in the 1073 request. 1075 If a request has any errors, the update stream server MUST NOT create 1076 an update stream. Also, the update stream server will send an error 1077 response to the ALTO client as specified in Section 6.6. 1079 6.6. Response 1081 If the update stream request has any errors, the update stream server 1082 MUST return an HTTP "400 Bad Request" to the ALTO client. The body 1083 part of the HTTP response is the JSON object defined in Section 8.5.2 1084 in [RFC7285]. Hence, an ALTO error response has the format: 1086 HTTP/1.1 400 Bad Request 1087 Content-Length: 131 1088 Content-Type: application/alto-error+json 1089 Connection: Closed 1091 { 1092 "meta":{ 1093 "code": "E_INVALID_FIELD_VALUE", 1094 "field": "add/my-network-map/resource-id", 1095 "value": "my-networkmap/#" 1096 } 1097 } 1099 Note that "field" and "value" are optional fields. If the "value" 1100 field exists, the "field" field MUST exist. 1102 o If an update stream request does not have an "add" field 1103 specifying one or more resources, the error code of the error 1104 message MUST be E_MISSING_FIELD and the "field" field SHOULD be 1105 "add". The update stream server MUST close the stream without 1106 sending any events. 1108 o If the "resource-id" field is invalid, or is not associated with 1109 the update stream, the error code of the error message MUST be 1110 E_INVALID_FIELD_VALUE; the "field" field SHOULD be the full path 1111 of the "resource-id" field and the "value" field SHOULD be the 1112 invalid resource-id. If there are more than one invalid resource- 1113 ids, the update stream server SHOULD pick one and return it. The 1114 update stream server MUST close the stream (i.e., TCP connection) 1115 without sending any events. 1117 o If the resource is a POST-mode service which requires input, the 1118 client MUST set the "input" field to a JSON Object with the 1119 parameters that that resource expects. If the "input" field is 1120 missing or invalid, the update stream server MUST return the same 1121 error response that that resource would return for missing or 1122 invalid input (see [RFC7285]). In this case, the update stream 1123 server MUST close the update stream without sending any events. 1124 If the input for several POST-mode resources are missing or 1125 invalid, the update stream server MUST pick one and return it. 1127 The response to a valid request is a stream of update messages. 1128 Section 5 defines the update messages, and [SSE] defines how they are 1129 encoded into a stream. 1131 An update stream server SHOULD send updates only when the underlying 1132 values change. However, it may be difficult for an update stream 1133 server to guarantee that in all circumstances. Therefore a client 1134 MUST NOT assume that an update message represents an actual change. 1136 6.7. Additional Requirements on Update Stream Service 1138 6.7.1. Event Sequence Requirements 1140 o The first event MUST be a control update message with the URI of 1141 the update stream control service (see Section 7) for this update 1142 stream. Note that the value of the control-uri can be "null", 1143 indicating that there is no control stream service. 1145 o As soon as possible after the ALTO client initiates the 1146 connection, the update stream server checks the "tag" field for 1147 each added update request. If the "tag" field is not specified in 1148 an added update request, the update stream server MUST first send 1149 a full replacement for the request. If the the "tag" field is 1150 specified, the client can accept incremental changes, and the 1151 server can compute an incremental update based on the "tag" (the 1152 server needs to ensure that for a POST resource with input, the 1153 "tag" should indicate the correct result for different inputs), 1154 the update stream server MAY omit the initial full replacement. 1156 o If this update stream provides updates for resource-ids R0 and R1, 1157 and if R1 depends on R0, then the update stream server MUST send 1158 the update for R0 before sending the related updates for R1. For 1159 example, suppose an update stream provides updates to a network 1160 map and its dependent cost maps. When the network map changes, 1161 the update stream server MUST send the network map update before 1162 sending the cost map updates. 1164 o When the ALTO client uses the stream control service to stop 1165 updates for one or more resources (Section 7), the ALTO client 1166 MUST send a stream control request. The update stream server MUST 1167 send a control update message whose "stopped" field has the 1168 substream-ids of all stopped resources. 1170 6.7.2. Cross-Stream Consistency Requirements 1172 If multiple ALTO clients create multiple update streams from the same 1173 update stream resource, and with the same update request parameters 1174 (i.e., same resource, same input), the update stream server MUST send 1175 the same updates to all of them. However, the update stream server 1176 MAY pack data items into different patch events, as long as the net 1177 result of applying those updates is the same. 1179 For example, suppose two different ALTO clients create two different 1180 update streams for the same cost map, and suppose the update stream 1181 server processes three separate cost point updates with a brief pause 1182 between each update. The server MUST send all three new cost points 1183 to both clients. But the update stream server MAY send a single 1184 patch event (with all three cost points) to one ALTO client, while 1185 sending three separate patch events (with one cost point per event) 1186 to the other ALTO client. 1188 A update stream server MAY offer several different update stream 1189 resources that provide updates to the same underlying resource (that 1190 is, a resource-id may appear in the "uses" field of more than one 1191 update stream resource). In this case, those update stream resources 1192 MUST return the same update. 1194 6.7.3. Multipart Update Requirements 1196 This design allows any valid media type for full replacement. Hence, 1197 it supports ALTO resources using multipart to contain multiple JSON 1198 objects. This realizes the push benefit, but not the incremental 1199 encoding benefit of SSE. 1201 JSON patch and merge patch provide the incremental encoding benefit 1202 but can be applied to only a single JSON object. If an update stream 1203 service supports a resource providing a multipart media type, which 1204 we refer to as a multipart resource, then the update stream service 1205 needs to handle the issue that the message of a full multipart 1206 resource can include multiple JSON objects. To address the issue, 1207 when an update stream service specifies that it supports JSON patch 1208 or merge patch incremental updates for a multipart resource, the 1209 service MUST ensure that (1) each part of a multipart message is a 1210 single JSON object, (2) each part is specified by a static content-id 1211 in the initial full message, (3) each data update event applies to 1212 only one part; and (4) each data update specifies substream- 1213 id.content-id as the `event` field of the event, to identify the part 1214 to be updated. 1216 6.8. Keep-Alive Messages 1218 In an SSE stream, any line which starts with a colon (U+003A) 1219 character is a comment, and an ALTO client MUST ignore that line 1220 ([SSE]). As recommended in [SSE], an update stream server SHOULD 1221 send a comment line (or an event) every 15 seconds to prevent ALTO 1222 clients and proxy servers from dropping the HTTP connection. Note 1223 that although TCP also provides a Keep-alive function, the interval 1224 between TCP Keep-alive messages can depend on the OS configuration 1225 and varies. The preceding recommended SSE keep-alive allows the SSE 1226 client to detect the status of the update stream server with more 1227 certainty. 1229 7. Stream Control Service 1231 A stream control service allows an ALTO client to remove resources 1232 from the set of resources that are monitored by an update stream, or 1233 add additional resources to that set. The service also allows an 1234 ALTO client to gracefully shut down an update stream. 1236 When an update stream server creates a new update stream, and if the 1237 update stream server supports stream control for the update stream, 1238 the update stream server creates a stream control service for that 1239 update stream. An ALTO client uses the stream control service to 1240 remove resources from the update stream instance, or to request 1241 updates for additional resources. An ALTO client cannot obtain the 1242 stream control service through the IRD. Instead, the first event 1243 that the update stream server sends to the ALTO client has the URI 1244 for the associated stream control service (see Section 5.3). 1246 Each stream control request is an individual HTTP request. The ALTO 1247 client MAY send multiple stream control requests to the stream 1248 control server using the same HTTP connection. 1250 7.1. URI 1252 The URI for a stream control service, by itself, MUST uniquely 1253 specify the update stream instance which it controls. The stream 1254 control server MUST NOT use other properties of an HTTP request, such 1255 as cookies or the client's IP address, to determine the update 1256 stream. Furthermore, an update stream server MUST NOT reuse a 1257 control service URI once the associated update stream has been 1258 closed. 1260 The ALTO client MUST evaluate a relative control URI reference 1261 [RFC3986] (for example, a URI reference without a host, or with a 1262 relative path) in the context of the URI used to create the update 1263 stream. The stream control service's host MAY be different from the 1264 update stream's host. 1266 It is expected that there is an internal mechanism to map a stream 1267 control URI to the unique update stream instance to be controlled. 1268 For example, the update stream service may assign a unique, internal 1269 stream id to each update stream instance. However, the exact 1270 mechanism is left to the update stream service provider. 1272 To prevent an attacker from forging a stream control URI and sending 1273 bogus requests to disrupt other update streams, the service should 1274 consider two security issues. First, if http, not https, is used, 1275 the stream control URI can be exposed to an on-path attacker. To 1276 address this issue, in a setting where the path from the server to 1277 the client can traverse such an attacker, the server SHOULD use 1278 https. Second, even without direct exposure, an off-path attacker 1279 may guess valid stream control URIs. To address this issue, the 1280 server SHOULD choose stream control URIs with enough randomness, to 1281 make guessing difficult; the server SHOULD introduce mechanisms that 1282 detect repeated guesses indicating an attack (e.g., keeping track of 1283 the number of failed stream control attempts); please see 1284 https://www.w3.org/TR/capability-urls/ . 1286 7.2. Media Type 1288 An ALTO stream control response does not have a specific media type. 1290 7.3. HTTP Method 1292 An ALTO update stream control resource is requested using the HTTP 1293 POST method. 1295 7.4. IRD Capabilities & Uses 1297 None (Stream control services do not appear in the IRD). 1299 7.5. Request: Accept Input Parameters 1301 A stream control service accepts the same input media type and input 1302 parameters as the update stream service (Section 6.5). The only 1303 difference is that a stream control service also accepts the "remove" 1304 field. 1306 If specified, the "remove" field is an array of substream-ids the 1307 ALTO client previously added to this update stream. An empty 1308 "remove" array is equivalent to a list of all currently active 1309 resources; the update stream server responds by removing all 1310 resources and closing the stream. 1312 An ALTO client MAY use the "add" field to add additional resources. 1313 The ALTO client MUST assign a unique substream-id to each additional 1314 resource. Substream-ids MUST be unique over the lifetime of this 1315 update stream: an ALTO client MUST NOT reuse a previously removed 1316 substream-id. The processing of an "add" resource is the same as 1317 discussed in Section 6.5 and Section 6.7. 1319 If a request has any errors, the update stream server MUST NOT add or 1320 remove any resources from the associated update stream. Also, the 1321 stream control server will return an error response to the client as 1322 specified in Section 7.6. 1324 7.6. Response 1326 The stream control server MUST process the "add" field before the 1327 "remove" field. If the request removes all active resources without 1328 adding any additional resources, the update stream server MUST close 1329 the update stream. Thus an update stream cannot have zero resources. 1331 If the request has any errors, the stream control server MUST return 1332 an HTTP "400 Bad Request" to the ALTO client. The body part of the 1333 HTTP response is the JSON object defined in Section 8.5.2 in 1334 [RFC7285]. An error response has the same format as specified in 1335 Section 6.6. Detailed error code and error information are specified 1336 as below. 1338 o If the "add" request does not satisfy the requirements in 1339 Section 6.5, the stream control server MUST return the ALTO error 1340 message defined in Section 6.6. 1342 o If any substream-id in the "remove" field was not added in a prior 1343 request, the error code of the error message MUST be 1344 E_INVALID_FIELD_VALUE; the "field" field SHOULD be "remove" and 1345 the "value" field SHOULD be an array of the invalid substream-ids. 1346 Thus it is illegal to "add" and "remove" the same substream-id in 1347 the same request. However, it is legal to remove a substream-id 1348 twice. To support the preceding checking, the update stream 1349 server MUST keep track of previously-used-but-now-closed 1350 substream-ids. 1352 o If any substream-id in the "add" field has been used before in 1353 this stream, the error code of the error message MUST be 1354 E_INVALID_FIELD_VALUE, the "field" field SHOULD be "add" and the 1355 "value" field SHOULD be an array of invalid substream-ids. 1357 o If the request has a non-empty "add" field and a "remove" field 1358 with an empty list of substream-ids (to replace all active 1359 resources with a new set, the client MUST explicitly enumerate the 1360 substream-ids to be removed), the error code of the error message 1361 MUST be E_INVALID_FIELD_VALUE; the "field" field SHOULD be 1362 "remove" and the "value" field SHOULD be an empty array. 1364 If the request is valid but the associated update stream has been 1365 closed then the stream control server MUST return an HTTP "404 Not 1366 Found". 1368 If the request is valid and the stream control server successfully 1369 processes the request without error, the stream control server should 1370 return either an HTTP "202 Accepted" response or an HTTP "204 No 1371 Content" response. The difference is that for the latter case, the 1372 stream control server is sure that the update stream server has also 1373 processed the request. Regardless of 202 or 204 HTTP response, the 1374 final updates of related resources will be notified by the update 1375 stream server using its control update message(s), due to the modular 1376 design. 1378 8. Examples 1380 8.1. Example: IRD Announcing Update Stream Services 1382 Below is an example IRD announcing three update stream services. The 1383 first, which is named "update-my-costs", provides updates for the 1384 network map, the "routingcost" and "hopcount" cost maps, and a 1385 filtered cost map resource. The second, which is named "update-my- 1386 prop", provides updates to the endpoint properties service. The 1387 third, which is named "update-my-pv", provides updates to a non- 1388 standard ALTO service returning a multipart response. 1390 Note that in the "update-my-costs" update stream shown in the example 1391 IRD, the update stream server uses JSON patch for network map, and it 1392 uses JSON merge patch to update the other resources. Also, the 1393 update stream will only provide full replacements for "my-simple- 1394 filtered-cost-map". 1396 Also, note that this IRD defines two filtered cost map resources. 1397 They use the same cost types, but "my-filtered-cost-map" accepts cost 1398 constraint tests, while "my-simple-filtered-cost-map" does not. To 1399 avoid the issues discussed in Section 9.3, the update stream provides 1400 updates for the second, but not the first. 1402 This IRD also announces a non-standard ALTO service, which is named 1403 "my-pv". This service accepts an extended endpoint cost request as 1404 an input and returns a multipart response including an endpoint cost 1405 resource and a property map resource. This document does not rely on 1406 any other design details of this new service. In this document, the 1407 "my-pv" service is only used to illustrate how the update stream 1408 service provides updates to an ALTO resource returning a multipart 1409 response. 1411 "my-network-map": { 1412 "uri": "https://alto.example.com/networkmap", 1413 "media-type": "application/alto-networkmap+json", 1414 }, 1415 "my-routingcost-map": { 1416 "uri": "https://alto.example.com/costmap/routingcost", 1417 "media-type": "application/alto-costmap+json", 1418 "uses": ["my-networkmap"], 1419 "capabilities": { 1420 "cost-type-names": ["num-routingcost"] 1421 } 1422 }, 1423 "my-hopcount-map": { 1424 "uri": "https://alto.example.com/costmap/hopcount", 1425 "media-type": "application/alto-costmap+json", 1426 "uses": ["my-networkmap"], 1427 "capabilities": { 1428 "cost-type-names": ["num-hopcount"] 1429 } 1430 }, 1431 "my-filtered-cost-map": { 1432 "uri": "https://alto.example.com/costmap/filtered/constraints", 1433 "media-type": "application/alto-costmap+json", 1434 "accepts": "application/alto-costmapfilter+json", 1435 "uses": ["my-networkmap"], 1436 "capabilities": { 1437 "cost-type-names": ["num-routingcost", "num-hopcount"], 1438 "cost-constraints": true 1439 } 1440 }, 1441 "my-simple-filtered-cost-map": { 1442 "uri": "https://alto.example.com/costmap/filtered/simple", 1443 "media-type": "application/alto-costmap+json", 1444 "accepts": "application/alto-costmapfilter+json", 1445 "uses": ["my-networkmap"], 1446 "capabilities": { 1447 "cost-type-names": ["num-routingcost", "num-hopcount"], 1448 "cost-constraints": false 1449 } 1450 }, 1451 "my-props": { 1452 "uri": "https://alto.example.com/properties", 1453 "media-type": "application/alto-endpointprops+json", 1454 "accepts": "application/alto-endpointpropparams+json", 1455 "capabilities": { 1456 "prop-types": ["priv:ietf-bandwidth"] 1457 } 1458 }, 1459 "my-pv": { 1460 "uri": "https://alto.example.com/endpointcost/pv", 1461 "media-type": "multipart/related; 1462 type=application/alto-endpointcost+json", 1463 "accepts": "application/alto-endpointcostparams+json", 1464 "capabilities": { 1465 "cost-type-names": [ "path-vector" ], 1466 "ane-properties": [ "maxresbw", "persistent-entities" ] 1467 } 1469 }, 1470 "update-my-costs": { 1471 "uri": "https://alto.example.com/updates/costs", 1472 "media-type": "text/event-stream", 1473 "accepts": "application/alto-updatestreamparams+json", 1474 "uses": [ 1475 "my-network-map", 1476 "my-routingcost-map", 1477 "my-hopcount-map", 1478 "my-simple-filtered-cost-map" 1479 ], 1480 "capabilities": { 1481 "incremental-change-media-types": { 1482 "my-network-map": "application/json-patch+json", 1483 "my-routingcost-map": "application/merge-patch+json", 1484 "my-hopcount-map": "application/merge-patch+json" 1485 }, 1486 "support-stream-control": true 1487 } 1488 }, 1489 "update-my-props": { 1490 "uri": "https://alto.example.com/updates/properties", 1491 "media-type": "text/event-stream", 1492 "uses": [ "my-props" ], 1493 "accepts": "application/alto-updatestreamparams+json", 1494 "capabilities": { 1495 "incremental-change-media-types": { 1496 "my-props": "application/merge-patch+json" 1497 }, 1498 "support-stream-control": true 1499 } 1500 }, 1501 "update-my-pv": { 1502 "uri": "https://alto.example.com/updates/pv", 1503 "media-type": "text/event-stream", 1504 "uses": [ "my-pv" ], 1505 "accepts": "application/alto-updatestreamparams+json", 1506 "capabilities": { 1507 "incremental-change-media-types": { 1508 "my-pv": "application/merge-patch+json" 1509 }, 1510 "support-stream-control": true 1511 } 1512 } 1514 8.2. Example: Simple Network and Cost Map Updates 1516 Given the update streams announced in the preceding example IRD, the 1517 section below shows an example of an ALTO client's request and the 1518 update stream server's immediate response, using the update stream 1519 resource "update-my-costs". In the example, the ALTO client requests 1520 updates for the network map and "routingcost" cost map, but not for 1521 the "hopcount" cost map. The ALTO client uses the ALTO server's 1522 resource-ids as the substream-ids. Because the client does not 1523 provide a "tag" for the network map, the update stream server must 1524 send a full replacement for the network map as well as for the cost 1525 map. The ALTO client does not set "incremental-changes" to "false", 1526 so it defaults to "true". Thus, the update stream server will send 1527 patch updates for the cost map and the network map. 1529 POST /updates/costs HTTP/1.1 1530 Host: alto.example.com 1531 Accept: text/event-stream,application/alto-error+json 1532 Content-Type: application/alto-updatestreamparams+json 1533 Content-Length: 155 1535 { "add": { 1536 "my-network-map": { 1537 "resource-id": "my-network-map" 1538 }, 1539 "my-routingcost-map": { 1540 "resource-id": "my-routingcost-map" 1541 } 1542 } 1543 } 1545 HTTP/1.1 200 OK 1546 Connection: keep-alive 1547 Content-Type: text/event-stream 1549 event: application/alto-updatestreamcontrol+json 1550 data: {"control-uri": 1551 data: "https://alto.example.com/updates/streams/3141592653589"} 1553 event: application/alto-networkmap+json,my-network-map 1554 data: { 1555 data: "meta" : { 1556 data: "vtag": { 1557 data: "resource-id" : "my-network-map", 1558 data: "tag" : "da65eca2eb7a10ce8b059740b0b2e3f8eb1d4785" 1559 data: } 1560 data: }, 1561 data: "network-map" : { 1562 data: "PID1" : { 1563 data: "ipv4" : [ "192.0.2.0/24", "198.51.100.0/25" ] 1564 data: }, 1565 data: "PID2" : { 1566 data: "ipv4" : [ "198.51.100.128/25" ] 1567 data: }, 1568 data: "PID3" : { 1569 data: "ipv4" : [ "0.0.0.0/0" ], 1570 data: "ipv6" : [ "::/0" ] 1571 data: } 1572 data: } 1573 data: } 1574 data: } 1576 event: application/alto-costmap+json,my-routingcost-map 1577 data: { 1578 data: "meta" : { 1579 data: "dependent-vtags" : [{ 1580 data: "resource-id": "my-network-map", 1581 data: "tag": "da65eca2eb7a10ce8b059740b0b2e3f8eb1d4785" 1582 data: }], 1583 data: "cost-type" : { 1584 data: "cost-mode" : "numerical", 1585 data: "cost-metric": "routingcost" 1586 data: }, 1587 data: "vtag": { 1588 data: "resource-id" : "my-routingcost-map", 1589 data: "tag" : "3ee2cb7e8d63d9fab71b9b34cbf764436315542e" 1590 data: } 1591 data: }, 1592 data: "cost-map" : { 1593 data: "PID1": { "PID1": 1, "PID2": 5, "PID3": 10 }, 1594 data: "PID2": { "PID1": 5, "PID2": 1, "PID3": 15 }, 1595 data: "PID3": { "PID1": 20, "PID2": 15 } 1596 data: } 1597 data: } 1599 After sending those events immediately, the update stream server will 1600 send additional events as the maps change. For example, the 1601 following represents a small change to the cost map. PID1->PID2 is 1602 changed to 9 from 5, PID3->PID1 is no longer available and PID3->PID3 1603 is now defined as 1: 1605 event: application/merge-patch+json,my-routingcost-map 1606 data: { 1607 data: "meta" : { 1608 data: "vtag": { 1609 data: "tag": "c0ce023b8678a7b9ec00324673b98e54656d1f6d" 1610 data: } 1611 data: }, 1612 data: "cost-map": { 1613 data: "PID1" : { "PID2" : 9 }, 1614 data: "PID3" : { "PID1" : null, "PID3" : 1 } 1615 data: } 1616 data: } 1618 As another example, the following represents a change to the network 1619 map: an ipv4 prefix "203.0.113.0/25" is added to PID1. It triggers 1620 changes to the cost map. The update stream server chooses to send an 1621 incremental change for the network map and send a full replacement 1622 instead of an incremental change for the cost map: 1624 event: application/json-patch+json,my-network-map 1625 data: { 1626 data: { 1627 data: "op": "replace", 1628 data: "path": "/meta/vtag/tag", 1629 data: "value" :"a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 1630 data: }, 1631 data: { 1632 data: "op": "add", 1633 data: "path": "/network-map/PID1/ipv4/2", 1634 data: "value": "203.0.113.0/25" 1635 data: } 1636 data: } 1638 event: application/alto-costmap+json,my-routingcost-map 1639 data: { 1640 data: "meta" : { 1641 data: "vtag": { 1642 data: "tag": "c0ce023b8678a7b9ec00324673b98e54656d1f6d" 1643 data: } 1644 data: }, 1645 data: "cost-map" : { 1646 data: "PID1": { "PID1": 1, "PID2": 3, "PID3": 7 }, 1647 data: "PID2": { "PID1": 12, "PID2": 1, "PID3": 9 }, 1648 data: "PID3": { "PID1": 14, "PID2": 8 } 1649 data: } 1650 data: } 1652 8.3. Example: Advanced Network and Cost Map Updates 1654 This example is similar to the previous one, except that the ALTO 1655 client requests updates for the "hopcount" cost map as well as the 1656 "routingcost" cost map and provides the current version tag of the 1657 network map, so the update stream server is not required to send the 1658 full network map data update message at the beginning of the stream. 1659 In this example, the client uses the substream-ids "net", "routing" 1660 and "hops" for those resources. The update stream server sends the 1661 stream control URI and the full cost maps, followed by updates for 1662 the network map and cost maps as they become available: 1664 POST /updates/costs HTTP/1.1 1665 Host: alto.example.com 1666 Accept: text/event-stream,application/alto-error+json 1667 Content-Type: application/alto-updatestreamparams+json 1668 Content-Length: 244 1670 { "add": { 1671 "net": { 1672 "resource-id": "my-network-map", 1673 "tag": "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 1674 }, 1675 "routing": { 1676 "resource-id": "my-routingcost-map" 1677 }, 1678 "hops": { 1679 "resource-id": "my-hopcount-map" 1680 } 1681 } 1682 } 1683 HTTP/1.1 200 OK 1684 Connection: keep-alive 1685 Content-Type: text/event-stream 1687 event: application/alto-updatestreamcontrol+json 1688 data: {"control-uri": 1689 data: "https://alto.example.com/updates/streams/2718281828459"} 1691 event: application/alto-costmap+json,routing 1692 data: { ... full routingcost cost map message ... } 1694 event: application/alto-costmap+json,hops 1695 data: { ... full hopcount cost map message ... } 1697 (pause) 1699 event: application/merge-patch+json,routing 1700 data: {"cost-map": {"PID2" : {"PID3" : 31}}} 1702 event: application/merge-patch+json,hops 1703 data: {"cost-map": {"PID2" : {"PID3" : 4}}} 1705 If the ALTO client wishes to stop receiving updates for the 1706 "hopcount" cost map, the ALTO client can send a "remove" request on 1707 the stream control URI: 1709 POST /updates/streams/2718281828459 HTTP/1.1 1710 Host: alto.example.com 1711 Accept: text/plain,application/alto-error+json 1712 Content-Type: application/alto-updatestreamparams+json 1713 Content-Length: 24 1715 { 1716 "remove": [ "hops" ] 1717 } 1719 HTTP/1.1 204 No Content 1720 Content-Length: 0 1722 (stream closed without sending data content) 1724 The update stream server sends a "stopped" control update message on 1725 the original request stream to inform the ALTO client that updates 1726 are stopped for that resource: 1728 event: application/alto-updatestreamcontrol+json 1729 data: { 1730 data: "stopped": ["hops"] 1731 data: } 1733 Below is an example of an invalid stream control request. The 1734 "remove" field of the request includes an undefined substream-id and 1735 the stream control server will return an error response to the ALTO 1736 client. 1738 POST /updates/streams/2718281828459 HTTP/1.1 1739 Host: alto.example.com 1740 Accept: text/plain,application/alto-error+json 1741 Content-Type: application/alto-updatestreamparams+json 1742 Content-Length: 31 1743 { 1744 "remove": [ "properties" ] 1745 } 1747 HTTP/1.1 400 Bad Request 1748 Content-Length: 89 1749 Content-Type: application/alto-error+json 1751 { 1752 "meta":{ 1753 "code": "E_INVALID_FIELD_VALUE", 1754 "field": "remove", 1755 "value": "properties" 1756 } 1758 If the ALTO client no longer needs any updates, and wishes to shut 1759 the update stream down gracefully, the client can send a "remove" 1760 request with an empty array: 1762 POST /updates/streams/2718281828459 HTTP/1.1 1763 Host: alto.example.com 1764 Accept: text/plain,application/alto-error+json 1765 Content-Type: application/alto-updatestreamparams+json 1766 Content-Length: 17 1768 { 1769 "remove": [ ] 1770 } 1772 HTTP/1.1 204 No Content 1773 Content-Length: 0 1775 (stream closed without sending data content) 1777 The update stream server sends a final control update message on the 1778 original request stream to inform the ALTO client that all updates 1779 are stopped and then closes the stream: 1781 event: application/alto-updatestreamcontrol+json 1782 data: { 1783 data: "stopped": ["net", "routing"] 1784 data: } 1786 (server closes stream) 1788 8.4. Example: Endpoint Property Updates 1790 As another example, here is how an ALTO client can request updates 1791 for the property "priv:ietf-bandwidth" for one set of endpoints and 1792 "priv:ietf-load" for another. The update stream server immediately 1793 sends full replacements with the property values for all endpoints. 1794 After that, the update stream server sends data update messages for 1795 the individual endpoints as their property values change. 1797 POST /updates/properties HTTP/1.1 1798 Host: alto.example.com 1799 Accept: text/event-stream 1800 Content-Type: application/alto-updatestreamparams+json 1801 Content-Length: 511 1803 { "add": { 1804 "props-1": { 1805 "resource-id": "my-props", 1806 "input": { 1807 "properties" : [ "priv:ietf-bandwidth" ], 1808 "endpoints" : [ 1809 "ipv4:198.51.100.1", 1810 "ipv4:198.51.100.2", 1811 "ipv4:198.51.100.3" 1812 ] 1813 } 1814 }, 1815 "props-2": { 1816 "resource-id": "my-props", 1817 "input": { 1818 "properties" : [ "priv:ietf-load" ], 1819 "endpoints" : [ 1820 "ipv6:2001:db8:100::1", 1821 "ipv6:2001:db8:100::2", 1822 "ipv6:2001:db8:100::3" 1823 ] 1824 } 1825 } 1826 } 1827 } 1828 HTTP/1.1 200 OK 1829 Connection: keep-alive 1830 Content-Type: text/event-stream 1832 event: application/alto-updatestreamcontrol+json 1833 data: {"control-uri": 1834 data: "https://alto.example.com/updates/streams/1414213562373"} 1836 event: application/alto-endpointprops+json,props-1 1837 data: { "endpoint-properties": { 1838 data: "ipv4:198.51.100.1" : { "priv:ietf-bandwidth": "13" }, 1839 data: "ipv4:198.51.100.2" : { "priv:ietf-bandwidth": "42" }, 1840 data: "ipv4:198.51.100.3" : { "priv:ietf-bandwidth": "27" } 1841 data: } } 1843 event: application/alto-endpointprops+json,props-2 1844 data: { "endpoint-properties": { 1845 data: "ipv6:2001:db8:100::1" : { "priv:ietf-load": "8" }, 1846 data: "ipv6:2001:db8:100::2" : { "priv:ietf-load": "2" }, 1847 data: "ipv6:2001:db8:100::3" : { "priv:ietf-load": "9" } 1848 data: } } 1850 (pause) 1852 event: application/merge-patch+json,props-1 1853 data: { "endpoint-properties": 1854 data: {"ipv4:198.51.100.1" : {"priv:ietf-bandwidth": "3"}} 1855 data: } 1857 (pause) 1859 event: application/merge-patch+json,props-2 1860 data: { "endpoint-properties": 1861 data: {"ipv6:2001:db8:100::3" : {"priv:ietf-load": "7"}} 1862 data: } 1864 If the ALTO client needs the "priv:ietf-bandwidth" property and the 1865 "priv:ietf-load" property for additional endpoints, the ALTO client 1866 can send an "add" request on the stream control URI: 1868 POST /updates/streams/1414213562373" HTTP/1.1 1869 Host: alto.example.com 1870 Accept: text/plain,application/alto-error+json 1871 Content-Type: application/alto-updatestreamparams+json 1872 Content-Length: 448 1874 { "add": { 1875 "props-3": { 1876 "resource-id": "my-props", 1877 "input": { 1878 "properties" : [ "priv:ietf-bandwidth" ], 1879 "endpoints" : [ 1880 "ipv4:198.51.100.4", 1881 "ipv4:198.51.100.5" 1882 ] 1883 } 1884 }, 1885 "props-4": { 1886 "resource-id": "my-props", 1887 "input": { 1888 "properties" : [ "priv:ietf-load" ], 1889 "endpoints" : [ 1890 "ipv6:2001:db8:100::4", 1891 "ipv6:2001:db8:100::5" 1892 ] 1893 } 1894 } 1895 } 1896 } 1898 HTTP/1.1 204 No Content 1899 Content-Length: 0 1901 (stream closed without sending data content) 1903 The update stream server sends full replacements for the two new 1904 resources, followed by incremental changes for all four requests as 1905 they arrive: 1907 event: application/alto-endpointprops+json,props-3 1908 data: { "endpoint-properties": { 1909 data: "ipv4:198.51.100.4" : { "priv:ietf-bandwidth": "25" }, 1910 data: "ipv4:198.51.100.5" : { "priv:ietf-bandwidth": "31" }, 1911 data: } } 1913 event: application/alto-endpointprops+json,props-4 1914 data: { "endpoint-properties": { 1915 data: "ipv6:2001:db8:100::4" : { "priv:ietf-load": "6" }, 1916 data: "ipv6:2001:db8:100::5" : { "priv:ietf-load": "4" }, 1917 data: } } 1919 (pause) 1921 event: application/merge-patch+json,props-3 1922 data: { "endpoint-properties": 1923 data: {"ipv4:198.51.100.5" : {"priv:ietf-bandwidth": "15"}} 1924 data: } 1926 (pause) 1928 event: application/merge-patch+json,props-2 1929 data: { "endpoint-properties": 1930 data: {"ipv6:2001:db8:100::2" : {"priv:ietf-load": "9"}} 1931 data: } 1933 (pause) 1935 event: application/merge-patch+json,props-4 1936 data: { "endpoint-properties": 1937 data: {"ipv6:2001:db8:100::4" : {"priv:ietf-load": "3"}} 1938 data: } 1940 8.5. Example: Multipart Message Updates 1942 This example shows how an ALTO client can request a non-standard ALTO 1943 service returning a multipart response. The update stream server 1944 immediately sends full replacements of the multipart response. After 1945 that, the update stream server sends data update messages for the 1946 individual parts of the response as the ALTO data (object) in each 1947 part changes. 1949 POST /updates/pv HTTP/1.1 1950 Host: alto.example.com 1951 Accept: text/event-stream 1952 Content-Type: application/alto-updatestreamparams+json 1953 Content-Length: 382 1955 { 1956 "add": { 1957 "ecspvsub1": { 1958 "resource-id": "my-pv", 1959 "input": { 1960 "cost-type": { 1961 "cost-mode": "array", 1962 "cost-metric": "ane-path" 1963 }, 1964 "endpoints": { 1965 "srcs": [ "ipv4:192.0.2.2" ], 1966 "dsts": [ "ipv4:192.0.2.89", "ipv4:203.0.113.45" ] 1967 }, 1968 "ane-properties": [ "maxresbw", "persistent-entities" ] 1969 } 1970 } 1971 } 1972 } 1973 HTTP/1.1 200 OK 1974 Connection: keep-alive 1975 Content-Type: text/event-stream 1977 event: application/alto-updatestreamcontrol+json 1978 data: {"control-uri": 1979 data: "https://alto.example.com/updates/streams/1414"} 1981 event: multipart/related;boundary=example-pv; 1982 type=application/alto-endpointcost+json,ecspvsub1 1983 data: --example-pv 1984 data: Content-ID: ecsmap 1985 data: Content-Type: application/alto-endpointcost+json 1986 data: 1987 data: { ... data (object) of an endpoint cost map ... } 1988 data: --example-pv 1989 data: Content-ID: propmap 1990 data: Content-Type: application/alto-propmap+json 1991 data: 1992 data: { ... data (object) of a property map ... } 1993 data: --example-pv-- 1995 (pause) 1997 event: application/merge-patch+json,ecspvsub1.ecsmap 1998 data: { ... merge patch for updates of ecspvsub1.ecsmap ... } 2000 event: application/merge-patch+json,ecspvsub1.propmap 2001 data: { ... merge patch for updates of ecspvsub1.propmap ... } 2003 9. Operation and Processing Considerations 2005 9.1. Considerations for Choosing Data Update Messages 2007 The update stream server should be cognizant of the effects of its 2008 update schedule, which includes both the choice of timing (i.e., 2009 when/what to trigger an update) and the choice of message format 2010 (i.e., given an update, send a full replacement or an incremental 2011 change). In particular, the update schedule can have effects on both 2012 the overhead and the freshness of information. To minimize overhead, 2013 the server may choose to batch a sequence of updates for resources 2014 that frequently change, by sending cumulative updates or a full 2015 replacement after a while. The update stream server should be 2016 cognizant that batching reduces the freshness of information. The 2017 server should also consider the effect of such delays on client 2018 behaviors (see below on client timeout on waiting for updates of 2019 dependent resources). 2021 For incremental updates, this design allows both JSON patch and JSON 2022 merge patch for incremental changes. JSON merge patch is clearly 2023 superior to JSON patch for describing incremental changes to Cost 2024 Maps, Endpoint Costs, and Endpoint Properties. For these data 2025 structures, JSON merge patch is more space-efficient, as well as 2026 simpler to apply; There is no advantage allowing a server to use JSON 2027 patch for those resources. 2029 The case is not as clear for incremental changes to network maps. 2031 First, consider small changes such as moving a prefix from one PID to 2032 another. JSON patch could encode that as a simple insertion and 2033 deletion, while JSON merge patch would have to replace the entire 2034 array of prefixes for both PIDs. On the other hand, to process a 2035 JSON patch update, the ALTO client would have to retain the indexes 2036 of the prefixes for each PID. Logically, the prefixes in a PID are 2037 an unordered set, not an array; aside from handling updates, a client 2038 has no need to retain the array indexes of the prefixes. Hence to 2039 take advantage of JSON patch for network maps, ALTO clients would 2040 have to retain additional, otherwise unnecessary, data. 2042 Second, consider more involved changes such as removing half of the 2043 prefixes from a PID. JSON merge patch would send a new array for 2044 that PID, while JSON patch would have to send a list of remove 2045 operations and delete the prefix one by one. 2047 Therefore, each update stream server may decide on its own whether to 2048 use JSON merge patch or JSON patch according to the changes in 2049 network maps. 2051 9.2. Considerations for Client Processing Data Update Messages 2053 In general, when an ALTO client receives a full replacement for a 2054 resource, the ALTO client should replace the current version with the 2055 new version. When an ALTO client receives an incremental change for 2056 a resource, the ALTO client should apply those patches to the current 2057 version of the resource. 2059 However, because resources can depend on other resources (e.g., cost 2060 maps depend on network maps), an ALTO client MUST NOT use a dependent 2061 resource if the resource on which it depends has changed. There are 2062 at least two ways an ALTO client can do that. The following 2063 paragraphs illustrate these techniques by referring to network and 2064 cost map messages, although these techniques apply to any dependent 2065 resources. 2067 Note that when a network map changes, the update stream server MUST 2068 send the network map update message before sending the updates for 2069 the dependent cost maps (see Section 6.7.1). 2071 One approach is for the ALTO client to save the network map update 2072 message in a buffer and continue to use the previous network map, and 2073 the associated cost maps, until the ALTO client receives the update 2074 messages for all dependent cost maps. The ALTO client then applies 2075 all network and cost map updates atomically. 2077 Alternatively, the ALTO client MAY update the network map 2078 immediately. In this case, the cost maps using the network map 2079 become invalid because they are inconsistent with the current network 2080 map; hence, the ALTO client MUST mark each such dependent cost map as 2081 temporarily invalid and MUST NOT use that each such cost map until 2082 the ALTO client receives a cost map update message indicating that it 2083 is based on the new network map version tag. 2085 The update stream server SHOULD send updates for dependent resources 2086 (i.e., the cost maps in the preceding example) in a timely fashion. 2087 However, if the ALTO client does not receive the expected updates, a 2088 simple recovery method is that the ALTO client closes the update 2089 stream connection, discards the dependent resources, and 2090 reestablishes the update stream. The ALTO client MAY retain the 2091 version tag of the last version of any tagged resources and give 2092 those version tags when requesting the new update stream. In this 2093 case, if a version is still current, the update stream server will 2094 not re-send that resource. 2096 Although not as efficient as possible, this recovery method is simple 2097 and reliable. 2099 9.3. Considerations for Updates to Filtered Cost Maps 2101 If an update stream provides updates to a Filtered cost map which 2102 allows constraint tests, then an ALTO client MAY request updates to a 2103 Filtered cost map request with a constraint test. In this case, when 2104 a cost changes, the update stream server MUST send an update if the 2105 new value satisfies the test. If the new value does not, whether the 2106 update stream server sends an update depends on whether the previous 2107 value satisfied the test. If it did not, the update stream server 2108 SHOULD NOT send an update to the ALTO client. But if the previous 2109 value did, then the update stream server MUST send an update with a 2110 "null" value, to inform the ALTO client that this cost no longer 2111 satisfies the criteria. 2113 An update stream server can avoid having to handle such a complicated 2114 behavior by offering update streams only for filtered cost maps which 2115 do not allow constraint tests. 2117 9.4. Considerations for Updates to Ordinal Mode Costs 2119 For an ordinal mode cost map, a change to a single cost point may 2120 require updating many other costs. As an extreme example, suppose 2121 the lowest cost changes to the highest cost. For a numerical mode 2122 cost map, only that one cost changes. But for an ordinal mode cost 2123 map, every cost might change. While this document allows an update 2124 stream server to offer incremental updates for ordinal mode cost 2125 maps, update stream server implementors should be aware that 2126 incremental updates for ordinal costs are more complicated than for 2127 numerical costs, and ALTO clients should be aware that small changes 2128 may result in large updates. 2130 An update stream server can avoid this complication by only offering 2131 full replacements for ordinal cost maps. 2133 9.5. Considerations for SSE Text Formatting and Processing 2135 SSE was designed for events that consist of relatively small amounts 2136 of line-oriented text data, and SSE clients frequently read input one 2137 line-at-a-time. However, an update stream sends a full cost map as a 2138 single events, and a cost map may involve megabytes, if not tens of 2139 megabytes, of text. This has implications that the ALTO client and 2140 the update stream server may consider. 2142 First, some SSE client libraries read all data for an event into 2143 memory, and then present it to the client as a character array. 2144 However, a client may not have enough memory to hold the entire JSON 2145 text for a large cost map. Hence an ALTO client SHOULD consider 2146 using an SSE library which presents the event data in manageable 2147 chunks, so the ALTO client can parse the cost map incrementally and 2148 store the underlying data in a more compact format. 2150 Second, an SSE client library may use a low level, generic socket 2151 read library that stores each line of an event data, just in case the 2152 higher level parser may need the line delimiters as part of the 2153 protocol formatting. A server sending a complete cost map as a 2154 single line may then generate a multi-megabyte data "line", and such 2155 a long line may then require complex memory management at the client. 2156 It is RECOMMENDED that an update stream server limit the lengths of 2157 data lines. 2159 Third, an SSE server may use a library which may put line breaks in 2160 places that would have semantic consequences for the ALTO updates; 2161 see Section 11. The update stream server implementation MUST ensure 2162 that no line breaks are introduced to change the semantics. 2164 10. Security Considerations 2166 The Security Considerations (Section 15 of [RFC7285]) of the base 2167 protocol fully apply to this extension. For example, the same 2168 authenticity and integrity considerations (Section 15.1 of [RFC7285]) 2169 still fully apply; the same considerations for the privacy of ALTO 2170 users (Section 15.4 of [RFC7285]) also still fully apply. 2172 The additional services (addition of update streams and stream 2173 control URIs) provided by this extension extend the attack surface 2174 described in Section 15.1.1 of [RFC7285]. Below we discuss the 2175 additional risks and their remedies. 2177 10.1. Update Stream Server: Denial-of-Service Attacks 2179 Allowing persistent update stream connections enables a new class of 2180 Denial-of-Service attacks. 2182 For the update stream server, an ALTO client might create an 2183 unreasonable number of update stream connections, or add an 2184 unreasonable number of substream-ids to one update stream. 2186 To avoid these attacks on the update stream server, the server SHOULD 2187 choose to limit the number of active streams and reject new requests 2188 when that threshold is reached. An update stream server SHOULD also 2189 choose to limit the number of active substream-ids on any given 2190 stream, or limit the total number of substream-ids used over the 2191 lifetime of a stream, and reject any stream control request which 2192 would exceed those limits. In these cases, the update stream server 2193 SHOULD return the HTTP status "503 Service Unavailable". 2195 It is important to note that the preceding approach are not the only 2196 possibilities. For example, it may be possible for the update stream 2197 server to use somewhat more clever logic involving IP reputation, 2198 rate-limiting, and compartmentalizing the overall threshold into 2199 smaller thresholds that apply to subsets of potential clients. 2201 While the preceding techniques prevent update stream DoS attacks from 2202 disrupting an update stream server's other services, it does make it 2203 easier for a DoS attack to disrupt the update stream service. 2204 Therefore an update stream server MAY prefer to restrict update 2205 stream services to authorized clients, as discussed in Section 15 of 2206 [RFC7285]. 2208 Alternatively, an update stream server MAY return the HTTP status 2209 "307 Temporary Redirect" to redirect the client to another ALTO 2210 server which can better handle a large number of update streams. 2212 10.2. ALTO Client: Update Overloading or Instability 2214 The availability of continuous updates can also cause overload for an 2215 ALTO client, in particular an ALTO client with limited processing 2216 capabilities. The current design does not include any flow control 2217 mechanisms for the client to reduce the update rates from the server. 2218 Under overloading, the client MAY choose to remove the information 2219 resources with high update rates. 2221 Also, under overloading, the client may no longer be able to detect 2222 whether an information is still fresh or has become stale. In such a 2223 case, the client should be careful in how it uses the information to 2224 avoid stability or efficiency issues. 2226 10.3. Stream Control: Spoofed Control Requests and Information 2227 Breakdown 2229 An outside party which can read the update stream response, or which 2230 can observe stream control requests, can obtain the control URI and 2231 use that to send a fraudulent "remove" requests, thus disabling 2232 updates for the valid ALTO client. This can be avoided by encrypting 2233 the update stream and stream control requests (see Section 15 of 2234 [RFC7285]). Also, the update stream server echoes the "remove" 2235 requests on the update stream, so the valid ALTO client can detect 2236 unauthorized requests. 2238 In general, as the architecture allows the possibility for the update 2239 stream server and the stream control server to be different entities, 2240 the additional risks should be evaluated and remedied. For example, 2241 the private communication path between the servers may be attacked, 2242 resulting in a risk of communications breakdown between them, as well 2243 as invalid or spoofed messages claiming to be on that private 2244 communications path. Proper security mechanisms, including 2245 confidentiality, authenticity, and integrity mechanisms should be 2246 considered. 2248 11. Requirements on Future ALTO Services to Use this Design 2250 Although this design is quite flexible, it has underlying 2251 requirements. 2253 The key requirements are that (1) each data update message is for a 2254 single resource; (2) an incremental change can be applied only to a 2255 resource that is a single JSON object, as both JSON merge patch and 2256 JSON patch can apply only to a single JSON object. Hence, if a 2257 future ALTO resource can contain multiple objects, then either each 2258 individual object also has a resource-id or an extension to this 2259 design is made. 2261 At the low level encoding level, new line in SSE has its own 2262 semantics. Hence, this design requires that resource encoding does 2263 not include new lines that can confuse with SSE encoding. In 2264 particular, the data update message MUST NOT include "event: " or 2265 "data: " at a new line as part of data message. 2267 If an update stream provides updates to a filtered cost map that 2268 allows constraint tests, the requirements for such services are 2269 stated in Section 9.3. 2271 12. IANA Considerations 2273 This document defines two new media-types, "application/alto- 2274 updatestreamparams+json", as described in Section 6.5, and 2275 "application/alto-updatestreamcontrol+json", as described in 2276 Section 5.3. All other media-types used in this document have 2277 already been registered, either for ALTO, JSON merge patch, or JSON 2278 patch. 2280 12.1. application/alto-updatestreamparams+json Media Type 2282 Type name: application 2284 Subtype name: alto-updatestreamparams+json 2286 Required parameters: n/a 2288 Optional parameters: n/a 2290 Encoding considerations: Encoding considerations are identical to 2291 those specified for the "application/json" media type. See 2292 [RFC8259]. 2294 Security considerations: Security considerations relating to the 2295 generation and consumption of ALTO Protocol messages are discussed 2296 in Section 10 of [RFCthis] and Section 15 of [RFC7285]. 2298 Interoperability considerations: [RFCthis] specifies format of 2299 conforming messages and the interpretation thereof. 2301 Published specification: Section 6.5 of [RFCthis]. 2303 Applications that use this media type: ALTO servers and ALTO clients 2304 either stand alone or are embedded within other applications. 2306 Fragment identifier considerations: n/a 2308 Additional information: 2310 Magic number(s): n/a 2312 File extension(s): [RFCthis] uses the mime type to refer to 2313 protocol messages and thus does not require a file extension. 2315 Macintosh file type code(s): n/a 2317 Person & email address to contact for further information: See 2318 Authors' Addresses section. 2320 Intended usage: COMMON 2322 Restrictions on usage: n/a 2324 Author: See Authors' Addresses section. 2326 Change controller: Internet Engineering Task Force 2327 (mailto:iesg@ietf.org). 2329 [RFC Editor: Please replace RFCthis with the published RFC number for 2330 this document.] 2332 12.2. application/alto-updatestreamcontrol+json Media Type 2334 Type name: application 2336 Subtype name: alto-updatestreamcontrol+json 2338 Required parameters: n/a 2340 Optional parameters: n/a 2342 Encoding considerations: Encoding considerations are identical to 2343 those specified for the "application/json" media type. See 2344 [RFC8259]. 2346 Security considerations: Security considerations relating to the 2347 generation and consumption of ALTO Protocol messages are discussed 2348 in Section 10 of [RFCthis] and Section 15 of [RFC7285]. 2350 Interoperability considerations: [RFCthis] specifies format of 2351 conforming messages and the interpretation thereof. 2353 Published specification: Section 5.3 of [RFCthis]. 2355 Applications that use this media type: ALTO servers and ALTO clients 2356 either stand alone or are embedded within other applications. 2358 Fragment identifier considerations: n/a 2360 Additional information: 2362 Magic number(s): n/a 2364 File extension(s): [RFCthis] uses the mime type to refer to 2365 protocol messages and thus does not require a file extension. 2367 Macintosh file type code(s): n/a 2369 Person & email address to contact for further information: See 2370 Authors' Addresses section. 2372 Intended usage: COMMON 2374 Restrictions on usage: n/a 2376 Author: See Authors' Addresses section. 2378 Change controller: Internet Engineering Task Force 2379 (mailto:iesg@ietf.org). 2381 [RFC Editor: Please replace RFCthis with the published RFC number for 2382 this document.] 2384 13. Contributors 2386 Section 2, Section 5.1, Section 5.2 and Section 8.5 of this document 2387 are based on contributions from Jingxuan Jensen Zhang, and he is 2388 considered an author. 2390 14. Acknowledgments 2392 Thank you to Dawn Chen (Tongji University), Shawn Lin (Tongji 2393 University) and Xiao Shi (Yale University) for their contributions to 2394 an earlier version of this document. 2396 15. Appendix: Design Decision: Not Allowing Stream Restart 2398 If an update stream is closed accidentally, when the ALTO client 2399 reconnects, the update stream server must resend the full maps. This 2400 is clearly inefficient. To avoid that inefficiency, the SSE 2401 specification allows an update stream server to assign an id to each 2402 event. When an ALTO client reconnects, the ALTO client can present 2403 the id of the last successfully received event, and the update stream 2404 server restarts with the next event. 2406 However, that mechanism adds additional complexity. The update 2407 stream server must save SSE messages in a buffer, in case ALTO 2408 clients reconnect. But that mechanism will never be perfect: if the 2409 ALTO client waits too long to reconnect, or if the ALTO client sends 2410 an invalid id, then the update stream server will have to resend the 2411 complete maps anyway. 2413 Furthermore, this is unlikely to be a problem in practice. ALTO 2414 clients who want continuous updates for large resources, such as full 2415 Network and cost maps, are likely to be things like P2P trackers. 2416 These ALTO clients will be well connected to the network; they will 2417 rarely drop connections. 2419 Mobile devices certainly can and do drop connections and will have to 2420 reconnect. But mobile devices will not need continuous updates for 2421 multi-megabyte cost maps. If mobile devices need continuous updates 2422 at all, they will need them for small queries, such as the costs from 2423 a small set of media servers from which the device can stream the 2424 currently playing movie. If the mobile device drops the connection 2425 and reestablishes the update stream, the update stream server will 2426 have to retransmit only a small amount of redundant data. 2428 In short, using event ids to avoid resending the full map adds a 2429 considerable amount of complexity to avoid a situation which is very 2430 rare. The complexity is not worth the benefit. 2432 The Update Stream service does allow the ALTO client to specify the 2433 tag of the last received version of any tagged resource, and if that 2434 is still current, the update stream server need not retransmit the 2435 full resource. Hence ALTO clients can use this to avoid 2436 retransmitting full network maps. cost maps are not tagged, so this 2437 will not work for them. Of course, the ALTO protocol could be 2438 extended by adding version tags to cost maps, which would solve the 2439 retransmission-on-reconnect problem. However, adding tags to cost 2440 maps might add a new set of complications. 2442 16. References 2444 16.1. Normative References 2446 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 2447 Requirement Levels", RFC 2119, BCP 14, March 1997. 2449 [RFC2387] Levinson, E., "The MIME Multipart/Related Content-type", 2450 RFC 2387, BCP 14, August 1998. 2452 [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform 2453 Resource Identifier (URI): Generic Syntax", STD 66, RFC 2454 3986, DOI 10.17487/RFC3986, January 2005, 2455 . 2457 [RFC6838] Freed, N., Klensin, J., and T. Hansen, "Media Type 2458 Specifications and Registration Procedures", RFC 6838, 2459 January 2013. 2461 [RFC6902] Bryan, P. and M. Nottingham, "JavaScript Object Notation 2462 (JSON) Patch", RFC 6902, April 2013. 2464 [RFC7285] Almi, R., Penno, R., Yang, Y., Kiesel, S., Previdi, S., 2465 Roome, W., Shalunov, S., and R. Woundy, "Application-Layer 2466 Traffic Optimization (ALTO) Protocol", RFC 7285, September 2467 2014. 2469 [RFC7396] Hoffman, P. and J. Snell, "JSON Merge Patch", RFC 7396, 2470 October 2014. 2472 [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2473 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, 2474 May 2017, . 2476 [RFC8259] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data 2477 Interchange Format", STD 90, RFC 8259, DOI 10.17487/ 2478 RFC8259, December 2017, . 2481 [SSE] Hickson, I., "Server-Sent Events (W3C)", W3C 2482 Recommendation 03 February 2015, February 2015. 2484 16.2. Informative References 2486 [RFC4960] Stewart, R., "Stream Control Transmission Protocol", RFC 2487 4960, September 2007. 2489 [RFC5789] Dusseault, L. and J. Snell, "PATCH Method for HTTP", RFC 2490 5789, March 2010. 2492 [RFC7230] Fielding, R. and J. Reschke, "Hypertext Transfer Protocol 2493 (HTTP/1.1): Message Syntax and Routing", RFC 7230, June 2494 2014. 2496 [RFC7231] Fielding, R. and J. Reschke, "Hypertext Transfer Protocol 2497 (HTTP/1.1): Semantics and Content", RFC 7231, June 2014. 2499 [RFC7540] Belshe, M., Peon, R., and M. Thomson, "Hypertext Transfer 2500 Protocol Version 2 (HTTP/2)", RFC 7540, May 2015. 2502 Authors' Addresses 2504 Wendy Roome 2505 Nokia Bell Labs (Retired) 2506 124 Burlington Rd 2507 Murray Hill, NJ 07974 2508 USA 2510 Phone: +1-908-464-6975 2511 Email: wendy@wdroome.com 2513 Y. Richard Yang 2514 Yale University 2515 51 Prospect St 2516 New Haven CT 2517 USA 2519 Email: yry@cs.yale.edu