Closed dret closed 1 year ago
Huh.
After a bit of discussion, I think we've landed on std-
-- thoughts?
Many programming languages don't support hyphen as a character in identifiers. Using std_
would require less translation as all the languages I have seen do support underscore. Having said that, most serializers/deserializers already have the ability to do mappings between wire formats and types so it is not a big deal.
You're defining the format. I think you can do better. Don't invent a new mechanism. If you have the will to do it in a proper, extensible fashion, borrow a page from XML or JSON-LD and work out how to associate URIs with short names in some way. If you don't have the will to do that, borrow a page from HTML5 and reserve all names that don't include a hypen (or an underscore or 💩) in them for yourself and let anyone adding new properties distinguish theirs.
reserve all names that don't include a hyp[h]en ... in them for yourself and let anyone adding new properties distinguish theirs [by using a hyphen]
I like that suggestion. Standard fields should be easy and straight-forward (including future ones). Non-standard fields should do a little extra.
If we were doing this from scratch, that might be workable (although it's not very intuitive). As it is, we have to take reasonable steps to assure we won't collide with existing usage; that is very likely to.
So, the opposite of "X-" then? I find myself wondering whether this solution is worse than the problem it aims to fix.
Let's say that I include a field that encodes an entire problem report from an upstream server. I define "upstream" to carry the problem report. That turns out to be useful and it is standardized as "std-upstream"[^1]. Now, do I teach my code to just strip "std-" prefixes? Maybe not for one instance like this, but if that starts happening more often, it starts looking tempting and "std-" becomes meaningless.
The alternative is just to suck it up and acknowledge that there might be collisions between what a standard defines and what a resource uses. New additions to standards might conflict with resource-specific usage that is unaware of changes in standards. But problem reports are always subject to some amount of interpretation and subtle semantic differences in the interpretation of fields with the same name but different definitions is already possible for stuff defined outside of standards. Reifying standardized values doesn't really improve that situation a whole lot.
As @mnot says, with forethought, this problem might have been anticipated and avoided.
[^1]: More likely it would a different name because standards, but maybe I was lucky this time and no one decided to bikeshed names.
I'm torn between all of the proposed solutions. I can totally understand the arguments for/against each and every one of them. In the end, what matters is that the solution is usable and understandable for all parties involved.
I do have to agree with @martinthomson and would like to pick up his example. If std-upstream
gets introduced we would have elements in the returned JSON that have the prefix attached to them and some that don't. From a users perspective this feels odd. So it probably would make sense to also "claim" the prefixed version for the old elements (std-status
, std-instance
, std-type
, and so on).
The second option would be to define that API providers who use their own elements prefix them with x-
or make them use a hyphen like @ndw proposed. This would make it also easier for consumers who are not familiar with the spec to understand what has been added by the provider. Yes this would also "break" existing implementations, but at least API providers only have to adjust their work once, instead of doing it every time a new "standard element" gets introduced.
The third option would be to create a new (version of the) standard replacing this one and in there define extensibility the way we think it should be implemented. Of course this would mean postponing a solution for providing future extensions for quite some time, but at least then we don't have to fear that we're breaking existing implementations.
There are many ways to spell this; e.g., if we want a new standard extension foo
that takes integer values from conflicting with a type-local extension that takes (for example) string values, we could put standard extensions in a container:
{
"type": "https://example.com/probs/out-of-credit",
"title": "You do not have enough credit.",
"detail": "Your current balance is 30, but that costs 50.",
"instance": "/account/12345/msgs/abc",
"std-exts": {
"foo": 1
},
"foo": "abc"
}
Or, we could invert that, and recommend that future problem types put everything into a local-exts
container:
{
"type": "https://example.com/probs/out-of-credit",
"title": "You do not have enough credit.",
"detail": "Your current balance is 30, but that costs 50.",
"instance": "/account/12345/msgs/abc",
"foo": 1,
"local-exts": {
"foo": "abc"
}
}
However, that doesn't avoid the problem that @martinthomson points out -- someone using a type-local extension that gets promoted to a standard extension needs to transition.
Maybe it's not that bad. If I'm consuming an existing problem type that uses the local extension, I'll need to understand that extension to consume it; it merely being defined as a standard extension doesn't change that. The producer of the problem can rely upon that, and can choose to either add the standard extension as a backwards-compatible change to their API, or they can wait until they version the API to switch to the standard, as a breaking change.
The producer of the problem can rely upon that, and can choose to either add the standard extension as a backwards-compatible change to their API, or they can wait until they version the API to switch to the standard, as a breaking change.
That holds true if the producer has complete control over how the problem+json
is produced. As https://github.com/ietf-wg-httpapi/rfc7807bis/pull/48#issuecomment-1256130831 proves, various web application frameworks such as Microsoft ASP.NET may be the deciding factor in what is included in the response, and how.
As an upgrade from one version of a framework to another may rest on many other factors than its problem+json
implementation, there's reasons to believe future extensions to the standard implemented in such frameworks may cause unintentional breakage.
So, AIUI you're saying that if a framework adds a new standard member and a deployment upgrades to it without versioning their API, trouble could result. Fair.
Stepping back, the purpose of *-
(or whatever we call it) was to make room for future standard extensions; we don't have one to include at the moment. Since it appears we're not sure how best to accommodate them, it might be best not to try to accommodate them -- i.e., punt the issue down the road -- especially since the right solution might be to introduce a new media type.
I'm supportive of that conclusion. This has escaped and thus we no longer have any control over it. Though a new media type is a bit disruptive, it seems commensurate with the risks.
On Apr 12, 2023, at 08:02, Mark Nottingham @.***> wrote:
Stepping back, the purpose of *- (or whatever we call it) was to make room for future standard extensions; we don't have one to include at the moment. Since it appears we're not sure how best to accommodate them, it might be best not to try to accommodate them -- i.e., punt the issue down the road -- especially since the right solution might be to introduce a new media type.
i my mind let's keep punting. we didn't address it in the original RFC and it may just be one of those things where the cure is worse than the disease.
I too support postponing this decision until the need to add another standard field arises.
Without chair hat, I support the removal of the extension.
These two paragraphs read a little funny in conjunction, given that the first one announces that the spec may start using names that are against the guidance in the second paragraph.
I have no great idea how to improve this, but reading through the text just made me wonder how these two things fit together and others may have the same reaction.