Due to some backward compatibility reasons, I need to support both the paths /ab and /a-b.
The request and response objects are going to be the same for both of the paths.
Can I have something like the following in my Swagger spec so that I do not have to repeat the request and response object definitions for both the paths.
paths:
/ab:
/a-b:
post:
...
Yes, you can have a path item that references another path item:
paths:
/ab:
post:
summary: ...
...
responses:
...
/a-b:
$ref: '#/paths/~1ab' # <------------
Here, ~1ab is an encoded version of /ab (see below).
One limitation of this approach is that you cannot have operationId in all operations of the referenced path item. This is because the copy of the path ends up with the same operationId values, but operationId must be unique.
Encoding $ref values
If the characters ~ and / are present in node names (as in case of path names, e.g. /ab) they must be encoded: ~ as ~0, and / as ~1:
/ab → ~1ab → $ref: '#/paths/~1ab'
/foo/bar → ~1foo~1bar → $ref: '#/paths/~1foo~1bar'
/ab~cd → ~1ab~0cd → #/paths/~1ab~0cd
Additionally, { } and other characters not allowed in URI fragment identifiers (RFC 3986, section 3.5) need to be percent-encoded. For example, { becomes %7B, and } becomes %7D.
/{zzz}
→ ~1{zzz} ( / replaced with ~1)
→ ~1%7Bzzz%7D (percent-encoded)
→ $ref: '#/paths/~1%7Bzzz%7D'
/foo/{zzz}
→ ~1foo~1{zzz} ( / replaced with ~1)
→ ~1foo~1%7Bzzz%7D (percent-encoded)
→ $ref: '#/paths/~1foo~1%7Bzzz%7D'
Note that you need to encode just the path name and not the #/paths/ prefix.
Related
The <<: operator in YAML is usable to import the contents of one mapping into another, similarly to the ** double-splat operator in Python or ... object destructuring operator in JavaScript. For example,
foo:
a: b
<<:
c: d
e: f
is equivalent to
foo:
a: b
c: d
e: f
This is useful when used along with node anchors to include some common default properties in many objects, as illustrated in, for example, the Learn YAML in Y minutes tutorial:
# Anchors can be used to duplicate/inherit properties
base: &base
name: Everyone has same name
foo: &foo
<<: *base
age: 10
bar: &bar
<<: *base
age: 20
However, I am confused about where this syntax comes from or why it works. CTRL + Fing the YAML specification for << reveals that it doesn't appear anywhere in the specification. Yet it's supported by, at the very least, PyYAML and Online YAML Parser.
What is this syntax, and how come it doesn't seem to appear in the specification?
It is called the Merge Key Language-Independent Type for YAML version 1.1. and specified here.
It is something that parsers can optionally support, and it is essentially an interpretation of the key-value pair with the special key <<, where the value is either a mapping (usually indicated via an alias as in the spec, and although that doesn't seem to be required, it makes little sense not to use an alias) or a list of mappings (i.e., aliases of mappings), and gets interpreted in a special way.
To add on to other answers:
IMO, the example from "Learn YAML in Y Minutes" is incomplete, because it doesn't show what happens when the keys are the same. For example:
base: &base
name: Everyone has same name
age: 5
foo: &foo
<<: *base
bar: &bar
<<: *base
age: 20
For the bottom two items, it yields:
foo:
name: Everyone has same name
age: 5
bar:
name: Everyone has same name
age: 20
bar overrides the age while foo does not. According to the spec, the entries of the object merging in have a lower priority than those on the object receiving them.
The “<<” merge key is used to indicate that all the keys of one or more specified maps should be inserted into the current map. If the value associated with the key is a single mapping node, each of its key/value pairs is inserted into the current mapping, unless the key already exists in it.
I am trying to understand in which case the forward slash needs to be escaped when writing OpenApi specification document.
Here (https://swagger.io/docs/specification/using-ref/) is written:
/ and ~ are special characters in JSON Pointers, and need to be escaped when used literally
(for example, in path names).
For example, to refer to the path /blogs/{blog_id}/new~posts, you would use:
$ref: '#/paths/~1blogs~1{blog_id}~1new~0posts'
In this example the first two forward slashes are not escaped?
Then later the following example is given:
$ref: '../resources/users.yaml'
$ref: '../resources/users-by-id.yaml'
And these paths are not escaped?
In which case all (or part of the) forward slashes need to be escaped with ~1 ?
The JSON Pointer part of a $ref is the part after the # fragment delimiter. Before that is the relative or absolute URI, where forward slashes do not need to be escaped.
In the section following the #, the values of things like pathItem keys which contain forward slashes do need to be escaped.
I am writing a grammar with a lot of case-insensitive keywords in ANTLR4. I collected some example files for the format, that I try to test parse and some use the same tokens which exist as keywords as identifiers in other places. For example there is a CORE keyword, which in other places is used as a ID for a structure from user input. Here some parts of my grammar:
fragment A : [aA]; // match either an 'a' or 'A'
fragment B : [bB];
fragment C : [cC];
[...]
CORE: C O R E ;
[...]
IDSTRING: [a-zA-Z_] [a-zA-Z0-9_]*;
id: IDSTRING ;
The error thrown then is line 7982:8 mismatched input 'core' expecting IDSTRING, as the user input is intended as IDSTRING, but always eaten by the keyword rule. In the input it exists both as keyword and as id like this:
MACRO oa12f01
CLASS CORE ; #here it is a KEYWORD
[...]
SITE core ; #here it is a ID
Is there a way I can let users use some keywords as identifiers by changing my grammar somehow like "casting" the token to IDSTRING for conjunctive rules like this or is this a false hope in not hand written parsers?
You can simply list the keywords that are allowed as identifiers as alternatives in the id rule:
id: IDSTRING | CORE | ... ;
Due to some backward compatibility reasons, I need to support both the paths /ab and /a-b.
The request and response objects are going to be the same for both of the paths.
Can I have something like the following in my Swagger spec so that I do not have to repeat the request and response object definitions for both the paths.
paths:
/ab:
/a-b:
post:
...
Yes, you can have a path item that references another path item:
paths:
/ab:
post:
summary: ...
...
responses:
...
/a-b:
$ref: '#/paths/~1ab' # <------------
Here, ~1ab is an encoded version of /ab (see below).
One limitation of this approach is that you cannot have operationId in all operations of the referenced path item. This is because the copy of the path ends up with the same operationId values, but operationId must be unique.
Encoding $ref values
If the characters ~ and / are present in node names (as in case of path names, e.g. /ab) they must be encoded: ~ as ~0, and / as ~1:
/ab → ~1ab → $ref: '#/paths/~1ab'
/foo/bar → ~1foo~1bar → $ref: '#/paths/~1foo~1bar'
/ab~cd → ~1ab~0cd → #/paths/~1ab~0cd
Additionally, { } and other characters not allowed in URI fragment identifiers (RFC 3986, section 3.5) need to be percent-encoded. For example, { becomes %7B, and } becomes %7D.
/{zzz}
→ ~1{zzz} ( / replaced with ~1)
→ ~1%7Bzzz%7D (percent-encoded)
→ $ref: '#/paths/~1%7Bzzz%7D'
/foo/{zzz}
→ ~1foo~1{zzz} ( / replaced with ~1)
→ ~1foo~1%7Bzzz%7D (percent-encoded)
→ $ref: '#/paths/~1foo~1%7Bzzz%7D'
Note that you need to encode just the path name and not the #/paths/ prefix.
TL;TR: Is (first) question mark in URL part of query or is is just a separator followed by query?
The RFC 1738, section 3.3, suggests that the "?" (question mark) is not part of the query string, but just separates it from the path:
http://<host>:<port>/<path>?<searchpart>
Grammar presented in the RFC 3986, Appendix A., also indicate the "?" is not part of the actual query string:
URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
Now, let's consider two URLs:
http://server.com/api/item.json
http://server.com/api/item.json?
Are they equivalent or distinct?
Is it valid to distinguish them and use to identify two different resources?
tl;dr:
The ? is not part of the query component.
The URIs are not equivalent, because one has no query component, while the other one has an empty query component.
The URI standard (STD 66) is currently RFC 3986.
Section 6.2. Comparison Ladder describes methods how to test if URIs are possibly equivalent.
In 6.2.3. Scheme-Based Normalization it says:
Normalization should not remove delimiters when their associated component is empty unless licensed to do so by the scheme specification. For example, the URI http://example.com/? cannot be assumed to be equivalent to any of the examples above.
Where "examples above" refers to:
http://example.com
http://example.com/
http://example.com:/
http://example.com:80/
(These 4 URIs are equivalent.)
So http://example.com/api/item.json has no query component, while http://example.com/api/item.json? has an empty query component.