-
-
Notifications
You must be signed in to change notification settings - Fork 299
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support URI input with "hrefSchema" #228
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -473,7 +473,8 @@ | |
|
||
<section title="Values for substitution"> | ||
<t> | ||
After pre-processing, the URI Template is filled out using data from the instance. | ||
After pre-processing, the URI Template is filled out using data from some combination of user input and the instance. | ||
|
||
To allow the use of any object property (including the empty string), array index, or the instance value itself, the following rules are defined: | ||
</t> | ||
|
||
|
@@ -487,6 +488,14 @@ | |
</list> | ||
</t> | ||
|
||
<t> | ||
If <xref target="hrefSchema">"hrefSchema"</xref> is present and | ||
user input is provided, the input MUST be valid according to the value of "hrefSchema". | ||
Template variables, after the process listed above, MUST first | ||
be resolved from the user input instance. Any variables left | ||
unresolved MUST be resolved from the resource instance. | ||
</t> | ||
|
||
<section title="Converting to strings"> | ||
<t> | ||
When any value referenced by the URI template is null, a boolean or a number, then it should first be converted into a string as follows: | ||
|
@@ -506,18 +515,103 @@ | |
<section title="Missing values"> | ||
<t> | ||
Sometimes, the appropriate values will not be available. | ||
For example, the template might specify the use of object properties, but the instance is an array or a string. | ||
For example, the template might specify the use of object properties, but no such input was provide (or "hrefSchema" is not present), and the instance is an array or a string. | ||
</t> | ||
|
||
<t> | ||
If any of the values required for the template are not present in the JSON instance, then substitute values MAY be provided from another source (such as default values). | ||
If any of the values required for the template are present in neither the user input (if relevant) or the JSON instance, then substitute values MAY be provided from another source (such as default values). | ||
Otherwise, the link definition SHOULD be considered not to apply to the instance. | ||
</t> | ||
</section> | ||
</section> | ||
|
||
</section> | ||
|
||
<section title="hrefSchema" anchor="hrefSchema"> | ||
<t> | ||
The value of the "hrefSchema" link description property MUST be | ||
a valid JSON Schema. This schema is used to validate user input | ||
for filling out the URI Template in | ||
<xref target="href">"href"</xref>, as described in that section. | ||
</t> | ||
<t> | ||
Omitting "hrefSchema" or setting the entire schema to "false" prevents | ||
any user input from being accepted. | ||
</t> | ||
<t> | ||
Implementations MUST NOT attempt to validate values resolved from | ||
instance data with "hrefSchema". This allows for different | ||
validation rules for user input, such as supporting spelled-out | ||
months for date-time input but using the standard date-time | ||
format for storage. | ||
</t> | ||
<figure> | ||
<preamble> | ||
For example, this defines a schema for each of the query string | ||
parameters in the URI template: | ||
</preamble> | ||
<artwork> | ||
<![CDATA[{ | ||
"href": "/foos{?condition,count,query}", | ||
"hrefSchema": { | ||
"properties": { | ||
"condition": { | ||
"type": "boolean", | ||
"default": true | ||
}, | ||
"count": { | ||
"type": "integer", | ||
"minimum": 0, | ||
"default": 0 | ||
}, | ||
"query": { | ||
"type": "string" | ||
} | ||
} | ||
} | ||
}]]> | ||
</artwork> | ||
</figure> | ||
<figure> | ||
<preamble> | ||
In this example, the schema for "extra" is given as a reference | ||
to keep the user input validation constraints identical to the | ||
instance validation constraints for the corresponding property, | ||
while "id" is given a false schema to prevent user input for | ||
that variable. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I understand the first part of this explanation, but not the second part.
For easy reference...
Maybe this is my lack of understand of HyperSchema, but how does having it in hrefSchema allow it as input? In terms of input in the URL? If so, is it implying that an invalid URI is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, @Relequestual and I talked on IRC and identified some unclear wording that led to his confusion. I am going to rework that and then update this PR. |
||
</preamble> | ||
<artwork> | ||
<![CDATA[{ | ||
"definitions": { | ||
"extra": { | ||
"type": "string", | ||
"maxLength": 32 | ||
} | ||
}, | ||
"type": "object", | ||
"properties": { | ||
"id": { | ||
"type": "integer", | ||
"minimum": 1, | ||
"readOnly": true | ||
}, | ||
"extra": {"$ref": "#/definitions/extra"} | ||
}, | ||
"links": [{ | ||
"rel": "self", | ||
"href": "/things/{id}{?extra}", | ||
"hrefSchema": { | ||
"properties": { | ||
"id": false, | ||
"extra": {"$ref": "#/definitions/extra"} | ||
} | ||
} | ||
}] | ||
}]]> | ||
</artwork> | ||
</figure> | ||
</section> | ||
|
||
<section title="rel"> | ||
<t> | ||
The value of the "rel" property indicates the name of the relation to the target resource. The value MUST be a registered link relation from the <xref target="RFC5988">IANA Link Relation Type Registry established in RFC 5988</xref>, or a normalized URI following the <xref target="RFC3986">URI production of RFC 3986</xref>. | ||
|
@@ -845,7 +939,10 @@ GET /foo/ | |
</t> | ||
|
||
<t> | ||
Note that this does not provide data for any URI templates. | ||
Note that this does not provide data for any URI templates. That is handed by <xref target="hrefSchema">"hrefSchema"</xref>. If the method is "get" and the resolved URI Template has a query string, the query string produced by input validated agaisnt "schema" replaces the existing query string. | ||
</t> | ||
|
||
<t> | ||
This is a separate concept from the "targetSchema" property, which is describing the target information resource (including for replacing the contents of the resource in a PUT request), unlike "schema" which describes the user-submitted request data to be evaluated by the resource. | ||
</t> | ||
</section> | ||
|
@@ -916,6 +1013,7 @@ GET /foo/ | |
<t hangText="draft-wright-json-schema-hyperschema-01"> | ||
<list style="symbols"> | ||
<t>Fixed examples</t> | ||
<t>Added "hrefSchema" for user input to "href" URI Templates</t> | ||
</list> | ||
</t> | ||
<t hangText="draft-wright-json-schema-hyperschema-00"> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels different to how we normally do things. If I read that right, you're saying that omitting hrefSchema will always result in a validation fail if user input is provided. This now means that the URI template is useless without defining the validation with hrefSchema, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Relequestual no, it just means that you can't provide user input to resolve the template. In other words, if "hrefSchema" is absent, everything works exactly the same as it does now. That seemed preferable, although I take your point that we usually allow things unless forbidden.
I was also kind of going by how I think "schema" works. I think that if "schema" is not present, then there is no input allowed via that route. But going back and reading it, it's not really clear whether that is intended to be 'you can only provide input if "schema" is present' or 'if there is no schema, you can provide any input'.
Given how "schema" and "encType" are generally described, I think it/they need to be present for input to be allowed. If that is indeed the case, then "hrefSchema" should have the same behavior. If that is not the case, and a missing "schema" means any and all input is allowed, then yes, "hrefSchema" should be changed to behave that way as well.
Either way, we should also clarify the behavior when "schema" is absent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Relequestual I figured out why it made sense to me to do it this way.
Validation is a constraint system. An empty schema validates everything, and every keyword you add restricts the set in some way.
Hyper-schema defines functionality. So in my head thats an additive capability approach. A blank hyper-schema indicates that there are no known hypermedia transitions, not that all possible transitions should work. So to me, it's philosophically consistent to look at a link and say that a minimal link defines minimal functionality. In order to know that it takes user input, it has to declare that it does.
I can see an argument in the other direction, though. I just wanted to explain why it felt consistent to me. I view it as a different conceptual model than validation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@handrews @Relequestual
One reason to take the additive approach that @handrews outlines is that it forces the user to define a schema whenever there are URI template variables to resolve, I think that is a nice feature because otherwise it suggests that you can provide any data whatsoever, where the object 's properties must coincidentally align with the URI template variables in run-time, sort of how it's set up currently. Perhaps the
schema
keyword has been previously used for this purpose in addition to validation, I can't really say. If this is true, I believe preventingschema
from being used for multiple purposes is a good thing, that way one turning knob doesn't have two potential effects.I agree, the template alone isn't enough to say "I accept some data" because you're then left with the question of "well what kind of data do you accept?". In an ecosystem essentially based around defining comparable types, I'd argue it's pretty essential. Perhaps we could also say: "
hrefSchema
is only required and used for validation if there are URI template variables to resolve, otherwise it is / should be ignored"There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the naïve answer which I tried when implementing a previous project is to just look up the part of the instance schema that corresponds to the instance data that you would use to resolve that template variable. If you have a simple object for your instance, that's easy enough to do. But if you have some complex beast of "oneOf"s and "not" and "dependencies", etc., it's challenging. And not even possible unless you have an instance available.
It was very messy to implement, hence me deciding to require that input schemas be specified on their own rather than inferred. Explicit is better than implicit.