Skip to content

Commit

Permalink
Merge branch 'rav/ref_objects_in_params' into dbkr/relations_common_p…
Browse files Browse the repository at this point in the history
…arams
  • Loading branch information
richvdh committed Mar 13, 2024
2 parents 5bdc8ef + 44db164 commit f16d804
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 20 deletions.
1 change: 1 addition & 0 deletions changelogs/internal/newsfragments/1749.clarification
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Templates: add support for reference objects in parameters.
8 changes: 8 additions & 0 deletions layouts/partials/json-schema/resolve-refs.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@
rather than a normal `dict` because with `dict` you can't replace key values:
https://discourse.gohugo.io/t/how-can-i-add-set-and-delete-keys-in-a-dictionary/29661

XXX: This partial should be phased out, and replaced with
`openapi/resolve-ref-object`. OpenAPI 3 doesn't really allow arbitrary JSON
references. As [swagger.io] says: "A common misconception is that `$ref` is
allowed anywhere in an OpenAPI specification file. Actually `$ref` is only
allowed in places where the OpenAPI 3.0 Specification explicitly states that
the value may be a reference."

[swagger.io]: https://swagger.io/docs/specification/using-ref/#allowed-places
*/}}

{{ $schema := .schema }}
Expand Down
2 changes: 1 addition & 1 deletion layouts/partials/openapi/render-api.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

{{/* note that a `paths` entry can be a $ref */}}

{{ $params := dict "endpoint" $endpoint "path" $path }}
{{ $params := dict "endpoint" $endpoint "path" $path "root_schema" $api_data }}

{{ with $path_data.get }}

Expand Down
4 changes: 3 additions & 1 deletion layouts/partials/openapi/render-operation.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* `endpoint`: the endpoint
* `operation_data`: the OpenAPI data for the operation
* `path`: the path where this definition was found, to enable us to resolve "$ref"
* `root_schema`: the root schema object where this definition was found, to enable us to resolve local "$ref" references

This template renders the operation as a `<section>` containing:

Expand All @@ -22,6 +23,7 @@
{{ $endpoint := .endpoint }}
{{ $operation_data := .operation_data }}
{{ $path := .path }}
{{ $root_schema := .root_schema }}
{{ $anchor := anchorize $endpoint }}

<section class="rendered-data http-api {{ $method }}">
Expand Down Expand Up @@ -80,7 +82,7 @@ <h1 id="{{ lower $method }}{{ $anchor }}">
</table>

<hr/>
{{ partial "openapi/render-request" (dict "parameters" $operation_data.parameters "request_body" $operation_data.requestBody "path" $path "anchor_base" $anchor ) }}
{{ partial "openapi/render-request" (dict "parameters" $operation_data.parameters "request_body" $operation_data.requestBody "path" $path "anchor_base" $anchor "root_schema" $root_schema ) }}
<hr/>
{{ partial "openapi/render-responses" (dict "responses" $operation_data.responses "path" $path "anchor_base" $anchor ) }}

Expand Down
36 changes: 23 additions & 13 deletions layouts/partials/openapi/render-parameters.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
Render the parameters of a given type, given:

* `parameters`: OpenAPI data specifying the parameters
* `type`: the type of parameters to render: "header, ""path", "query"
* `type`: the type of parameters to render: "header", "path", "query"
* `caption`: caption to use for the table
* `path`: the path where this definition was found, to enable us to resolve "$ref"
* `root_schema`: the root schema object where this definition was found, to enable us to resolve local "$ref" references

This template renders a single table containing parameters of the given type.

Expand All @@ -13,14 +15,23 @@
{{ $parameters := .parameters }}
{{ $type := .type }}
{{ $caption := .caption }}

{{ $parameters_of_type := where $parameters "in" $type }}

{{ with $parameters_of_type }}

{{/* build a dict mapping from name->parameter, which render-object-table expects */}}
{{ $param_dict := dict }}
{{ range $parameter := . }}
{{ $root_schema := .root_schema }}
{{ $path := .path }}

{{/* build a dict mapping from name->parameter, which render-object-table expects */}}
{{ $param_dict := dict }}

{{ range $parameter := $parameters }}
{{/*
Per https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#operation-object:
the parameters can be reference objects; resolve them now.
*/}}
{{ $parameter = partial "openapi/resolve-ref-object" (dict
"schema" $parameter
"root_schema" $root_schema
"path" $path
) }}
{{ if (eq $parameter.in $type) }}
{{/*
merge the schema at the same level as the rest of the other fields because that is
what `render-object-table` expects. Put the schema first so examples in it are
Expand All @@ -29,8 +40,7 @@
{{ $param := merge $parameter.schema $parameter }}
{{ $param_dict = merge $param_dict (dict $parameter.name $param )}}
{{ end }}

{{/* and render the parameters */}}
{{ partial "openapi/render-object-table" (dict "title" $caption "properties" $param_dict) }}

