|
353 | 353 | at runtime, for instance due to application state that controls the operation's
|
354 | 354 | availability.
|
355 | 355 | </t>
|
356 |
| - <section title="Resolving templated URIs"> |
357 |
| - <t> |
358 |
| - URI Template variables in <xref target="href">"href"</xref> resolve from |
359 |
| - server-supplied instance data by default. This data is drawn from the |
360 |
| - sub-instance that validated against the schema containing the LDO. |
361 |
| - </t> |
362 |
| - <t> |
363 |
| - <xref target="templatePointers">"templatePointers"</xref> allows adjusting |
364 |
| - the location from which instance data is resolved on a per-variable |
365 |
| - basis. |
366 |
| - </t> |
367 |
| - <t> |
368 |
| - <xref target="hrefSchema">"hrefSchema"</xref> allows a link to specify |
369 |
| - a schema for resolving template variables from client-supplied data. |
370 |
| - Regular JSON Schema validation features can be used to require resolution |
371 |
| - from user agent data, forbid it, or allow user agent data while falling back |
372 |
| - to server-supplied instance data if no user agent data is provided. |
373 |
| - </t> |
374 |
| - <t> |
375 |
| - To implement the common pattern of resolving a templated path component |
376 |
| - with server-supplied instance data while accepting user agent data to build |
377 |
| - a query string: |
378 |
| - <list style="symbols"> |
379 |
| - <t> |
380 |
| - set the "hrefSchema" subschemas for the path template variables |
381 |
| - to false, to disallow user agent input |
382 |
| - </t> |
383 |
| - <t> |
384 |
| - give the query string template variables names that do not appear |
385 |
| - in the instance, to prevent resolving them from the instance |
386 |
| - </t> |
387 |
| - </list> |
388 |
| - See the "hrefSchema" section for an example of this approach. |
389 |
| - </t> |
390 |
| - <t> |
391 |
| - To implement the equivalent of an input form pre-populated with |
392 |
| - pre-existing instance data: |
393 |
| - <list style="symbols"> |
394 |
| - <t> |
395 |
| - ensure that each variable in the form resolves from the appropriate |
396 |
| - field in the instance, which provides the initial value that will |
397 |
| - continue to be used if the user agent takes no action to change it |
398 |
| - </t> |
399 |
| - <t> provide a validation schema for each of those fields in |
400 |
| - "hrefSchema", to describe what user agent input may be allowed |
401 |
| - to replace it |
402 |
| - </t> |
403 |
| - </list> |
404 |
| - This can be done with variables in any component of the URI template |
405 |
| - (path, query string, etc.) While the word "form" is used here, |
406 |
| - JSON Hyper-Schema does not constraint the nature of this interaction, which |
407 |
| - may or may not involve rendering an interactive form. |
408 |
| - </t> |
409 |
| - </section> |
410 | 356 | <section title="Manipulating the target resource representation">
|
411 | 357 | <t>
|
412 | 358 | In JSON Hyper-Schema, <xref target="targetSchema">"targetSchema"</xref>
|
|
451 | 397 | This property is REQUIRED.
|
452 | 398 | </t>
|
453 | 399 |
|
454 |
| - <section title="URI Templating"> |
455 |
| - <t> |
456 |
| - <cref> |
457 |
| - The pre-processing rules present in earlier drafts have been removed due |
458 |
| - to their complexity and inability to address all limitations with URI |
459 |
| - templating. |
460 |
| - This section is subject to significant change in upcoming drafts to |
461 |
| - replace the old pre-processing with a comprehensive solution. |
462 |
| - </cref> |
463 |
| - </t> |
464 |
| - <t> |
465 |
| - The value of "href" is to be used as a URI Template, as defined in |
466 |
| - <xref target="RFC6570">RFC 6570</xref>. |
467 |
| - However, some special considerations apply: |
468 |
| - </t> |
469 |
| - |
470 |
| - <section title="Values for substitution"> |
471 |
| - <t> |
472 |
| - The URI Template is filled out using data from some combination of an |
473 |
| - external source and the instance. |
474 |
| - Where either instance data or user agent data may be used, this section |
475 |
| - will refer simply to "data" or to a "value". |
476 |
| - When the source is important, it is specified explicitly. |
477 |
| - |
478 |
| - To allow the use of any object property (including the empty string) or |
479 |
| - array index, the following rules are defined: |
480 |
| - </t> |
481 |
| - |
482 |
| - <t> |
483 |
| - For a given variable name in the URI Template, the value to use is |
484 |
| - determined as follows: |
485 |
| - <list> |
486 |
| - <t> |
487 |
| - If the data is an array, and the variable name is a |
488 |
| - representation of a non-negative integer, then the value at the |
489 |
| - corresponding array index MUST be used (if it exists). |
490 |
| - </t> |
491 |
| - <t> |
492 |
| - Otherwise, the variable name should be percent-decoded, and the |
493 |
| - corresponding object property MUST be used (if it exists). |
494 |
| - </t> |
495 |
| - </list> |
496 |
| - </t> |
497 |
| - |
498 |
| - <t> |
499 |
| - If <xref target="hrefSchema">"hrefSchema"</xref> is present and |
500 |
| - user agent data is provided, the data MUST be a valid instance according |
501 |
| - to the value of "hrefSchema". |
502 |
| - Template variables, after the process listed above, MUST first |
503 |
| - be resolved from the user agent data instance. Any variables left |
504 |
| - unresolved MUST be resolved from the resource instance data. |
505 |
| - </t> |
506 |
| - |
507 |
| - <section title="Converting to strings"> |
508 |
| - <t> |
509 |
| - When any value referenced by the URI template is null, a boolean or |
510 |
| - a number, then it should first be converted into a string as |
511 |
| - follows: |
512 |
| - <list> |
513 |
| - <t> |
514 |
| - null values SHOULD be replaced by the text "null" |
515 |
| - </t> |
516 |
| - <t> |
517 |
| - boolean values SHOULD be replaced by their lower-case |
518 |
| - equivalents: "true" or "false" |
519 |
| - </t> |
520 |
| - <t> |
521 |
| - numbers SHOULD be replaced with their original JSON |
522 |
| - representation. |
523 |
| - </t> |
524 |
| - </list> |
525 |
| - </t> |
526 |
| - <t> |
527 |
| - In some software environments the original JSON representation of a |
528 |
| - number will not be available (there is no way to tell the difference |
529 |
| - between 1.0 and 1), so any reasonable representation should be used. |
530 |
| - Schema and API authors should bear this in mind, and use other types |
531 |
| - (such as string or boolean) if the exact representation is |
532 |
| - important. |
533 |
| - </t> |
534 |
| - </section> |
535 |
| - </section> |
536 |
| - |
537 |
| - <section title="Missing values" anchor="missingValues"> |
538 |
| - <t> |
539 |
| - Sometimes, the appropriate values will not be available. In many |
540 |
| - cases, the URI Template behavior of simply removing variables that |
541 |
| - do not have a value will be appropriate. An example of this is |
542 |
| - optional query parameters, the presence or absence of which does |
543 |
| - not change the nature of the link relation type. |
544 |
| - </t> |
545 |
| - |
546 |
| - <t> |
547 |
| - However, some variables, such as an identifier used in a path component, |
548 |
| - cannot meaningfully be omitted. The resulting URI would be meaningless, |
549 |
| - or would require a different link relation type. While "hrefSchema" can |
550 |
| - express a requirement for those variables that can be supplied via input, |
551 |
| - some variables must be resolved from instance data. When that instance |
552 |
| - data is not required by the context schema, the |
553 |
| - <xref target="templateRequired">"templateRequired</xref> keyword may |
554 |
| - be used to indicate that when the instance data is not available, the |
555 |
| - link does not apply. |
556 |
| - </t> |
557 |
| - </section> |
558 |
| - </section> |
559 |
| - |
560 | 400 | </section>
|
561 | 401 |
|
562 | 402 | <section title="templatePointers" anchor="templatePointers">
|
|
676 | 516 | any user agent data from being accepted.
|
677 | 517 | </t>
|
678 | 518 | <t>
|
679 |
| - Implementations MUST NOT attempt to validate values resolved from |
680 |
| - resource instance data with "hrefSchema". This allows for different |
| 519 | + Setting any subschema that applies to a particular variable to "false" |
| 520 | + prevents any user agent data from being accepted for that single variable. |
| 521 | + </t> |
| 522 | + <t> |
| 523 | + For template variables that can be resolved from the instance data, |
| 524 | + if the instance data is valid against all applicable subschemas |
| 525 | + in "hrefSchema", then it MUST be used to pre-populate the input |
| 526 | + data set for that variable. |
| 527 | + </t> |
| 528 | + <t> |
| 529 | + Note that even when data is pre-populated from the instance, the validation |
| 530 | + schema for that variable in "hrefSchema" need not be identical to the validation |
| 531 | + schema(s) that apply to the instance data's location. This allows for different |
681 | 532 | validation rules for user agent data, such as supporting spelled-out
|
682 |
| - months for date-time input but using the standard date-time |
683 |
| - format for storage. |
| 533 | + months for date-time input, but using the standard date-time format for storage. |
684 | 534 | </t>
|
685 | 535 | <figure>
|
686 | 536 | <preamble>
|
|
711 | 561 | </figure>
|
712 | 562 | <figure>
|
713 | 563 | <preamble>
|
714 |
| - In this example, the schema for "extra" is given as a reference |
| 564 | + In the following example, the schema for "extra" is given as a reference |
715 | 565 | to keep the user agent data validation constraints identical to the
|
716 | 566 | instance validation constraints for the corresponding property,
|
717 | 567 | while "id" is given a false schema to prevent user agent data for
|
@@ -957,7 +807,7 @@ GET /foo/
|
957 | 807 | <t>
|
958 | 808 | This property changes the point within the instance that is considered
|
959 | 809 | to be the context resource of the link. The value of the property MUST be a
|
960 |
| - valid <xref target="RFC6901">JSON Pointer</xref>, or a valid |
| 810 | + valid <xref target="RFC6901">JSON Pointer</xref>, or a valid |
961 | 811 | <xref target="I-D.luff-relative-json-pointer">Relative JSON Pointer</xref>
|
962 | 812 | which is evaluated relative to the position in the instance from which
|
963 | 813 | <xref target="href">"href"</xref> template variable resolution would
|
@@ -1539,6 +1389,166 @@ GET /foo/
|
1539 | 1389 | </t>
|
1540 | 1390 | </section>
|
1541 | 1391 | </section>
|
| 1392 | + <section title="URI Templating"> |
| 1393 | + <t> |
| 1394 | + Three hyper-schema keywords are <xref target="RFC6570">URI Templates</xref>: |
| 1395 | + "base", "anchor", and "href". Each are resolved separately to URI-references, |
| 1396 | + and then the anchor or href URI-reference is resolved against the base (which |
| 1397 | + is itself resolved against earlier bases as needed, each of which was first |
| 1398 | + resolved from a URI Template to a URI-reference). |
| 1399 | + </t> |
| 1400 | + <t> |
| 1401 | + All three keywords share the same algorithm for resolving variables from |
| 1402 | + instance data, which makes use of the "templatePointers" and "templateRequired" |
| 1403 | + keywords. When resolving "href", both it and any "base" templates |
| 1404 | + needed for resolution to an absolute URI, the algorithm is modfied to |
| 1405 | + optionally accept user input based on the "hrefSchema" keyword. |
| 1406 | + </t> |
| 1407 | + <t> |
| 1408 | + For each URI Template (T), the following pseudocode describes an algorithm for |
| 1409 | + resolving T into a URI-reference (R). For the purpose of this algorithm: |
| 1410 | + <list style="symbols"> |
| 1411 | + <t> |
| 1412 | + "ldo.templatePointers" is an empty object if the keyword was not |
| 1413 | + present and "ldo.templateRequired" is likewise an empty array. |
| 1414 | + </t> |
| 1415 | + <t> |
| 1416 | + "attachmentPointer" is the absolute JSON Pointer for the attachment |
| 1417 | + location of the LDO. |
| 1418 | + </t> |
| 1419 | + <t> |
| 1420 | + "getApplicableSchemas()" returns an iterable set of all (sub)schemas |
| 1421 | + that apply to the attachment point in the instance. |
| 1422 | + </t> |
| 1423 | + </list> |
| 1424 | + </t> |
| 1425 | + <t> |
| 1426 | + This algorithm should be applied first to either "href" or "anchor", |
| 1427 | + and then as needed to each successive "base". The order is important, |
| 1428 | + as it is not always possible to tell whether a template will resolve |
| 1429 | + to a full URI or a URI-reference. |
| 1430 | + </t> |
| 1431 | + <figure> |
| 1432 | + <preamble> |
| 1433 | + This is the high-level algorithm. "T" comes from either "href" |
| 1434 | + or "anchor" within the LDO, or from "base" in a containing schema. |
| 1435 | + Pseudocode for each step follows. |
| 1436 | + </preamble> |
| 1437 | + <artwork> |
| 1438 | +<![CDATA[ |
| 1439 | +templateData = populateDataFromInstance(T, ldo, instance) |
| 1440 | +
|
| 1441 | +if resolving "href" and ldo.hrefSchema exists: |
| 1442 | + inputData = acceptInput(ldo, instance, templateData) |
| 1443 | + for varname in inputData: |
| 1444 | + templateData[varname] = inputData[varname] |
| 1445 | +
|
| 1446 | +for varname in ldo.templateRequired: |
| 1447 | + if not exists templateData[varname] |
| 1448 | + fatal("Missing required variable(s)") |
| 1449 | +
|
| 1450 | +templateData = stringEncode(templateData) |
| 1451 | +R = rfc6570ResolutionAlgorithm(T, templateData) |
| 1452 | +]]> |
| 1453 | + </artwork> |
| 1454 | + </figure> |
| 1455 | + |
| 1456 | + <section title="Populating template data from the instance"> |
| 1457 | + <figure> |
| 1458 | + <artwork> |
| 1459 | +<![CDATA[ |
| 1460 | +for varname in T: |
| 1461 | + varname = rfc3986PercentDecode(varname) |
| 1462 | + if varname in ldo.templatePointers: |
| 1463 | + valuePointer = templatePointers[varname] |
| 1464 | + if valuePointer is relative: |
| 1465 | + valuePointer = resolveRelative(attachmentPointer, |
| 1466 | + valuePointer) |
| 1467 | + else |
| 1468 | + valuePointer = attachmentPointer + "/" + varname |
| 1469 | +
|
| 1470 | + value = instance.valueAt(valuePointer) |
| 1471 | + if value is defined: |
| 1472 | + templateData[varname] = value |
| 1473 | +]]> |
| 1474 | + </artwork> |
| 1475 | + </figure> |
| 1476 | + </section> |
| 1477 | + |
| 1478 | + <section title="Accepting input for template data"> |
| 1479 | + <figure> |
| 1480 | + <preamble> |
| 1481 | + "InputForm" represents whatevers sort of input mechanism is appropriate. |
| 1482 | + This may be a literal web form, or may be a more programmatic construct |
| 1483 | + such as a callback funciton accepting specific fields and data types, |
| 1484 | + with the given initial values, if any. |
| 1485 | + </preamble> |
| 1486 | + <artwork> |
| 1487 | +<![CDATA[ |
| 1488 | +form = new InputForm() |
| 1489 | +for varname in T: |
| 1490 | + useField = true |
| 1491 | + useInitialData = true |
| 1492 | + for schema in getApplicableSchemas(ldo.hrefSchema, |
| 1493 | + "/" + varname): |
| 1494 | + if schema is false: |
| 1495 | + useField = false |
| 1496 | + break |
| 1497 | +
|
| 1498 | + if varname in templateData and |
| 1499 | + not isValid(templateData[varname], schema)): |
| 1500 | + useInitialData = false |
| 1501 | + break |
| 1502 | +
|
| 1503 | + if useField: |
| 1504 | + if useInitialData: |
| 1505 | + form.addInputFieldFor(varname, ldo.hrefSchema, |
| 1506 | + templateData[varname]) |
| 1507 | + else: |
| 1508 | + form.addInputFieldFor(varname, ldo.hrefSchema) |
| 1509 | +
|
| 1510 | +inputData = form.acceptInput() |
| 1511 | +
|
| 1512 | +if not isValid(inputData, hrefSchema): |
| 1513 | + fatal("Input invalid, link is not usable") |
| 1514 | +
|
| 1515 | +return inputData: |
| 1516 | +]]> |
| 1517 | + </artwork> |
| 1518 | + </figure> |
| 1519 | + </section> |
| 1520 | + |
| 1521 | + <section title="Encoding data as strings"> |
| 1522 | + <figure> |
| 1523 | + <artwork> |
| 1524 | +<![CDATA[ |
| 1525 | +for varname in templateData: |
| 1526 | + value = templateData[varname] |
| 1527 | + if value is true: |
| 1528 | + templateData[varname] = "true" |
| 1529 | + else if value is false: |
| 1530 | + temlateData[varname] = "false" |
| 1531 | + else if value is null: |
| 1532 | + templateData[varname] = "null" |
| 1533 | + else if value is a number: |
| 1534 | + templateData[varname] = |
| 1535 | + bestEffortOriginalJsonString(value) |
| 1536 | + else: |
| 1537 | + templateData[varname] = rfc3986PercentEncode(value) |
| 1538 | +]]> |
| 1539 | + </artwork> |
| 1540 | + <postamble> |
| 1541 | + In some software environments the original JSON representation of a |
| 1542 | + number will not be available (there is no way to tell the difference |
| 1543 | + between 1.0 and 1), so any reasonable representation should be used. |
| 1544 | + Schema and API authors should bear this in mind, and use other types |
| 1545 | + (such as string or boolean) if the exact representation is |
| 1546 | + important. If the number was provide as input in the form of a |
| 1547 | + string, the string used as input SHOULD be used. |
| 1548 | + </postamble> |
| 1549 | + </figure> |
| 1550 | + </section> |
| 1551 | + </section> |
1542 | 1552 |
|
1543 | 1553 | <!--
|
1544 | 1554 | <section title="IANA Considerations">
|
|
0 commit comments