OpenAPI encoding refs for non-URI-safe strings [duplicate] - openapi

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

How to make UriParameter as optional in RAML 1.0

There is a scenario for example as in any Application Controller while exposing a rest api we can make PathParams/UriParams as optional at controller level, so it wouldn't required always for client to pass it. Now I want to achieve same at RAML level. I can see their documentation that says like this.
"Although a URI parameter MAY be explicitly specified as optional, it
SHOULD be required when surrounded directly by slashes (/). In this
case, the URI parameter constitutes a complete URI path fragment, for
example .../{objectId}/.... It usually makes no sense to allow a URI
to contain adjacent slashes, enclosing no characters, for example,
...//.... Therefore, a URI parameter SHOULD be specified as optional
only when it appears adjacent to other text. For example,
/people/~{fieldSelectors} indicates that URI parameter
{fieldSelectors} can be blank, and therefore optional, which implies
that /people/~ is a valid relative URI."
That does give sense that we can try with combination of letter e,g /{someLetter}{uriParam} .. at end of resource Url. I did try this way but it always mention that "resouce not found"
Issue is just related to RAML configuration. for example this is sample resource url for which I have to add url param.
/test-api/{testId}
Now I want to keep it the client decision to either pass UriParameter or not.
This is sample RAML code I am trying.
/test-api/{testId}:
uriParameters:
testId?: string
/test-api/{testId}:
uriParameters:
testId: string
required: false
/test-api{testId}:
uriParameters:
testId: string
Now all three approaches aren't working.
1st approach simply making testId as optional using '?'. But if I skip UriParam it shows that no resource found for this.
2nd approach with required: false also not working looks like RAML is ignoring this validation it always expect even a single '/' from me after /test-api
3rd approach isn't working because it again expect me to put UriParam otherwise consider default one.
To subscribe to the automatic insertion of the URI parameter in RAML 1.0 make this change:
/test-api:
/{testId}:
uriParameters:
testId:
description: Id of test
type: string
required: false
get:
description: return test
responses:
200:
body:
application/json:
example: { "message": "success" }
put:
description: update test
responses:
200:
body:
application/json:
example: { "message": "success" }
delete:
description: remove test
responses:
200:
body:
application/json:
example: { "message": "success" }

Does OpenAPI 3 allow duplicate parameter names but in different locations (path/query/header)?

I am not sure if I understand the specification correctly. For example, this states that a unique parameter is defined by a combination of its name and location.
Does that mean I can have a path parameter called "hello", a query parameter called "hello", and a header called "hello" all at the same time?
Does that mean I can have a path parameter called "hello", a query parameter called "hello", and a header called "hello" all at the same time?
Yes - because path/query/header parameters go into different parts of an HTTP request.
GET /path/hello/subpath?hello=value <-- path and query
Host: example.com
hello: 123 <-- HTTP header

Swagger Open api : add link to schema in description [duplicate]

I'm writing a Swagger specification for an future public API that requires a very detailed and clean documentation. Is there a way to reference/link/point to another endpoint at some other location in the swagger.yml file?
For example, here is what I am trying to achieve:
paths:
/my/endpoint:
post:
tags:
- Some tag
summary: Do things
description: >
This endpoint does things.
See /my/otherEndpoint for stuff # Here I would like to have some kind of hyperlink
operationId: doThings
consumes:
- application/json
produces:
- application/json
parameters:
...
responses:
...
/my/otherEndpoint: # This is the endpoint to be referenced to
get:
...
I have found that $ref does not help because it simply replaces itself with the contents of the reference.
Can Swagger do such a thing?
Swagger UI provides permalinks for tags and operations if it's configured with the deepLinking: true option. These permalinks are generated based on the tag names and operationId (or if there are no operationId - based on the endpoint names and HTTP verbs).
index.html#/tagName
index.html#/tagName/operationId
You can use these permalinks in your Markdown markup:
description: >
This endpoint does things.
See [/my/otherEndpoint](#/tagName/myOtherEndpointId) for stuff
Notes:
Markdown links (such as above) currently open in a new browser tab (as with target="_blank") - see issue #3473.
HTML-formatted links foobar currently don't work.
Swagger Editor does not support such permalinks.

Can OpenAPI schema names have "/" in them?

I am consuming an API that uses string like "foo/bar" to identify (discriminate) JSON objects.
A $ref like $ref: '#/components/schemas/foo/bar' gives me errors.
Is this naming supported? I want to use leverage these properties provided by the API in order to use discrimination to pick the most appropriate component schema.
I am using OpenAPI 3.0.1.
No.
OpenAPI 3.0 component names (including schema names) can only contain these characters:
a-z A-Z 0-9 - . _
(Source)
However, there are no restrictions on property names in schemas, so / can be used in property names:
components:
schemas:
MySchema:
type: object
properties:
foo/bar: # <-----
type: string

Idiomatic way to overcome difficulties with `#extension = 'html'` in AEM 6.3 Sightly/HTL?

AEM's HTL (f.k.a. Sightly) has a special idiom for reformatting URL properties, e.g.
<a href="${properties.path # extension = 'html'}">
The purpose of this idiom is two-fold
to append .html to internal links authored via a pathbrowser field
to apply resource mappings which have been configured to strip /content/projectname
Unfortunately this well-intentioned feature has several problems:
It won't work with resource links, e.g. a PDF file in the DAM.
It won't work with external links that don't end in .html.
It escapes the "&" in URLs containing query string params, breaking the link.
My team is now tasked with fixing dozens of defects caused by over-use of this extension = 'html' trick, and we would like to fix them all consistently and quickly with a minimum risk of regressions.
Is there a quick fix, preferrably something that can be repeated via mindless search/replace of every occurrence of extension = 'html'?
I can suggest a combination of uri context and adding .html extension to resource URLs from server side.
It won't work with resource links, e.g. a PDF file in the DAM.
Use # context = 'uri', default context for href and src attributes and does not explicitly add .html extension.
Input -
Resource Link uses default uri context.
Output -
Resource Link
On any other html attribute, use an attribute context - # context='attribute'
Input -
<div data-link="${'/content/dam/repl/en.pdf' # context='attribute'}"/>
Output -
<div data-link="/content/dam/repl/en.pdf"/>
It won't work with external links that don't end in .html.
It escapes the "&" in URLs containing query string params, breaking the link.
Again use # context = 'uri', does not escape & in URLs, works fine with selectors and # params as well. Added advantage of XSS protection.
Input -
URI context
Output -
URI context
To append .html to internal resource URLs
You cannot use # extension and # context together in the same element.
You could append .html like this Title or better way would be to address this at the sling model level, a util method like this maybe.
public static String getUrl(String link, String extension, ResourceResolver resourceResolver) {
String updatedLink = "";
if (link != null) {
Resource pathResource = resourceResolver.getResource(link);
// check if resource exists
if (pathResource != null) {
// append .html
updatedLink = resourceResolver.map(link) + extension;
}
}
return updatedLink;
}
Side note: Avoid # context='unsafe' for obvious reasons - completely disables xss protection.
Check this for the available context expression options.