-
Notifications
You must be signed in to change notification settings - Fork 890
feat(profiles): server-required profiles #1354
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
Conversation
This is one final section from #1999 that I realized never made it over to the current spec.
#1999 does not exist :) Not sure which issue/PR you're referring to? |
Whoops. I've updated the OP. |
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.
Looking good overall! Two nits, two questions.
### <a href="#profiles-required" id="profiles-required" class="headerlink"></a> Server-Required Profiles | ||
|
||
Generally, servers should not require that clients apply specific profiles to | ||
their requests, as such requirements reduce interoperability. |
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 is a very important sentence for understanding how profiles are meant to be implemented for maximum interoperability! I'm glad we're adding it after all :)
|
||
However, in many common cases, a server does require that clients provide | ||
certain data (e.g., authentication credentials), and it **MAY** require that | ||
this data be provided by applying a specific profile (or any one profile from |
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.
I find this example not very convincing. I cannot imagine authentication is often embedded into JSON:API documents. Authentication is an orthogonal concern.
Which leaves me wondering: what is a good example of this? Why is this "common"?
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.
I think it's strange that this statement broadly contradicts the one before it by saying "Generally servers should not require profiles" and then "in many common cases, servers can require profiles".
I think it's hard to think of an example where extra data must be provided (a revision
key is the best I could come up with), but I can think of requirements about how that data is provided (i.e. different profiles for different date/time formats).
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.
I find this example not very convincing. I cannot imagine authentication is often embedded into JSON:API documents. Authentication is an orthogonal concern.
Authentication isn't a great example; I was imagining a case where maybe a request signature could show up in the body (e.g., in top-level meta
), but Gabe's examples are better tbh. I can update the PR and the wording.
I think it's strange that this statement broadly contradicts the one before it by saying "Generally servers should not require profiles" and then "in many common cases, servers can require profiles".
How would you suggest wording it?
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.
A server MAY require that a client applies a specific profile to its request.
However, it is NOT RECOMMENDED for servers to require profiles which require additional query parameters or additional request document members, as such requirements reduce interoperability between clients and servers.
Note: Profiles with optional document members, specific value formats (e.g. ISO 8601 date and time format), or specific query parameters within a query parameter family already reserved by this specification should be treated with care, but do not have the same level of interoperability concerns.
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.
My theory here is that:
- anything optional obviously doesn't have interop concerns.
- query parameters within query parameter families are usually implementation specific (filter, sort, etc) so clients will likely not have them hardcoded.
- like Consider relaxing some MUSTs #2, value formats are usually "passed through" a client library and aren't hardcoded; they typically come from a frontend developer working against a specific backend.
required profile that is missing, and this error object **MUST**: | ||
|
||
1. have a `type` who's URI is `http://jsonapi.org/errors/missing-required-profile` | ||
2. include the URI of the missing profile in the `extension` member of the |
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.
s/extension/profile/
that the error was caused by a missing profile, JSON object key (or array | ||
index), or URI query parameter. If present, this object **MUST** contain | ||
exactly one of the following keys: | ||
* `extension`: the URI of a missing profile. This key **SHOULD** be |
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.
s/extension/profile/
@@ -2371,6 +2393,23 @@ An error object **MAY** have the following members: | |||
exists; if it doesn't, the client **SHOULD** simply ignore the pointer. | |||
* `parameter`: a string indicating which URI query parameter caused | |||
the error. | |||
* <a id="error-objects-source-missing"></a>`missing`: an object indicating | |||
that the error was caused by a missing profile, JSON object key (or array | |||
index), or URI query parameter. If present, this object **MUST** contain |
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.
I can't think of a use case for the missing array index. What am I missing?
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.
E.g., a profile that takes data in an [x,y,z]
coordinate pair is given an array with fewer entries. More importantly, though, it just seems good to general here
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.
The coordinate example helps, thanks!
But I thought profiles only could add elements to the document structure (per
https://jsonapi.org/format/1.1/#profile-keywords-and-aliases), which means they must have a name, and hence a JSON object key? Wouldn't the coordinate example be a value of an object key, and therefore z
being absent from [x,y,z]
would not result in a missing
error since the key would be present, the value itself would just be invalid. In other words: invalid
, not missing
?
I'm probably still missing something, sorry.
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.
Wouldn't the coordinate example be a value of an object key, and therefore z being absent from
[x,y,z]
would not result in a missing error since the key would be present, the value itself would just be invalid.
It's both. I.e., the value is invalid because a key (index 2) is missing.
In other words, if a client client sends:
{ "meta": { "homeBase": [x,y] }
then the server's error object would ideally contain "pointer": "/meta/homeBase"
, whether it contains "missing"
or not. But that just tells you that the value at /meta/homeBase
had an error. Being able to supplement the pointer with "missing": { "key": "2" }
just makes it a bit more specific about what the error was.
In theory, you never need "missing": { "key": "... " }
, because you can always reinterpret your error as being not that some key is missing, but that the value that's supposed to contain the key (pointed to by "pointer") is invalid. But missing
is a way to be more specific about "invalid how".
I think this PR brings to a head some concerns I've had about requirements for clients. In https://jsonapi.org/format/1.1/#profiles-sending we place the same MUST requirement on clients as on servers:
Since profiles are additive to the base spec, I believe that this MUST could be relaxed to a SHOULD. Similarly, if a server requires that a profile be applied, then it could operate as if the document it receives has applied that profile without it being explicitly stated. Of course, it would still need to respond with an error if a conflicting profile has been applied OR if the required profile has been applied incorrectly. By making servers more forgiving about accepting documents without explicitly declared profiles we could simplify the experience for clients without harm. This seems inline with allowing clients to omit the |
If the client is already updated to specifically send a JSON:API document with a profile applied, then why is requiring that profile to be specified in the media type as well unreasonable? |
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.
re base please
* `key`: the name of a missing key in a JSON object, or a missing index in | ||
a JSON array, expressed as a string. This key **SHOULD** be used with | ||
the `pointer` member to indicate which object/array in the request | ||
document is missing the key. |
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.
Even if server-required profiles doesn't make it into 1.1, I think this is a worthwhile addition, paired with the language added in e75cec1 to clarify that the pointer must reference an element in the original request. In the case of a missing key, this should be paired with some other data point (e.g., this element) to tell the client exactly which data was missing.
To @wimleers' question in #1354 (comment)
I think this is precisely because profile functionality has predated the official release of json:api 1.1. E.g., I have a client that is implementing Drupal's fancy filtering without sending a content-type parameter indicating so. I don't think we can require clients to upgrade their request parameters simultaneous with the server. However, that doesn't mean this improvement is for nothing, in so far as it aids in compatible profile negotiation; as @dgeb points out:
Again, in Drupal's case, this could mean we detect some sort of problem in the fancy-filtering request parameters, and can throw and translate exceptions to the json:api implementation to indicate that we should tell the client precisely which profile they must implement (correctly) to remedy the problem. |
This PR was written at a time when we were considering "profiles" to provide a single answer to the separate roles that profiles and extensions now play in v1.1. As such it is outdated, although the work has definitely informed the current state of the spec. Many thanks to @ethanresnick for his work here!
@bradjones1 Yes, I think this is reasonable. And hopefully clients / servers will soon start explicitly negotiating profiles. |
This is one final section from #1195 that I realized never made it over to the current spec.