{{ end }}

{{/* and render the parameters */}}
{{ partial "openapi/render-object-table" (dict "title" $caption "properties" $param_dict) }}
30 changes: 25 additions & 5 deletions layouts/partials/openapi/render-request.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* `parameters`: OpenAPI data specifying the parameters
* `request_body`: OpenAPI data specifying the request body
* `path`: the path where this definition was found, to enable us to resolve "$ref"
* `root_schema`: the root schema object where this definition was found, to enable us to resolve local "$ref" references
* `anchor_base`: a prefix to add to the HTML anchors generated for each object

This template renders:
Expand All @@ -17,6 +18,7 @@
{{ $parameters := .parameters }}
{{ $request_body := .request_body }}
{{ $path := .path }}
{{ $root_schema := .root_schema }}
{{ $anchor_base := .anchor_base }}

<h2>Request</h2>
Expand All @@ -26,10 +28,28 @@ <h2>Request</h2>
{{ if $parameters }}
<h3>Request parameters</h3>

{{ partial "openapi/render-parameters" (dict "parameters" $parameters "type" "header" "caption" "header parameters") }}
{{ partial "openapi/render-parameters" (dict "parameters" $parameters "type" "path" "caption" "path parameters") }}
{{ partial "openapi/render-parameters" (dict "parameters" $parameters "type" "query" "caption" "query parameters") }}

{{ partial "openapi/render-parameters" (dict
"parameters" $parameters
"type" "header"
"caption" "header parameters"
"path" $path
"root_schema" $root_schema
) }}
{{ partial "openapi/render-parameters" (dict
"parameters" $parameters
"type" "path"
"caption" "path parameters"
"path" $path
"root_schema" $root_schema
) }}
{{ partial "openapi/render-parameters" (dict
"parameters" $parameters
"type" "query"
"caption" "query parameters"
"root_schema" $root_schema
"path" $path
"root_schema" $root_schema
) }}
{{ end }}

{{ if $request_body }}
Expand All @@ -53,7 +73,7 @@ <h3>Request body</h3>
{{/*
Show the content types and description.
*/}}
{{ $mimes := slice }}
{{ $mimes := slice }}
{{ range $mime, $body := $request_body.content }}
{{ $mimes = $mimes | append $mime }}
{{ end }}
Expand Down
74 changes: 74 additions & 0 deletions layouts/partials/openapi/resolve-ref-object.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
{{/*

Handles OpenAPI "Reference Objects".

Reference objects are JSON objects with a single property, `$ref` (and
optionally a `summary` and `description`). This partial resolves the reference
and returns the expanded object.

The input parameter is a dict with the following keys:

* `schema`: A schema object to check for $ref properties.

* `path`: The path of the schema file containing the (potential) ref; used for resolving
relative references.

* `root_schema`: The top-level schema which contains the potential ref; use for resolving `#/`
references.

Ref: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#reference-object.

*/}}

{{ $schema := .schema }}
{{ $path := .path }}
{{ $root_schema := .root_schema }}

{{ $ret := $schema }}

{{ $ref_value := index $schema "$ref"}}
{{ if $ref_value }}
{{ $ref_url := urls.Parse $ref_value }}

{{ if ne $ref_url.Path "" }}
{{/* Reference to a different file: load it */}}
{{ $full_path := path.Join $path $ref_url.Path }}
{{ $without_ext := replaceRE "\\.[^\\.]*$" "" $full_path }}
{{ $pieces := split $without_ext "/" }}
{{ $ret = index site.Data $pieces }}
{{ else }}
{{ $ret = $root_schema }}
{{ end }}

{{ if ne $ref_url.Fragment "" }}
{{/*
Per https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#relative-references-in-uris:

> If a URI contains a fragment identifier, then the fragment should
> be resolved per the fragment resolution mechanism of the
> referenced document. If the representation of the referenced
> document is JSON or YAML, then the fragment identifier SHOULD be
> interpreted as a JSON-Pointer as per RFC6901.

RFC6901, in a nutshell, says the pointer is a series of keys
separated by `/`. We strip off the leading `/` and use the
subsequent keys as indexes.
*/}}

{{ $keys := split (strings.TrimPrefix "/" $ref_url.Fragment ) "/" }}
{{ $ret = index $ret $keys }}
{{ end }}

{{/*
OpenAPI spec says that "summary" and "description" from the reference object override
the values from the referenced component.
*/}}
{{ if isset $schema "summary" }}
{{ $ret = merge $ret (dict "summary" $schema.summary) }}
{{ end }}
{{ if isset $schema "description" }}
{{ $ret = merge $ret (dict "description" $schema.summary) }}
{{ end }}
{{ end }}

{{ return $ret }}

0 comments on commit f16d804

Please sign in to comment.