Skip to content
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

adds ABNF for path templating #4244

Open
wants to merge 4 commits into
base: v3.2-dev
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions src/oas.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,27 @@ Each template expression in the path MUST correspond to a path parameter that is

The value for these path parameters MUST NOT contain any unescaped "generic syntax" characters described by [RFC3986](https://tools.ietf.org/html/rfc3986#section-3): forward slashes (`/`), question marks (`?`), or hashes (`#`).

The path templating expression is defined by the following [ABNF](https://tools.ietf.org/html/rfc5234) syntax

```abnf
; OpenAPI Path Templating ABNF syntax
path-template = slash *( path-segment slash ) [ path-segment ]
path-segment = 1*( path-literal / template-expression )
slash = "/"
path-literal = 1*( unreserved / pct-encoded / sub-delims / ":" / "@" )
template-expression = "{" template-expression-param-name "}"
template-expression-param-name = 1*( unreserved / pct-encoded / sub-delims / ":" / "@" )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only explicit restriction we state is that

Each template expression in the path MUST correspond to a path parameter

and there are no restrictions on path parameter names.

The only implicit restriction is that the } cannot be used in a template expression because we don't define an escaping mechanism for it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so you'd extend what's in there in essence? I double checked RFC5234 and there does not appear to be any way so simply say "anything but this character", and I think it's on purpose.

What do you think is missing? %[]^"'<>? ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trick question: which ABNF rule is equivalent to regexp ^[^}]+$ 😎

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's effectively what I was looking for, couldn't find an equivalent, but maybe I missed something?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My ABNF knowledge reaches its limits with this question 😞

Copy link
Contributor

@ralfhandl ralfhandl Dec 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The most generous rule would be

Suggested change
template-expression-param-name = 1*( unreserved / pct-encoded / sub-delims / ":" / "@" )
template-expression-param-name = 1*( %x00-7C / %x7E-10FFFF ) ; every Unicode character except "}"

This relies on path templates being represented as JSON or YAML strings and thus using UTF-8.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ralfhandl should we also at least exclude { ? it'd probably make parser's lives much easier.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ralfhandl @baywet I'd consider /foo/{bar{baz}/stuff to be an error, because it's ambiguous as to whether the template name here is bar{baz or just baz. We don't define a precedence or parse order, so there's no way to resolve this. Therefore I think we can exclude it. If we want to put this into 3.1.2 we can finesse it by saying that the behavior of any template that does not match the ABNF is implementation-defined. That's valid to do when there's ambiguity. The same logic would apply to apparently-nested names, e.g. /foo/{bar{baz}abc}/

But for things like using a space in a template name... there's nothing that forbids it and nothing that makes its parsing exceptionally difficult, much less ambiguous. In YAML you can even write:

/{foo bar}:
  parameters:
  - in: path
    name: foo bar

and it parses just fine:

>>> yaml.safe_load("""
... /{foo bar}:
...   parameters:
...   - in: path
...     name: foo bar
... """)
{'/{foo bar}': {'parameters': [{'in': 'path', 'name': 'foo bar'}]}}

For the control characters, you could technically use the same argument as for the space character, but I think there's a reasonable expectations that control characters are always a special case, and are implicitly excluded if they are not explicitly included. I am completely making that rule up, but I suspect it won't bother people. On the other hand, I would not be at all surprised if someone put a space in a template variable name. For... reasons.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for all this additional information!

I think we're reaching a consensus to this

%x00-79 / %x7C / %x7E-10FFFF ; every UTF8 character except { and }

Thoughts?


; Characters definitions (from RFC 3986)
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded = "%" HEXDIG HEXDIG
sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
/ "*" / "+" / "," / ";" / "="
ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
DIGIT = %x30-39 ; 0-9
HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
```

### Media Types

Media type definitions are spread across several resources.
Expand Down
Loading