Skip to content

Commit c66e13a

Browse files
committed
docs(examples): add example for Overlay usage
As part of oapi-codegen#1553. This tries to cover a lot of the more complex cases. Plus a fair bit of blurb + info to the README too.
1 parent 3cf49e0 commit c66e13a

File tree

8 files changed

+550
-0
lines changed

8 files changed

+550
-0
lines changed

README.md

+85
Original file line numberDiff line numberDiff line change
@@ -1947,6 +1947,91 @@ If you don't want to do this, an alternate option is to [bundle your multiple Op
19471947

19481948
Check out [the import-mapping example](examples/import-mapping/) for the full code.
19491949

1950+
## Modifying the input OpenAPI Specification
1951+
1952+
Prior to `oapi-codegen` v2.4.0, users wishing to override specific configuration, for instance taking advantage of extensions such as `x-go-type` would need to modify the OpenAPI specification they are using.
1953+
1954+
In a lot of cases, this OpenAPI specification would be produced by a different team to the consumers (or even a different company) and so asking them to make changes like this were unreasonable.
1955+
1956+
This would lead to the API consumers needing to vendor the specification from the producer (which is [our recommendation anyway](#https-paths)) and then make any number of local changes to the specification to make it generate code that looks reasonable.
1957+
1958+
However, in the case that a consumer would update their specification, they would likely end up with a number of merge conflicts.
1959+
1960+
Now, as of `oapi-codegen` v2.4.0, it is now possible to make changes to the input OpenAPI specification _without needing to modify it directly_.
1961+
1962+
This takes advantage of the [OpenAPI Overlay specification](https://github.com/OAI/Overlay-Specification), which is a stable specification.
1963+
1964+
> [!CAUTION]
1965+
> Beware! Here (may) be dragons.
1966+
>
1967+
> The Overlay specification requires the use of JSON Path, which some users may find difficult to write and/or maintain.
1968+
>
1969+
> We still heavily recommend using Overlay functionality, but would like users to be aware of this.
1970+
>
1971+
> There is a [proposed modification to the specification](https://github.com/OAI/Overlay-Specification/pull/32) which would relax the need for JSON Path as the targeting mechanism.
1972+
1973+
For instance, let's say that we have the following OpenAPI specification, which provides insight into an internal endpoint that we should not be generating any code for (denoted by `x-internal`):
1974+
1975+
```yaml
1976+
openapi: "3.0.0"
1977+
info:
1978+
version: 1.0.0
1979+
title: "Example to indicate how to use the OpenAPI Overlay specification (https://github.com/OAI/Overlay-Specification)"
1980+
paths:
1981+
/ping:
1982+
get:
1983+
responses:
1984+
'200':
1985+
description: pet response
1986+
content:
1987+
application/json:
1988+
schema:
1989+
$ref: '#/components/schemas/Pong'
1990+
delete:
1991+
x-internal: true
1992+
responses:
1993+
'202':
1994+
content: {}
1995+
```
1996+
1997+
If we were to run `oapi-codegen` with out-of-the-box functionality, this would then lead to the DELETE endpoint being generated, which we don't want.
1998+
1999+
Instead, we can define the following `overlay.yaml`:
2000+
2001+
2002+
```yaml
2003+
overlay: 1.0.0
2004+
info:
2005+
title: Overlay
2006+
version: 0.0.0
2007+
actions:
2008+
- target: $.paths.*[?(@.x-internal)]
2009+
description: Remove internal endpoints (noted by x-internal)
2010+
remove: true
2011+
- target: $.paths.*.*[?(@.x-internal)]
2012+
description: Remove internal endpoints (noted by x-internal)
2013+
remove: true
2014+
```
2015+
2016+
And our configuration file for `oapi-codegen`:
2017+
2018+
```yaml
2019+
# yaml-language-server: $schema=https://raw.githubusercontent.com/deepmap/oapi-codegen/HEAD/configuration-schema.json
2020+
package: api
2021+
output: ping.gen.go
2022+
generate:
2023+
models: true
2024+
gorilla-server: true
2025+
embedded-spec: true
2026+
output-options:
2027+
overlay:
2028+
path: overlay.yaml
2029+
```
2030+
2031+
This then completely removes the DELETE endpoint _before_ we even start to parse the specification in `oapi-codegen`, so it's as if your specification was provided without that endpoint.
2032+
2033+
Check out [the overlay example](examples/overlay/) for the full code, and some more complex examples.
2034+
19502035
## Generating Nullable types
19512036

19522037
It's possible that you want to be able to determine whether a field isn't sent, is sent as `null` or has a value.

examples/overlay/api/api.yaml

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
openapi: "3.0.0"
2+
info:
3+
version: 1.0.0
4+
title: "Example to indicate how to use the OpenAPI Overlay specification (https://github.com/OAI/Overlay-Specification)"
5+
paths:
6+
/ping:
7+
get:
8+
responses:
9+
'200':
10+
description: pet response
11+
content:
12+
application/json:
13+
schema:
14+
$ref: '#/components/schemas/Pong'
15+
delete:
16+
x-internal: true
17+
responses:
18+
'202':
19+
content: {}
20+
/admin/autoscaling:
21+
get:
22+
# this is a method-level `tags`
23+
tags:
24+
- internal
25+
responses:
26+
'200':
27+
content:
28+
application/json:
29+
schema:
30+
type: object
31+
properties:
32+
instances:
33+
type: number
34+
required:
35+
- instances
36+
/healthz:
37+
x-internal: true
38+
get:
39+
responses:
40+
'200':
41+
content: {}
42+
/admin/users/reset-password:
43+
x-internal: true
44+
put:
45+
requestBody:
46+
content:
47+
application/json:
48+
schema:
49+
type: object
50+
properties:
51+
username:
52+
type: string
53+
not_documented:
54+
type: string
55+
format: uuid
56+
x-internal: true
57+
required:
58+
- username
59+
responses:
60+
'200':
61+
content:
62+
application/json:
63+
schema:
64+
type: object
65+
properties:
66+
password:
67+
type: string
68+
not_documented:
69+
type: string
70+
format: uuid
71+
x-internal: true
72+
required:
73+
- password
74+
components:
75+
schemas:
76+
# base types
77+
Pong:
78+
type: object
79+
required:
80+
- ping
81+
properties:
82+
ping:
83+
type: string
84+
example: pong
85+
seed:
86+
type: number
87+
description: The seed for the internal randomness. SHOULD NOT be explained to users
88+
# undocumented and not useful
89+
verbose:
90+
type: boolean
91+
x-internal: true

examples/overlay/api/cfg.yaml

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# yaml-language-server: $schema=../../../configuration-schema.json
2+
package: api
3+
output: ping.gen.go
4+
generate:
5+
models: true
6+
gorilla-server: true
7+
embedded-spec: true
8+
output-options:
9+
overlay:
10+
path: overlay.yaml

examples/overlay/api/generate.go

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package api
2+
3+
//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml api.yaml

examples/overlay/api/impl.go

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package api
2+
3+
import (
4+
"encoding/json"
5+
"net/http"
6+
)
7+
8+
// ensure that we've conformed to the `ServerInterface` with a compile-time check
9+
var _ ServerInterface = (*Server)(nil)
10+
11+
type Server struct{}
12+
13+
func NewServer() Server {
14+
return Server{}
15+
}
16+
17+
// (GET /ping)
18+
func (Server) GetPing(w http.ResponseWriter, r *http.Request) {
19+
resp := OverriddenPong{
20+
Ping: "pong",
21+
}
22+
23+
w.WriteHeader(http.StatusOK)
24+
_ = json.NewEncoder(w).Encode(resp)
25+
}

examples/overlay/api/overlay.yaml

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
overlay: 1.0.0
2+
info:
3+
title: "Example to indicate how to use the OpenAPI Overlay specification (https://github.com/OAI/Overlay-Specification)"
4+
version: 1.0.0
5+
actions:
6+
- target: $.paths.*.*[?([email protected])]
7+
description: Override the servers
8+
update:
9+
servers:
10+
- url: http://localhost:35123
11+
description: The default server.
12+
- target: $.components.schemas.Pong
13+
description: Override the Pong schema to utilise the `x-go-name` to override the generated Go type name
14+
update:
15+
x-go-name: OverriddenPong
16+
17+
- target: "$"
18+
update:
19+
info:
20+
x-overlay-applied: structured-overlay
21+
22+
- target: $.paths['/ping'].get
23+
description: Override the poorly documented internal description for the ping API
24+
update:
25+
description: Check that the API is running OK
26+
27+
- target: $.components.schemas.Pong.properties.seed
28+
description: Hide information about the Seed parameter
29+
remove: true
30+
31+
- target: $.components.schemas.*.*.*[?(@.x-internal)]
32+
description: Remove any internal fields on Schemas (noted by x-internal)
33+
remove: true
34+
35+
- target: $.paths.*.*.requestBody.*.*.schema..[?(@.x-internal)]
36+
description: Remove any internal fields on request bodies (noted by x-internal)
37+
remove: true
38+
39+
- target: $.paths.*.*.responses.*.*.*.schema..[?(@.x-internal)]
40+
description: Remove any internal fields on responses (noted by x-internal)
41+
remove: true
42+
43+
- target: $.paths.*[?(@.x-internal)]
44+
description: Remove internal endpoints (noted by x-internal)
45+
remove: true
46+
47+
- target: $.paths.*.*[?(@.x-internal)]
48+
description: Remove internal endpoints (noted by x-internal)
49+
remove: true
50+
51+
- target: $.paths.*.*[?(@.tags[*] == 'internal')]
52+
description: Remove internal endpoints (noted by internal tag)
53+
remove: true

0 commit comments

Comments
 (0)