idnits 2.17.1 draft-ietf-core-href-01.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 : ---------------------------------------------------------------------------- No issues found here. Miscellaneous warnings: ---------------------------------------------------------------------------- == The copyright year in the IETF Trust and authors Copyright Line does not match the current year -- The document date (November 4, 2019) is 1635 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) ** Obsolete normative reference: RFC 7049 (Obsoleted by RFC 8949) -- Obsolete informational reference (is this intentional?): RFC 7230 (Obsoleted by RFC 9110, RFC 9112) Summary: 1 error (**), 0 flaws (~~), 1 warning (==), 2 comments (--). Run idnits with the --verbose option for more detailed information about the items above. -------------------------------------------------------------------------------- 2 CoRE Working Group K. Hartke 3 Internet-Draft Ericsson 4 Intended status: Standards Track November 4, 2019 5 Expires: May 7, 2020 7 Constrained Resource Identifiers 8 draft-ietf-core-href-01 10 Abstract 12 Constrained Resource Identifiers (CoRIs) are an alternate 13 serialization of Uniform Resource Identifiers (URIs) that encodes the 14 URI components in Concise Binary Object Representation (CBOR) instead 15 of a string of characters. This simplifies parsing, reference 16 resolution, and comparison of URIs in environments with severe 17 limitations on processing power, code size, and memory size. 19 Status of This Memo 21 This Internet-Draft is submitted in full conformance with the 22 provisions of BCP 78 and BCP 79. 24 Internet-Drafts are working documents of the Internet Engineering 25 Task Force (IETF). Note that other groups may also distribute 26 working documents as Internet-Drafts. The list of current Internet- 27 Drafts is at https://datatracker.ietf.org/drafts/current/. 29 Internet-Drafts are draft documents valid for a maximum of six months 30 and may be updated, replaced, or obsoleted by other documents at any 31 time. It is inappropriate to use Internet-Drafts as reference 32 material or to cite them other than as "work in progress." 34 This Internet-Draft will expire on May 7, 2020. 36 Copyright Notice 38 Copyright (c) 2019 IETF Trust and the persons identified as the 39 document authors. All rights reserved. 41 This document is subject to BCP 78 and the IETF Trust's Legal 42 Provisions Relating to IETF Documents 43 (https://trustee.ietf.org/license-info) in effect on the date of 44 publication of this document. Please review these documents 45 carefully, as they describe your rights and restrictions with respect 46 to this document. Code Components extracted from this document must 47 include Simplified BSD License text as described in Section 4.e of 48 the Trust Legal Provisions and are provided without warranty as 49 described in the Simplified BSD License. 51 Table of Contents 53 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 2 54 1.1. Notational Conventions . . . . . . . . . . . . . . . . . 3 55 2. Data Model . . . . . . . . . . . . . . . . . . . . . . . . . 3 56 2.1. Options . . . . . . . . . . . . . . . . . . . . . . . . . 3 57 2.2. Option Sequences . . . . . . . . . . . . . . . . . . . . 4 58 3. CBOR . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 59 4. Python . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 60 4.1. Reference Resolution . . . . . . . . . . . . . . . . . . 9 61 4.2. URI Recomposition . . . . . . . . . . . . . . . . . . . . 10 62 4.3. CoAP Encoding . . . . . . . . . . . . . . . . . . . . . . 12 63 5. Security Considerations . . . . . . . . . . . . . . . . . . . 14 64 6. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 14 65 7. References . . . . . . . . . . . . . . . . . . . . . . . . . 14 66 7.1. Normative References . . . . . . . . . . . . . . . . . . 14 67 7.2. Informative References . . . . . . . . . . . . . . . . . 15 68 Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . 15 69 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 15 71 1. Introduction 73 Uniform Resource Identifier (URI) references [RFC3986] are the 74 standard way to link to resources in hypertext formats such as HTML 75 [W3C.REC-html52-20171214] or the HTTP "Link" header field [RFC8288]. 76 A URI reference is either a URI or a relative reference that must be 77 resolved against a base URI. 79 URI references are strings of characters chosen from the repertoire 80 of US-ASCII characters. The individual components of a URI reference 81 are delimited by a number of reserved characters, which necessitates 82 the use of percent-encoding when these reserved characters are used 83 in a non-delimiting function. One component can also contain special 84 dot-segments that affect how the component is to be interpreted. The 85 resolution of URI references involves parsing the character string 86 into its components, combining those components with the components 87 of a base URI, merging path components, removing dot-segments, and 88 recomposing the result back into a character string. 90 Overall, the proper processing of URIs is quite complicated. This 91 can be a problem in particular in constrained environments [RFC7228], 92 where devices often have severe code size limitations. As a result, 93 many implementations in these environments choose to support only an 94 ad-hoc, informally-specified, bug-ridden, non-interoperable subset of 95 half of the URI standard. 97 This document introduces Constrained Resource Identifier (CoRI) 98 references, an alternate serialization of URI references that encodes 99 the URI components in Concise Binary Object Representation (CBOR) 100 [RFC7049] instead of a string of characters. Assuming an 101 implementation of CBOR is already present on a device, typical 102 operations on URI references such as parsing, reference resolution, 103 and comparison can be implemented more easily than for character 104 strings. A full implementation that covers all corner cases is 105 intended to be implementable in a relatively small amount of code. 107 As a result of the simplification, CoRI references are not capable of 108 expressing all URI references permitted by the syntax of RFC 3986. 109 (Hence the "constrained" in "Constrained Resource Identifiers".) The 110 supported subset includes all Constrained Application Protocol (CoAP) 111 URIs [RFC7252], most Hypertext Transfer Protocol (HTTP) URIs 112 [RFC7230], and many other URIs that function as resource locators. 114 1.1. Notational Conventions 116 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 117 "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and 118 "OPTIONAL" in this document are to be interpreted as described in BCP 119 14 [RFC2119] [RFC8174] when, and only when, they appear in all 120 capitals, as shown here. 122 Terms defined in this document appear in _cursive_ where they are 123 introduced. 125 2. Data Model 127 The data model for CoRI references is very similar to the 128 serialization of the request URI in CoAP messages [RFC7252]: The 129 components of a URI reference are encoded as a sequence of _options_, 130 where each path segment and query parameter becomes its own option. 131 Every option consists of an _option number_ identifying the type of 132 option (scheme, host name, path segment, etc.) and an _option value_. 134 2.1. Options 136 The following types of options are defined: 138 scheme 139 Specifies the URI scheme. The option value can be any Unicode 140 string matching the "scheme" rule described in Section 3.1 of RFC 141 3986 [RFC3986]. 143 host.name 144 Specifies the host of the URI authority as a registered name. The 145 option value can be any Unicode string matching the specifications 146 of the URI scheme. 148 host.ip 149 Specifies the host of the URI authority as an IPv4 address or an 150 IPv6 address. The option value is a byte string with a length of 151 either 4 or 16 bytes, respectively. 153 port 154 Specifies the port number of the URI authority. The option value 155 is an integer in the range from 0 to 65535. 157 path.type 158 Specifies the type of the URI path for reference resolution. The 159 option value is an integer in the range from 0 to 127, named as 160 follows: 162 0 - absolute-path 163 1 - append-relation 164 2 - append-path 165 3 - relative-path 166 4 - relative-path-1up 167 5 - relative-path-2up 168 6 - relative-path-3up 169 7 - relative-path-4up 170 ... 172 path 173 Specifies one segment of the URI path. The option value can be 174 any Unicode string with the exception of "." and "..". This 175 option can occur more than once. 177 query 178 Specifies one argument of the URI query. The option value can be 179 any Unicode string. This option can occur more than once. 181 fragment 182 Specifies the fragment identifier. The option value can be any 183 Unicode string. 185 No percent-encoding is performed in option values. 187 2.2. Option Sequences 188 _ host.name _ 189 ____ scheme __/ \___ port _ 190 \ \________/ \__ host.ip __/ / \ 191 \__________________________/ ________/ 192 \ / ________ _________ 193 \ / / \ / \ 194 \__________ path.type __\_\_ path _/__\_ query _/__ fragment __ 195 \___________/ \________/ \_________/ \__________/ 197 Figure 1: Structure of a Well-Formed Sequence of Options 199 A sequence of options is considered _well-formed_ if: 201 o the sequence of options is empty or starts with a "scheme", 202 "host.name", "host.ip", "port", "path.type", "path", "query", or 203 "fragment" option; 205 o any "scheme" option is followed by either a "host.name" or a 206 "host.ip" option; 208 o any "host.name" option is followed by a "port" option; 210 o any "host.ip" option is followed by a "port" option; 212 o any "port" option is followed by a "path", "query", or "fragment" 213 option or is at the end of the sequence; 215 o any "path.type" option is followed by a "path", "query", or 216 "fragment" option or is at the end of the sequence; 218 o any "path" option is followed by a "path", "query", or "fragment" 219 option or is at the end of the sequence; 221 o any "query" option is followed by a "query" or "fragment" option 222 or is at the end of the sequence; and 224 o any "fragment" option is at the end of the sequence. 226 A well-formed sequence of options is considered _absolute_ if the 227 sequence of options starts with a "scheme" option. 229 A well-formed sequence of options is considered _relative_ if the 230 sequence of options is empty or starts with an option other than a 231 "scheme" option. 233 An absolute sequence of options is considered _normalized_ if the 234 result of resolving the sequence of options against any base is equal 235 to the input. (It doesn't matter what base it is resolved against, 236 since it is already absolute.) 238 The following operations can be performed on a sequence of options: 240 resolve(href, base) 241 Resolves a well-formed sequence of options `href` against an 242 absolute sequence of options `base`. This operation MUST be 243 performed by applying any algorithm that is functionally 244 equivalent to the reference implementation in Section 4.1 of this 245 document. 247 relative(href, base) 248 Makes an absolute sequence of options `href` relative to an 249 absolute sequence of options `base`. This operation MUST be 250 performed by applying any algorithm that returns a sequence of 251 options such that `resolve(relative(h, b), b)` is equal to `h` 252 given the same `b`. 254 recompose(href) 255 Recomposes a URI from an absolute sequence of options `href`. This 256 operation MUST be performed by applying any algorithm that is 257 functionally equivalent to the reference implementation in 258 Section 4.2 of this document. 260 To reduce variability, it is RECOMMENDED to uppercase the letters 261 in the hexadecimal notation when percent-encoding octets [RFC3986] 262 and to follow the recommendations of Section 4 of RFC 5952 for the 263 text representation of IPv6 addresses [RFC5952]. 265 decompose(str) 266 Decomposes a URI `str` into a sequence of options. This operation 267 MUST be performed by applying any algorithm that returns a 268 sequence of options such that `recompose(decompose(x))` is 269 equivalent to `x`. 271 coap(href) 272 Constructs CoAP options from an absolute, normalized sequence of 273 options. This operation MUST be performed by recomposing the 274 sequence of options to a URI (as described above) and decomposing 275 the URI into CoAP options (as specified in Section 6.4 of RFC 276 7252). A concise implementation of this algorithm is illustrated 277 in Section 4.3 of this document. 279 3. CBOR 281 In Concise Binary Object Representation (CBOR) [RFC7049], a sequence 282 of options is encoded as an array that contains the option numbers 283 and option values in alternating order. 285 The structure can be described in the Concise Data Definition 286 Language (CDDL) [RFC8610] as follows: 288 CoRI = [?(scheme: 1, text .regexp "[A-Za-z][A-Za-z0-9+.-]*"), 289 ?(host.name: 2, text // 290 host.ip: 3, bytes .size 4 / bytes .size 16), 291 ?(port: 4, 0..65535), 292 ?(path.type: 5, 0..127), 293 *(path: 6, text), 294 *(query: 7, text), 295 ?(fragment: 8, text)] 297 Example: 299 [1, "coap", 3, h'20010DB8000000000000000000000001', 4, 5683, 6, 300 ".well-known", 6, "core"] 302 [5, 0, 6, ".well-known", 6, "core", 7, "rt=temperature-c"] 304 4. Python 306 In Python, a sequence of options is encoded as a list of tuples, 307 where each tuple contains one option number and one option value. 309 The following Python 3.6 code illustrates how to check a sequence of 310 options for being well-formed, absolute, and relative. 312 314 import enum 316 class Option(enum.IntEnum): 317 _BEGIN = 0 318 SCHEME = 1 319 HOST_NAME = 2 320 HOST_IP = 3 321 PORT = 4 322 PATH_TYPE = 5 323 PATH = 6 324 QUERY = 7 325 FRAGMENT = 8 326 _END = 9 328 class PathType(enum.IntEnum): 329 ABSOLUTE_PATH = 0 330 APPEND_RELATION = 1 331 APPEND_PATH = 2 332 RELATIVE_PATH = 3 333 RELATIVE_PATH_1UP = 4 334 RELATIVE_PATH_2UP = 5 335 RELATIVE_PATH_3UP = 6 336 RELATIVE_PATH_4UP = 7 338 _TRANSITIONS = ([Option.SCHEME, Option.HOST_NAME, Option.HOST_IP, 339 Option.PORT, Option.PATH_TYPE, Option.PATH, Option.QUERY, 340 Option.FRAGMENT, Option._END], 341 [Option.HOST_NAME, Option.HOST_IP], 342 [Option.PORT], 343 [Option.PORT], 344 [Option.PATH, Option.QUERY, Option.FRAGMENT, Option._END], 345 [Option.PATH, Option.QUERY, Option.FRAGMENT, Option._END], 346 [Option.PATH, Option.QUERY, Option.FRAGMENT, Option._END], 347 [Option.QUERY, Option.FRAGMENT, Option._END], 348 [Option._END]) 350 def is_well_formed(href): 351 previous = Option._BEGIN 352 for option, _ in href: 353 if option not in _TRANSITIONS[previous]: 354 return False 355 previous = option 356 if Option._END not in _TRANSITIONS[previous]: 357 return False 358 return True 360 def is_absolute(href): 361 return is_well_formed(href) and \ 362 (len(href) != 0 and href[0][0] == Option.SCHEME) 364 def is_relative(href): 365 return is_well_formed(href) and \ 366 (len(href) == 0 or href[0][0] != Option.SCHEME) 368 370 Examples: 372 [(Option.SCHEME, "coap"), (Option.HOST_IP, b"\x20\x01\x0D\xB8\x00\ 373 x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"), (Option.PORT, 374 5683), (Option.PATH, ".well-known"), (Option.PATH, "core")] 376 [(Option.PATH_TYPE, PathType.ABSOLUTE_PATH), (Option.PATH, ".well- 377 known"), (Option.PATH, "core"), (Option.QUERY, "rt=temperature- 378 c")] 380 4.1. Reference Resolution 382 The following Python 3.6 code defines how to resolve a sequence of 383 options that might be relative to a given base. 385 387 def resolve(base, href, relation=0): 388 if not is_absolute(base) or not is_well_formed(href): 389 return None 390 result = [] 391 option = Option.FRAGMENT 392 if len(href) != 0: 393 option = href[0][0] 394 if option == Option.HOST_IP: 395 option = Option.HOST_NAME 396 elif option == Option.PATH_TYPE: 397 type = href[0][1] 398 href = href[1:] 399 elif option == Option.PATH: 400 type = PathType.RELATIVE_PATH 401 option = Option.PATH_TYPE 402 if option != Option.PATH_TYPE or type == PathType.ABSOLUTE_PATH: 403 _copy_until(base, result, option) 404 else: 405 _copy_until(base, result, Option.QUERY) 406 if type == PathType.APPEND_RELATION: 407 _append_and_normalize(result, Option.PATH, str(relation)) 408 while type > PathType.APPEND_PATH: 409 if len(result) == 0 or result[-1][0] != Option.PATH: 410 break 411 del result[-1] 412 type -= 1 413 _copy_until(href, result, Option._END) 414 _append_and_normalize(result, Option._END, None) 415 return result 417 def _copy_until(input, output, end): 418 for option, value in input: 419 if option >= end: 420 break 421 _append_and_normalize(output, option, value) 423 def _append_and_normalize(output, option, value): 425 if option > Option.PATH: 426 if len(output) >= 2 and \ 427 output[-1] == (Option.PATH, '') and ( 428 output[-2][0] < Option.PATH_TYPE or ( 429 output[-2][0] == Option.PATH_TYPE and 430 output[-2][1] == PathType.ABSOLUTE_PATH)): 431 del output[-1] 432 if option > Option.FRAGMENT: 433 return 434 output.append((option, value)) 436 438 4.2. URI Recomposition 440 The following Python 3.6 code defines how to recompose a URI from an 441 absolute sequence of options. 443 445 def recompose(href): 446 if not is_absolute(href): 447 return None 448 result = '' 449 no_path = True 450 first_query = True 451 for option, value in href: 452 if option == Option.SCHEME: 453 result += value + ':' 454 elif option == Option.HOST_NAME: 455 result += '//' + _encode_reg_name(value) 456 elif option == Option.HOST_IP: 457 result += '//' + _encode_ip_address(value) 458 elif option == Option.PORT: 459 result += ':' + _encode_port(value) 460 elif option == Option.PATH: 461 result += '/' + _encode_path_segment(value) 462 no_path = False 463 elif option == Option.QUERY: 464 if no_path: 465 result += '/' 466 no_path = False 467 result += '?' if first_query else '&' 468 result += _encode_query_argument(value) 469 first_query = False 470 elif option == Option.FRAGMENT: 471 if no_path: 472 result += '/' 473 no_path = False 474 result += '#' + _encode_fragment(value) 475 if no_path: 476 result += '/' 477 no_path = False 478 return result 480 def _encode_reg_name(s): 481 return ''.join(c if _is_reg_name_char(c) 482 else _encode_pct(c) for c in s) 484 def _encode_ip_address(b): 485 if len(b) == 4: 486 return '.'.join(str(c) for c in b) 487 elif len(b) == 16: 488 return '[' + ... + ']' # see RFC 5952 490 def _encode_port(p): 491 return str(p) 493 def _encode_path_segment(s): 494 return ''.join(c if _is_segment_char(c) 495 else _encode_pct(c) for c in s) 497 def _encode_query_argument(s): 498 return ''.join(c if _is_query_char(c) and c not in '&' 499 else _encode_pct(c) for c in s) 501 def _encode_fragment(s): 502 return ''.join(c if _is_fragment_char(c) 503 else _encode_pct(c) for c in s) 505 def _encode_pct(s): 506 return ''.join('%{0:0>2X}'.format(c) for c in s.encode('utf-8')) 508 def _is_reg_name_char(c): 509 return _is_unreserved(c) or _is_sub_delim(c) 511 def _is_segment_char(c): 512 return _is_pchar(c) 514 def _is_query_char(c): 515 return _is_pchar(c) or c in '/?' 517 def _is_fragment_char(c): 518 return _is_pchar(c) or c in '/?' 520 def _is_pchar(c): 522 return _is_unreserved(c) or _is_sub_delim(c) or c in ':@' 524 def _is_unreserved(c): 525 return _is_alpha(c) or _is_digit(c) or c in '-._~' 527 def _is_alpha(c): 528 return c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + \ 529 'abcdefghijklmnopqrstuvwxyz' 531 def _is_digit(c): 532 return c in '0123456789' 534 def _is_sub_delim(c): 535 return c in '!$&\'()*+,;=' 537 539 4.3. CoAP Encoding 541 The following Python 3.6 code illustrates how to construct CoAP 542 options from an absolute sequence of options. For simplicity, the 543 code does not omit CoAP options with their default value. 545 547 def coap(href, to_proxy=False): 548 if not is_absolute(href): 549 return None 550 result = b'' 551 previous = 0 552 for option, value in href: 553 if option == Option.SCHEME: 554 pass 555 elif option == Option.HOST_NAME: 556 opt = 3 # Uri-Host 557 val = value.encode('utf-8') 558 result += _encode_coap_option(opt - previous, val) 559 previous = opt 560 elif option == Option.HOST_IP: 561 opt = 3 # Uri-Host 562 if len(value) == 4: 563 val = '.'.join(str(c) for c in value).encode('utf-8') 564 elif len(value) == 16: 565 val = b'[' + ... + b']' # see RFC 5952 566 result += _encode_coap_option(opt - previous, val) 567 previous = opt 568 elif option == Option.PORT: 569 opt = 7 # Uri-Port 570 val = value.to_bytes((value.bit_length() + 7) // 8, 'big') 571 result += _encode_coap_option(opt - previous, val) 572 previous = opt 573 elif option == Option.PATH: 574 opt = 11 # Uri-Path 575 val = value.encode('utf-8') 576 result += _encode_coap_option(opt - previous, val) 577 previous = opt 578 elif option == Option.QUERY: 579 opt = 15 # Uri-Query 580 val = value.encode('utf-8') 581 result += _encode_coap_option(opt - previous, val) 582 previous = opt 583 elif option == Option.FRAGMENT: 584 pass 585 if to_proxy: 586 (option, value) = href[0] 587 opt = 39 # Proxy-Scheme 588 val = value.encode('utf-8') 589 result += _encode_coap_option(opt - previous, val) 590 previous = opt 591 return result 593 def _encode_coap_option(delta, value): 594 length = len(value) 595 delta_nibble = _encode_coap_option_nibble(delta) 596 length_nibble = _encode_coap_option_nibble(length) 597 result = bytes([delta_nibble << 4 | length_nibble]) 598 if delta_nibble == 13: 599 delta -= 13 600 result += bytes([delta]) 601 elif delta_nibble == 14: 602 delta -= 256 + 13 603 result += bytes([delta >> 8, delta & 255]) 604 if length_nibble == 13: 605 length -= 13 606 result += bytes([length]) 607 elif length_nibble == 14: 608 length -= 256 + 13 609 result += bytes([length >> 8, length & 255]) 610 result += value 611 return result 613 def _encode_coap_option_nibble(n): 614 if n < 13: 615 return n 616 elif n < 256 + 13: 617 return 13 619 elif n < 65536 + 256 + 13: 620 return 14 622 624 5. Security Considerations 626 Parsers must operate on input that is assumed to be untrusted. This 627 means that parsers MUST fail gracefully in the face of malicious 628 inputs. Additionally, parsers MUST be prepared to deal with resource 629 exhaustion (e.g., resulting from the allocation of big data items) or 630 exhaustion of the call stack (stack overflow). See Section 8 of RFC 631 7049 [RFC7049] for security considerations relating to CBOR. 633 The security considerations discussed in Section 7 of RFC 3986 634 [RFC3986] also apply to Constrained Resource Identifiers. 636 6. IANA Considerations 638 This document has no IANA actions. 640 7. References 642 7.1. Normative References 644 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 645 Requirement Levels", BCP 14, RFC 2119, 646 DOI 10.17487/RFC2119, March 1997, 647 . 649 [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform 650 Resource Identifier (URI): Generic Syntax", STD 66, 651 RFC 3986, DOI 10.17487/RFC3986, January 2005, 652 . 654 [RFC7049] Bormann, C. and P. Hoffman, "Concise Binary Object 655 Representation (CBOR)", RFC 7049, DOI 10.17487/RFC7049, 656 October 2013, . 658 [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 659 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, 660 May 2017, . 662 [RFC8610] Birkholz, H., Vigano, C., and C. Bormann, "Concise Data 663 Definition Language (CDDL): A Notational Convention to 664 Express Concise Binary Object Representation (CBOR) and 665 JSON Data Structures", RFC 8610, DOI 10.17487/RFC8610, 666 June 2019, . 668 7.2. Informative References 670 [RFC5952] Kawamura, S. and M. Kawashima, "A Recommendation for IPv6 671 Address Text Representation", RFC 5952, 672 DOI 10.17487/RFC5952, August 2010, 673 . 675 [RFC7228] Bormann, C., Ersue, M., and A. Keranen, "Terminology for 676 Constrained-Node Networks", RFC 7228, 677 DOI 10.17487/RFC7228, May 2014, 678 . 680 [RFC7230] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer 681 Protocol (HTTP/1.1): Message Syntax and Routing", 682 RFC 7230, DOI 10.17487/RFC7230, June 2014, 683 . 685 [RFC7252] Shelby, Z., Hartke, K., and C. Bormann, "The Constrained 686 Application Protocol (CoAP)", RFC 7252, 687 DOI 10.17487/RFC7252, June 2014, 688 . 690 [RFC8288] Nottingham, M., "Web Linking", RFC 8288, 691 DOI 10.17487/RFC8288, October 2017, 692 . 694 [W3C.REC-html52-20171214] 695 Faulkner, S., Eicholz, A., Leithead, T., Danilo, A., and 696 S. Moon, "HTML 5.2", World Wide Web Consortium 697 Recommendation REC-html52-20171214, December 2017, 698 . 700 Acknowledgements 702 Thanks to Christian Amsuess, Ari Keranen, and Dave Thaler for helpful 703 comments and discussions that have shaped the document. 705 Author's Address 707 Klaus Hartke 708 Ericsson 709 Torshamnsgatan 23 710 Stockholm SE-16483 711 Sweden 713 Email: klaus.hartke@ericsson.com