v3.2: issues with the path-item and server url templates
Thank you for the expanded sections on path and server url templating in the 3.2 spec (https://spec.openapis.org/oas/latest#path-templating and https://spec.openapis.org/oas/latest#server-variable-object respectively) -- this is quite helpful in ensuring closer specification compliance in implementations that perform matching of live HTTP requests against elements of the OpenAPI description (OAD).
However I have some questions and concerns that might suggest there are errors with the specification, or perhaps areas where further clarifications could be added:
-
In both path templates and server urls, we do not explicitly disallow two adjacent template components - e.g.
/{foo}{bar}. In the absence of specifying which one of these matches is greedy, there is no deterministic way of matching this, and should be prohibited. (I filter these out in regexes (see below) using a negative look-ahead assertion.) -
https://spec.openapis.org/oas/latest#path-templating says that the path template ABNF is derived from RFC3986 s3.3 (via commit e4caedca690, by @baywet). But that section describes URI paths, not templates. Was this intended to refer to the uri template RFC instead?
The regular expressions that I am using in my implementation are below; I would appreciate a sanity check:
-
for path templates: each segment (split on
/, after omitting the leading/) must match:^(?:\{[^{}]+\}(?!\{)|%[0-9A-F]{2}|[:@!\$&'()*+,;=A-Za-z0-9._~-]+)+$ -
for server url, the entire string must match:
^(?:\{[^{}]+\}(?!\{)|%[0-9A-F]{2}|[\x21\x23\x24\x26-\x3B\x3D\x3F-\x5B\x5D\x5F\x61-\x7A\x7E\xA0-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}\x{E000}-\x{F8FF}\x{F0000}-\x{FFFFD}\x{100000}-\x{10FFFD}])+$
Thanks for creating this issue (and for mentioning so I get a notification)
In both path templates and server urls, we do not explicitly disallow two adjacent template components - e.g. /{foo}{bar}. In the absence of specifying which one of these matches is greedy, there is no deterministic way of matching this, and should be prohibited.
I don't see why we should prohibit this as a path template? To me this is perfectly valid as RFC 6570 and a valid use case from the client side perspective which does need to know how the server will parse things to some extent. Of course, in that example, it'd be better to use value modifiers (if the values are fixed length) so both the client and server side know what to expect.
https://spec.openapis.org/oas/latest#path-templating says that the path template ABNF is derived from RFC3986 s3.3 (via commit https://github.com/OAI/OpenAPI-Specification/commit/e4caedca6906ee964690e8879a06eee7edc2fabc, by @baywet). But that section describes URI paths, not templates. Was this intended to refer to the uri template RFC instead?
Essentially we built this ABNF using parts of the one provided by 6570, and 6570 says itself "we're using some ABNF from 3986" so we decided to quote align with the source here. Like 6570 does here https://datatracker.ietf.org/doc/html/rfc6570#section-1.5
I don't see why we should prohibit this as a path template? To me this is perfectly valid as RFC 6570 and a valid use case from the client side perspective which does need to know how the server will parse things to some extent.
On the server side, there is no way to parse this deterministically. When matching /{foo}{bar} against the path /abcde, what are the values of foo and bar, that would be provided to a validator as the values of the foo and bar path parameters?
Of course, in that example, it'd be better to use value modifiers (if the values are fixed length) so both the client and server side know what to expect.
How would that be done? Are you suggesting that path template matching should be supporting the full syntax of URI templates in RFC6570, e.g. a path template of {/who,who} should match /fred/fred?
A path template like /{foo}{bar} is currently allowed, and there are many situations where it may make sense:
- There are additional constraints that make it deterministically parseable, and these constraints are intentionally not mentioned in the OAD, or impossible to formally express in OpenAPI 3.x, or …
- The OAD describes an existing server, and generating a server implementation solely from the OAD is a non-goal.
- …
From a specification perspective there is not much we can do about that, we cannot add restrictions on path templates in a 3.x spec because we want to avoid breaking changes in a minor spec version.
There were discussions in Moonwalk about signatures and whether they have to be unambiguous, and as far as I know it hasn’t been decided yet whether ambiguous signatures are a problem or a feature.
I suggest moving the „disallow“ parts of this issue to Moonwalk.
Given your question
Are you suggesting that path template matching should be supporting the full syntax of URI templates in RFC6570
I think we should remove all mentions of RFC6570 from the sections on path templates and server URL templates and solely refer to RFC3986.
I think we should remove all mentions of RFC6570 from the sections on path templates and server URL templates and solely refer to RFC3986.
@ralfhandl do you just mean the ABNF stuff or throughout the spec? We do reference RFC6570 behavior to define our own field behavior oin the Parameter, Header, and Encoding Objects.
@handrews I only mean the two templating sections
There I want to avoid any misunderstanding that we might want to support or require the full power of RFC6570.
In path templating the only mention of 6570 is for Appendix C. Which in essence says "if you want to use 6570 to perform the expansion, you can, here are a few considerations" (the reference to path templating is implicit through the parameters).
In the server variable object, the only mention is for the ABNF parts we "borrowed" from that spec.
Maybe as 3.3 we could clarify in appendix C some of the wording, to specifically call out that using 6570 for URL templating is possible, but not required? But beyond that I'm not sure what could be changed without causing a "breaking change" (adding more restrictions and whatnot)
@baywet ah, right it used to be mentioned more but we've moved more and more of those to the appendix. I think it still gets mentioned in a definition of allowReserved but it's mostly the appendix in 3.2.