idnits 2.17.1 draft-hartke-t2trg-ciri-00.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 (October 22, 2018) is 2012 days in the past. Is this intentional? Checking references for intended status: Experimental ---------------------------------------------------------------------------- == Outdated reference: A later version (-08) exists of draft-ietf-cbor-cddl-05 ** 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 (~~), 2 warnings (==), 2 comments (--). Run idnits with the --verbose option for more detailed information about the items above. -------------------------------------------------------------------------------- 2 Thing-to-Thing Research Group K. Hartke 3 Internet-Draft Ericsson 4 Intended status: Experimental October 22, 2018 5 Expires: April 25, 2019 7 Constrained Internationalized Resource Identifiers 8 draft-hartke-t2trg-ciri-00 10 Abstract 12 This document specifies Constrained Internationalized Resource 13 Identifier References, a serialization of Internationalized Resource 14 Identifier (IRI) references that encodes the IRI components as 15 Concise Binary Object Representation (CBOR) data items rather than a 16 string of characters. This intends to simplify parsing, reference 17 resolution, and comparison of IRIs in Constrained RESTful 18 Environments (CoRE). 20 Status of This Memo 22 This Internet-Draft is submitted in full conformance with the 23 provisions of BCP 78 and BCP 79. 25 Internet-Drafts are working documents of the Internet Engineering 26 Task Force (IETF). Note that other groups may also distribute 27 working documents as Internet-Drafts. The list of current Internet- 28 Drafts is at https://datatracker.ietf.org/drafts/current/. 30 Internet-Drafts are draft documents valid for a maximum of six months 31 and may be updated, replaced, or obsoleted by other documents at any 32 time. It is inappropriate to use Internet-Drafts as reference 33 material or to cite them other than as "work in progress." 35 This Internet-Draft will expire on April 25, 2019. 37 Copyright Notice 39 Copyright (c) 2018 IETF Trust and the persons identified as the 40 document authors. All rights reserved. 42 This document is subject to BCP 78 and the IETF Trust's Legal 43 Provisions Relating to IETF Documents 44 (https://trustee.ietf.org/license-info) in effect on the date of 45 publication of this document. Please review these documents 46 carefully, as they describe your rights and restrictions with respect 47 to this document. Code Components extracted from this document must 48 include Simplified BSD License text as described in Section 4.e of 49 the Trust Legal Provisions and are provided without warranty as 50 described in the Simplified BSD License. 52 Table of Contents 54 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 2 55 1.1. Requirements Notation . . . . . . . . . . . . . . . . . . 3 56 2. Data Model . . . . . . . . . . . . . . . . . . . . . . . . . 3 57 2.1. Options . . . . . . . . . . . . . . . . . . . . . . . . . 3 58 2.2. Option Sequences . . . . . . . . . . . . . . . . . . . . 4 59 3. CBOR . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 60 4. Python . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 61 4.1. Reference Resolution . . . . . . . . . . . . . . . . . . 8 62 4.2. IRI Recomposition . . . . . . . . . . . . . . . . . . . . 9 63 4.3. CoAP Encoding . . . . . . . . . . . . . . . . . . . . . . 12 64 5. Security Considerations . . . . . . . . . . . . . . . . . . . 13 65 6. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 14 66 7. References . . . . . . . . . . . . . . . . . . . . . . . . . 14 67 7.1. Normative References . . . . . . . . . . . . . . . . . . 14 68 7.2. Informative References . . . . . . . . . . . . . . . . . 14 69 Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . 15 70 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 15 72 1. Introduction 74 URI references [RFC3986] and, albeit less prevalently, IRI references 75 [RFC3987] are the standard way to link to resources in hypertext 76 formats like HTML [W3C.REC-html52-20171214] and the CoRE Link Format 77 [RFC6690]. They encode the components of a resource reference either 78 as an absolute URI/IRI or as a relative reference that must be 79 resolved against a base URI/IRI to receive an absolute URI/IRI. 81 URI and IRI references are strings of characters where the characters 82 are chosen from a limited subset of the repertoires of US-ASCII and 83 Unicode characters, respectively. The individual components of a URI 84 or IRI reference are delimited by a number of reserved characters, 85 which necessitates the use of percent-encoding when these reserved 86 characters are used in a non-delimiting function. The resolution of 87 references involves parsing URI/IRI references into their components, 88 combining those components with the components of the base URI/IRI, 89 merging paths, removing dot segments, and recomposing the result back 90 into a character string. 92 Altogether, the proper processing of URIs is quite complex. This can 93 be a problem particularly in constrained environments [RFC7228], 94 where devices often have severe code size limitations. As a result, 95 many implementations in these environments choose to implement only 96 an ad-hoc, informally-specified, bug-ridden, non-interoperable subset 97 of less than half of RFC 3986. 99 This document specifies Constrained IRI References, a serialization 100 format for IRI references that encodes the IRI components as Concise 101 Binary Object Representation (CBOR) [RFC7049] data items rather than 102 as a string of characters. Assuming that a CBOR implementation is 103 already present on a device, typical operations on Constrained IRI 104 references such as parsing, reference resolution, and comparison can 105 be implemented much more easily than with the original format. A 106 full implementation that covers all corner cases of the specification 107 can be implemented in a relatively small amount of code. 109 As a result of the simplification, Constrained IRI References are not 110 capable of expressing all IRI references that are permitted by the 111 syntax of RFC 3987. The supported subset includes all Constrained 112 Application Protocol (CoAP) URIs [RFC7252], most Hypertext Transfer 113 Protocol (HTTP) URIs [RFC7230], and many other URIs and IRIs. 115 1.1. Requirements Notation 117 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 118 "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and 119 "OPTIONAL" in this document are to be interpreted as described in BCP 120 14 [RFC2119] [RFC8174] when, and only when, they appear in all 121 capitals, as shown here. 123 2. Data Model 125 The data model for Constrained IRI References is very similar to the 126 encoding of a request URI in CoAP messages [RFC7252]: The components 127 of an IRI reference are encoded as a sequence of _options_. Each 128 option consists of an _option number_ identifying the type of option 129 (scheme, host name, etc.) and the _option value_. 131 2.1. Options 133 The following types of options are defined: 135 scheme 136 Specifies the IRI scheme. Since IRI schemes have the same syntax 137 as URI schemes, the option value MUST match the "scheme" rule 138 defined in Section 3.1 of RFC 3986. 140 host.name 141 Specifies the host of the IRI authority as a registered name. 143 host.ip 144 Specifies the host of the IRI authority as an IPv4 address 145 (4 bytes) or an IPv6 address (16 bytes). 147 port 148 Specifies the port number. The option value MUST be an unsigned 149 integer in the range 0 to 65535 (inclusive). 151 path.type 152 Specifies the type of the IRI path for reference resolution. 153 Possible values are 0 (absolute-path), 1 (append-path), 2 154 (relative-path), and 3 (append-relation). 156 path 157 Specifies one segment of the IRI path. This option can occur more 158 than once. 160 query 161 Specifies one argument of the IRI query. This option can occur 162 more than once. 164 fragment 165 Specifies the fragment identifier. 167 The value of a "host.name", "path", "query", and "fragment" option 168 can be any Unicode string. No percent-encoding is performed. 170 2.2. Option Sequences 172 _ host.name _ 173 ____ scheme __/ \___ port _ 174 \ \________/ \__ host.ip __/ / \ 175 \__________________________/ ________/ 176 \ / ________ _________ 177 \ / / \ / \ 178 \__________ path.type __\_\_ path _/__\_ query _/__ fragment __ 179 \___________/ \________/ \_________/ \__________/ 181 Figure 1: Structure of a Well-Formed Sequence of Options 183 A sequence of options is considered _well-formed_ if: 185 o the sequence of options is empty or starts with a "scheme", 186 "host.name", "host.ip", "port", "path.type", "path", "query", or 187 "fragment" option; 189 o any "scheme" option is followed by either a "host.name" or a 190 "host.ip" option; 192 o any "host.name" option is followed by a "port" option; 194 o any "host.ip" option is followed by a "port" option; 196 o any "port" option is followed by a "path", "query", or "fragment" 197 option or is at the end of the sequence; 199 o any "path.type" option is followed by a "path", "query", or 200 "fragment" option or is at the end of the sequence; 202 o any "path" option is followed by a "path", "query", or "fragment" 203 option or is at the end of the sequence; 205 o any "query" option is followed by a "query" or "fragment" option 206 or is at the end of the sequence; and 208 o any "fragment" option is at the end of the sequence. 210 A well-formed sequence of options is considered _absolute_ if the 211 sequence of options starts with a "scheme" option. 213 A well-formed sequence of options is considered _relative_ if the 214 sequence of options is empty or starts with an option other than the 215 "scheme" option. 217 An absolute sequence of options is considered _normalized_ if the 218 result of resolving the sequence of options against any base IRI 219 reference is equal to the input. (It doesn't matter what base IRI it 220 is resolved against, since it is already absolute.) 222 The following operations can be performed on a sequence of options: 224 resolve(href, base) 225 Resolves a well-formed sequence of options `href` against an 226 absolute sequence of options `base`. This operation MUST be 227 performed by applying any algorithm that is functionally 228 equivalent to the reference implementation in Section 4.1 of this 229 document. 231 recompose(href) 232 Recomposes an IRI reference string from an absolute sequence of 233 options `href`. This operation MUST be performed by applying any 234 algorithm that is functionally equivalent to the reference 235 implementation in Section 4.2 of this document. 237 To reduce variability, it is RECOMMENDED to uppercase the letters 238 in the hexadecimal notation when percent-encoding octets [RFC3986] 239 and to follow the recommendations of Section 4 of RFC 5952 for the 240 text representation of IPv6 addresses [RFC5952]. 242 decompose(iriref) 243 Decomposes a IRI reference string into a sequence of options. 244 This operation MUST be performed by applying any algorithm that 245 returns a sequence of options such that `recompose(decompose(x))` 246 is equivalent to `x`. 248 coap(href) 249 Constructs CoAP options from an absolute, normalized sequence of 250 options. This operation MUST be performed by recomposing the 251 sequence of options to an IRI reference string as described above, 252 mapping the IRI to a URI as specified in Section 3.1 of RFC 3987, 253 and decomposing the URI into CoAP options as specified in 254 Section 6.4 of RFC 7252. A concise implementation is illustrated 255 in Section 4.3 of this document. 257 3. CBOR 259 A sequence of options is serialized as an array in Concise Binary 260 Object Representation (CBOR) [RFC7049] as follows. The structure is 261 presented in the Concise Data Definition Language (CDDL) 262 [I-D.ietf-cbor-cddl]. 264 ciri = [?(scheme: 1, text .regexp "[A-Za-z][A-Za-z0-9+.-]*"), 265 ?(host.name: 2, text // 266 host.ip: 3, bytes .size 4 / bytes .size 16), 267 ?(port: 4, uint .size 2), 268 ?(path.type: 5, path-type), 269 *(path: 6, text), 270 *(query: 7, text), 271 ?(fragment: 8, text)] 273 path-type = &(absolute-path: 0, 274 append-path: 1, 275 relative-path: 2, 276 append-relation: 3) 278 4. Python 280 The following Python 3.6 code shows how to work with a sequence of 281 options. 283 285 import enum 286 class Option(enum.IntEnum): 287 _BEGIN = 0 288 SCHEME = 1 289 HOST_NAME = 2 290 HOST_IP = 3 291 PORT = 4 292 PATH_TYPE = 5 293 PATH = 6 294 QUERY = 7 295 FRAGMENT = 8 296 _END = 9 298 class PathType(enum.IntEnum): 299 ABSOLUTE_PATH = 0 300 APPEND_PATH = 1 301 RELATIVE_PATH = 2 302 APPEND_RELATION = 3 304 _TRANSITIONS = [(Option.SCHEME, Option.HOST_NAME, Option.HOST_IP, 305 Option.PORT, Option.PATH_TYPE, Option.PATH, Option.QUERY, 306 Option.FRAGMENT, Option._END), 307 (Option.HOST_NAME, Option.HOST_IP), 308 (Option.PORT,), 309 (Option.PORT,), 310 (Option.PATH, Option.QUERY, Option.FRAGMENT, Option._END), 311 (Option.PATH, Option.QUERY, Option.FRAGMENT, Option._END), 312 (Option.PATH, Option.QUERY, Option.FRAGMENT, Option._END), 313 (Option.QUERY, Option.FRAGMENT, Option._END), 314 (Option._END,)] 316 def is_well_formed(href): 317 previous = Option._BEGIN 318 for option, _ in href: 319 if option not in _TRANSITIONS[previous]: 320 return False 321 previous = option 322 if Option._END not in _TRANSITIONS[previous]: 323 return False 324 return True 326 def is_absolute(href): 327 return is_well_formed(href) and \ 328 (len(href) != 0 and href[0][0] == Option.SCHEME) 330 def is_relative(href): 331 return is_well_formed(href) and \ 332 (len(href) == 0 or href[0][0] != Option.SCHEME) 334 336 4.1. Reference Resolution 338 The following Python 3.6 code defines how to resolve a sequence of 339 options that might be relative to a given base IRI. 341 343 def resolve(base, href, relation=0): 344 if not is_absolute(base) or not is_well_formed(href): 345 return None 346 result = [] 347 type = PathType.RELATIVE_PATH 348 option = href[0][0] if href else Option._END 349 if option == Option.HOST_IP: 350 option = Option.HOST_NAME 351 elif option == Option.PATH_TYPE: 352 type = href[0][1] 353 href = href[1:] 354 option = Option.PATH 355 if option != Option.PATH or type == PathType.ABSOLUTE_PATH: 356 _copy_until(base, result, option) 357 else: 358 _copy_until(base, result, Option.QUERY) 359 if type == PathType.APPEND_RELATION: 360 _append_and_normalize(result, Option.PATH, str(relation)) 361 elif type == PathType.RELATIVE_PATH: 362 _remove_last_path_segment(result) 363 _copy_until(href, result, Option._END) 364 _append_and_normalize(result, Option._END, None) 365 return result 367 def _copy_until(input, output, end): 368 for option, value in input: 369 if option >= end: 370 break 371 _append_and_normalize(output, option, value) 373 def _append_and_normalize(output, option, value): 374 if option == Option.PATH: 375 if value == '.': 376 return 377 if value == '..': 378 _remove_last_path_segment(output) 379 return 380 elif option > Option.PATH: 381 if len(output) >= 2 and \ 382 output[-1] == (Option.PATH, '') and ( 383 output[-2][0] < Option.PATH_TYPE or ( 384 output[-2][0] == Option.PATH_TYPE and 385 output[-2][1] == PathType.ABSOLUTE_PATH)): 386 _remove_last_path_segment(output) 387 if option > Option.FRAGMENT: 388 return 389 output.append((option, value)) 391 def _remove_last_path_segment(output): 392 if len(output) >= 1 and output[-1][0] == Option.PATH: 393 del output[-1] 395 397 4.2. IRI Recomposition 399 The following Python 3.6 code defines how to recompose an IRI from a 400 sequence of options that encodes an absolute IRI reference. 402 404 def recompose(href): 405 if not is_absolute(href): 406 return None 407 result = '' 408 no_path = True 409 first_query = True 410 for option, value in href: 411 if option == Option.SCHEME: 412 result += value + ':' 413 elif option == Option.HOST_NAME: 414 result += '//' + _encode_ireg_name(value) 415 elif option == Option.HOST_IP: 416 result += '//' + _encode_ip_address(value) 417 elif option == Option.PORT: 418 result += ':' + str(value) 419 elif option == Option.PATH: 420 result += '/' + _encode_path_segment(value) 421 no_path = False 422 elif option == Option.QUERY: 423 if no_path: 424 result += '/' 425 no_path = False 426 result += '?' if first_query else '&' 427 result += _encode_query_argument(value) 428 first_query = False 429 elif option == Option.FRAGMENT: 431 if no_path: 432 result += '/' 433 no_path = False 434 result += '#' + _encode_fragment(value) 435 if no_path: 436 result += '/' 437 no_path = False 438 return result 440 def _encode_ireg_name(s): 441 return ''.join(c if _is_ireg_name_char(c) 442 else _encode_pct(c) for c in s) 444 def _encode_ip_address(b): 445 if len(b) == 4: 446 return '.'.join(str(c) for c in b) 447 elif len(b) == 16: 448 return '[' + ... + ']' # see RFC 5952 450 def _encode_path_segment(s): 451 return ''.join(c if _is_isegment_char(c) 452 else _encode_pct(c) for c in s) 454 def _encode_query_argument(s): 455 return ''.join(c if _is_iquery_char(c) and c != '&' 456 else _encode_pct(c) for c in s) 458 def _encode_fragment(s): 459 return ''.join(c if _is_ifragment_char(c) 460 else _encode_pct(c) for c in s) 462 def _encode_pct(s): 463 return ''.join('%{0:0>2X}'.format(c) for c in s.encode('utf-8')) 465 def _is_ireg_name_char(c): 466 return _is_iunreserved(c) or _is_sub_delim(c) 468 def _is_isegment_char(c): 469 return _is_ipchar(c) 471 def _is_iquery_char(c): 472 return _is_ipchar(c) or _is_iprivate(c) or c == '/' or c == '?' 474 def _is_ifragment_char(c): 475 return _is_ipchar(c) or c == '/' or c == '?' 477 def _is_ipchar(c): 478 return _is_iunreserved(c) or _is_sub_delim(c) or \ 479 c == ':' or c == '@' 481 def _is_iunreserved(c): 482 return _is_alpha(c) or _is_digit(c) or \ 483 c == '-' or c == '.' or c == '_' or c == '~' or \ 484 _is_ucschar(c) 486 def _is_alpha(c): 487 return c >= 'A' and c <= 'Z' or c >= 'a' and c <= 'z' 489 def _is_digit(c): 490 return c >= '0' and c <= '9' 492 def _is_sub_delim(c): 493 return c == '!' or c == '$' or c == '&' or c == '\'' or \ 494 c == '(' or c == ')' or c == '*' or c == '+' or \ 495 c == ',' or c == ';' or c == '=' 497 def _is_ucschar(c): 498 return c >= '\U000000A0' and c <= '\U0000D7FF' or \ 499 c >= '\U0000F900' and c <= '\U0000FDCF' or \ 500 c >= '\U0000FDF0' and c <= '\U0000FFEF' or \ 501 c >= '\U00010000' and c <= '\U0001FFFD' or \ 502 c >= '\U00020000' and c <= '\U0002FFFD' or \ 503 c >= '\U00030000' and c <= '\U0003FFFD' or \ 504 c >= '\U00040000' and c <= '\U0004FFFD' or \ 505 c >= '\U00050000' and c <= '\U0005FFFD' or \ 506 c >= '\U00060000' and c <= '\U0006FFFD' or \ 507 c >= '\U00070000' and c <= '\U0007FFFD' or \ 508 c >= '\U00080000' and c <= '\U0008FFFD' or \ 509 c >= '\U00090000' and c <= '\U0009FFFD' or \ 510 c >= '\U000A0000' and c <= '\U000AFFFD' or \ 511 c >= '\U000B0000' and c <= '\U000BFFFD' or \ 512 c >= '\U000C0000' and c <= '\U000CFFFD' or \ 513 c >= '\U000D0000' and c <= '\U000DFFFD' or \ 514 c >= '\U000E1000' and c <= '\U000EFFFD' 516 def _is_iprivate(c): 517 return c >= '\U0000E000' and c <= '\U0000F8FF' or \ 518 c >= '\U000F0000' and c <= '\U000FFFFD' or \ 519 c >= '\U00100000' and c <= '\U0010FFFD' 521 523 4.3. CoAP Encoding 525 The following Python 3.6 code shows how to construct CoAP options 526 from an absolute sequence of options. For simplicity, the code does 527 not omit CoAP options with their default value in a CoAP request. 529 531 def coap(href, to_proxy=False): 532 if not is_absolute(href): 533 return None 534 result = b'' 535 previous = 0 536 for option, value in href: 537 if option == Option.SCHEME: 538 pass 539 elif option == Option.HOST_NAME: 540 opt = 3 # Uri-Host 541 val = value.encode('utf-8') 542 result += _encode_coap_option(opt - previous, val) 543 previous = opt 544 elif option == Option.HOST_IP: 545 opt = 3 # Uri-Host 546 if len(value) == 4: 547 val = '.'.join(str(c) for c in value).encode('utf-8') 548 elif len(value) == 16: 549 val = b'[' + ... + b']' # see RFC 5952 550 result += _encode_coap_option(opt - previous, val) 551 previous = opt 552 elif option == Option.PORT: 553 opt = 7 # Uri-Port 554 val = value.to_bytes((value.bit_length() + 7) // 8, 'big') 555 result += _encode_coap_option(opt - previous, val) 556 previous = opt 557 elif option == Option.PATH: 558 opt = 11 # Uri-Path 559 val = value.encode('utf-8') 560 result += _encode_coap_option(opt - previous, val) 561 previous = opt 562 elif option == Option.QUERY: 563 opt = 15 # Uri-Query 564 val = value.encode('utf-8') 565 result += _encode_coap_option(opt - previous, val) 566 previous = opt 567 elif option == Option.FRAGMENT: 568 pass 569 if to_proxy: 570 (option, value) = href[0] 571 opt = 39 # Proxy-Scheme 572 val = value.encode('utf-8') 573 result += _encode_coap_option(opt - previous, val) 574 previous = opt 575 return result 577 def _encode_coap_option(delta, value): 578 length = len(value) 579 delta_nibble = _encode_coap_option_nibble(delta) 580 length_nibble = _encode_coap_option_nibble(length) 581 result = bytes([delta_nibble << 4 | length_nibble]) 582 if delta_nibble == 13: 583 delta -= 13 584 result += bytes([delta]) 585 elif delta_nibble == 14: 586 delta -= 256 + 13 587 result += bytes([delta >> 8, delta & 255]) 588 if length_nibble == 13: 589 length -= 13 590 result += bytes([length]) 591 elif length_nibble == 14: 592 length -= 256 + 13 593 result += bytes([length >> 8, length & 255]) 594 result += value 595 return result 597 def _encode_coap_option_nibble(n): 598 if n < 13: 599 return n 600 elif n < 256 + 13: 601 return 13 602 elif n < 65536 + 256 + 13: 603 return 14 605 607 5. Security Considerations 609 Parsers of Constrained IRI References must operate on input that is 610 assumed to be untrusted. This means that parsers MUST fail 611 gracefully in the face of malicious inputs. Additionally, parsers 612 MUST be prepared to deal with resource exhaustion (e.g., resulting 613 from the allocation of big data items) or exhaustion of the call 614 stack (stack overflow). See Section 8 of RFC 7049 [RFC7049] for 615 security considerations relating to parsing CBOR. 617 The security considerations discussed in Section 7 of RFC 3986 618 [RFC3986] and Section 8 of RFC 3987 [RFC3987] also apply to 619 Constrained IRI References. 621 6. IANA Considerations 623 This document has no IANA actions. 625 7. References 627 7.1. Normative References 629 [I-D.ietf-cbor-cddl] 630 Birkholz, H., Vigano, C., and C. Bormann, "Concise data 631 definition language (CDDL): a notational convention to 632 express CBOR and JSON data structures", draft-ietf-cbor- 633 cddl-05 (work in progress), August 2018. 635 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 636 Requirement Levels", BCP 14, RFC 2119, 637 DOI 10.17487/RFC2119, March 1997, 638 . 640 [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform 641 Resource Identifier (URI): Generic Syntax", STD 66, 642 RFC 3986, DOI 10.17487/RFC3986, January 2005, 643 . 645 [RFC3987] Duerst, M. and M. Suignard, "Internationalized Resource 646 Identifiers (IRIs)", RFC 3987, DOI 10.17487/RFC3987, 647 January 2005, . 649 [RFC7049] Bormann, C. and P. Hoffman, "Concise Binary Object 650 Representation (CBOR)", RFC 7049, DOI 10.17487/RFC7049, 651 October 2013, . 653 [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 654 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, 655 May 2017, . 657 7.2. Informative References 659 [RFC5952] Kawamura, S. and M. Kawashima, "A Recommendation for IPv6 660 Address Text Representation", RFC 5952, 661 DOI 10.17487/RFC5952, August 2010, 662 . 664 [RFC6690] Shelby, Z., "Constrained RESTful Environments (CoRE) Link 665 Format", RFC 6690, DOI 10.17487/RFC6690, August 2012, 666 . 668 [RFC7228] Bormann, C., Ersue, M., and A. Keranen, "Terminology for 669 Constrained-Node Networks", RFC 7228, 670 DOI 10.17487/RFC7228, May 2014, 671 . 673 [RFC7230] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer 674 Protocol (HTTP/1.1): Message Syntax and Routing", 675 RFC 7230, DOI 10.17487/RFC7230, June 2014, 676 . 678 [RFC7252] Shelby, Z., Hartke, K., and C. Bormann, "The Constrained 679 Application Protocol (CoAP)", RFC 7252, 680 DOI 10.17487/RFC7252, June 2014, 681 . 683 [W3C.REC-html52-20171214] 684 Faulkner, S., Eicholz, A., Leithead, T., Danilo, A., and 685 S. Moon, "HTML 5.2", World Wide Web Consortium 686 Recommendation REC-html52-20171214, December 2017, 687 . 689 Acknowledgements 691 Thanks to Christian Amsuess and Ari Keranen for helpful comments and 692 discussions that have shaped the document. 694 Author's Address 696 Klaus Hartke 697 Ericsson 698 Torshamnsgatan 23 699 Stockholm SE-16483 700 Sweden 702 Email: klaus.hartke@ericsson.com