Skip to content

Commit 867af76

Browse files
authored
Fix: #111. Add gh-pages (#112)
* fix url * Fix merge keys. * Throttling middleware. * Consolidation. * format yaml * Security: Availability, Integrity, Confidentiality * Reorganize CIA. Valid OAS. * more stuff
1 parent ff24e9d commit 867af76

44 files changed

Lines changed: 2731 additions & 575 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

connexion-101/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ core*
99
*_python_intro.ipynb
1010
.tox
1111
*generated*
12+
*deleteme*

connexion-101/034-schema-design.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ The `$ref` value is an URI.
128128
components:
129129
schemas:
130130
Problem:
131-
$ref: 'https://teamdigitale.github.io/openapi/0.0.5/definitions.yaml#/schemas/Problem'
131+
$ref: 'components.oas3.yaml#/components/schemas/Problem'
132132
```
133133

134134
> Note: Schema registries guarantee consistency: if a shared schema adds a required field,
@@ -369,7 +369,7 @@ to ensure consistent errors
369369
components:
370370
schemas:
371371
Problem:
372-
$ref: 'https://teamdigitale.github.io/openapi/0.0.5/definitions.yaml#/schemas/Problem'
372+
$ref: 'components.oas3.yaml#/components/schemas/Problem'
373373
```
374374

375375
----

connexion-101/040-01-connexion-writing-operationid.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ components:
149149
150150
----
151151
152-
Or just `$ref` the `Retry-After` defined in <https://teamdigitale.github.io/openapi/0.0.5/definitions.yaml#/headers/Retry-After>
152+
Or just `$ref` the `Retry-After` defined in <components.oas3.yaml#/components/headers/Retry-After>
153153

154154
Modify [api.py:get_status](/edit/notebooks/oas3/api.py) such that:
155155

connexion-101/050-reusing-and-bundling.md

Lines changed: 78 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,45 @@ See the [OAS website](https://github.com/OAI/OpenAPI-Specification).
4141
### Exercise: replacing definitions with $refs
4242

4343
- Open [ex-05-01-bundle.yaml](/edit/notebooks/oas3/ex-05-01-bundle.yaml)
44-
- replace as many definitions as possible with references from the shared [components.oas3.yaml]().
44+
- replace as many definitions as possible with references from the shared
45+
<https://raw.githubusercontent.com/ioggstream/python-course/refs/tags/v2026.05.1/connexion-101/notebooks/oas3/components.oas3.yaml>
46+
- "resolve" the OAS file as JSON, to ensure that anchors are removed.
4547

4648
```python
49+
import yaml, json
50+
d = yaml.safe_load(stream=open("oas3/ex-05-01-bundle-ok.yaml"))
51+
json.dump(d, open("oas3/bundle.json", "w+"))
52+
```
53+
54+
----
55+
56+
### Exercise: create a bundle from the previous file
57+
58+
If you have docker, you can use the Redocly CLI to create a bundle from the previous file.
59+
60+
A bundle is a single file containing all the resolved references. It can be used to share your API definition with others, or to deploy it to a server.
61+
62+
```bash
4763
# Exercise: create a bundle from the previous file with
64+
docker run --rm -v $PWD:/app
65+
docker run --rm -v $PWD:/app docker.io/redocly/cli@sha256:78fa111b6c84522383d419a0631c984aefa76c5fbd39d8904a201b86e3b44168 bundle /app/oas3/bundle.json --output /app/bundle.yaml
4866
```
4967

50-
### YAML anchors are your friends
68+
---
69+
70+
## YAML as a template engine
71+
72+
YAML can be used as a template engine for your OAS files. It allows you to define reusable components and reference them in your OAS file.
73+
74+
```mermaid
75+
graph TD
76+
77+
YAML[YAML OAS source]
78+
-->|processing| JSON[JSON OAS with $refs]
79+
-->|bundling| --> BUNDLE[OAS with resolved $refs]
80+
```
81+
82+
----
5183

5284
YAML has a nice feature, named **anchors**. They allow to define and reference
5385
given portions of a YAML file.
@@ -58,9 +90,10 @@ a: &this_is_an_anchor foo
5890

5991
# *star dereferences the anchor
6092
b: *this_is_an_anchor
61-
6293
```
6394
95+
----
96+
6497
See [anchors.yaml](/edit/notebooks/anchors.yaml)
6598
6699
```python
@@ -73,6 +106,9 @@ content = Path('anchors.yaml').read_text()
73106
print(content)
74107
```
75108

109+
----
110+
111+
Check anchor content:
76112

77113
```python
78114
ret = yaml.safe_load(content)
@@ -83,19 +119,48 @@ print(ret['foo'])
83119
print(ret['bar'])
84120
```
85121

86-
{'name': 'Everyone has same name', 'age': 10}
87-
{'name': 'Everyone has same name', 'age': 20}
122+
----
88123

89124
### Using YAML anchors in OAS3
90125

126+
If you have a set of constants in your API definition
127+
e.g., maximum number of items in a list, or common responses, you can use YAML anchors to define them once and reuse them everywhere.
128+
129+
```yaml
130+
openapi: 3.0.0
131+
...
132+
components:
133+
schemas:
134+
MaxItems:
135+
type: integer
136+
maximum: &max-items 100
137+
Limit:
138+
type: integer
139+
maximum: *max-items # Reuses the max-items anchor
140+
...
141+
```
142+
143+
----
144+
145+
### YAML merge keys
146+
147+
Merge keys are a special feature of YAML that allows you to merge
148+
the content of one or more dicts.
149+
This can be useful when you have a set of common properties that you want to reuse across multiple objects.
150+
151+
:warning: YAML merge keys are not supported by all YAML parsers, and they are not part of the OAS specification. While they are widely used on the web, they are formally deprecated in YAML 1.2.
152+
Nonetheles, I find them very useful to avoid using a specific template engine to generate OAS files and manage safely model composition without recurring to `allOf` and `oneOf` keywords, which might cause nesting and readability issues.
153+
154+
155+
91156
As every operation may have a set of predefined responses, namely:
92157

93158
- 503 Service Unavailable
94159
- 429 Too Many Requests
95160

96161
You can put them in an `x-` custom parameter.which will be ignored by the OAS spec parser.
97162

98-
```
163+
```yaml
99164
x-common-responses: &common-responses
100165
503ServiceUnavailable:
101166
$ref: ...
@@ -104,9 +169,11 @@ x-common-responses: &common-responses
104169

105170
```
106171

172+
----
173+
107174
Then use the `<<:` keyword and `*anchor_name` to reference them.
108175

109-
```
176+
```yaml
110177
paths:
111178
/status:
112179
get:
@@ -120,10 +187,8 @@ paths:
120187
...
121188
```
122189
123-
## NOTE: ANCHORS ARE PROCESSED BY THE YAML PARSER, NOT BY OAS
124-
125-
## OAS knows nothing about ANCHORS
190+
:warning: ANCHORS ARE PROCESSED BY THE YAML PARSER, NOT BY OAS
191+
:warning: OAS knows nothing about ANCHORS
126192
127-
```python
128-
129-
```
193+
For YAML interoperability considerations
194+
see <https://www.rfc-editor.org/rfc/rfc9512.html>.

connexion-101/060-connexion-authorization-basic.md renamed to connexion-101/060-security-confidentiality.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def get_echo(tz, user=None):
9292
9393
### Test the my_auth implementation
9494
95-
Run the spec in the [terminal](/terminals/1)
95+
Run the spec in the [terminal](/terminals/connexion)
9696
with the usual
9797
9898
```

connexion-101/070-connexion-throttling-headers.md renamed to connexion-101/070-security-availability.md

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
11
# Throttling headers
22

3-
Service management is an essential component of a stable API Ecosystem.
3+
Service management is key for the reliability of an API ecosystem.
44

5-
Basic compontents for service management are communicating:
5+
Basic components for service management communicates:
66

77
- when you are not operational, and explicit
88
how long it will take to be up and running again;
99

1010
- if they are over quota and
1111
prevent overquota via throttling headers.
1212

13-
1413
While it could be annoying to explicitly state that every response
15-
should contain throttling headers, you can use yaml anchors for that!
14+
should contain throttling headers, you can use YAML anchors for that!
1615

17-
```
16+
```yaml
1817
x-commons:
1918
throttling-headers: &throttling-headers
2019
X-RateLimit-Limit:
@@ -30,9 +29,9 @@ x-commons:
3029

3130
Now we can use the anchor in our `get /echo responses`
3231

33-
```
32+
```yaml
3433
paths:
35-
/echo
34+
/echo:
3635
get:
3736
...
3837
operationId: api.get_echo
@@ -59,7 +58,7 @@ Use the `throttling_quota` utilities either:
5958
- or implement your own throttling
6059

6160

62-
```
61+
```python
6362
# Decorate with `throttle`
6463
from oas3.throttling_quota import throttle
6564

@@ -70,7 +69,7 @@ def f(user='foo'):
7069
```
7170

7271

73-
```
72+
```python
7473
# Or write your own using
7574
from oas3.throttling_quota import ThrottlingQuota
7675

@@ -81,11 +80,6 @@ for i in range(4):
8180
print(ret)
8281
```
8382

84-
{'limit': 3, 'remaining': 2, 'reset': 23, 'user': 'user1', 'comment': '2019-07-06T07:57:00'}
85-
{'limit': 3, 'remaining': 1, 'reset': 23, 'user': 'user1', 'comment': '2019-07-06T07:57:00'}
86-
{'limit': 3, 'remaining': 0, 'reset': 23, 'user': 'user1', 'comment': '2019-07-06T07:57:00'}
87-
{'limit': 3, 'remaining': 0, 'reset': 23, 'user': 'user1', 'comment': '2019-07-06T07:57:00'}
88-
8983

9084
Modify [api.py:get_echo](/edit/notebooks/oas3/api.py) such that:
9185

@@ -98,10 +92,9 @@ Modify [api.py:get_echo](/edit/notebooks/oas3/api.py) such that:
9892
- X-RateLimit-Remaining: remaining requests before the quota is consumed
9993

10094

101-
Now [run the spec in a terminal](/terminals/1) using
95+
Now [run the spec in a terminal](/terminals/connexion) using
10296

103-
```
104-
cd /code/notebooks/oas3/
97+
```text
10598
connexion run /code/notebooks/oas3/ex-07-01-throttling-ok.yaml
10699
```
107100

@@ -111,11 +104,6 @@ and try making a request!
111104

112105

113106

114-
```
107+
```python
115108
!curl http://localhost:5000/datetime/v1/echo -kv -ufoo:foo
116109
```
117-
118-
119-
```
120-
121-
```
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Response integrity with Content-Digest
2+
3+
```text
4+
SPEC_FILE=ex-07-02-integrity-ok.yaml uvicorn api_solution:main --reload
5+
```
6+
7+
Service management is not only about availability and quotas.
8+
9+
Clients may also need a simple way to verify that the response body
10+
they received is exactly the one produced by the server.
11+
12+
The HTTP fields `Want-Content-Digest` and `Content-Digest` can be used
13+
for that purpose:
14+
15+
- the client sends `Want-Content-Digest` to ask for a digest in the response;
16+
17+
- the server replies with `Content-Digest`, containing the digest of the
18+
response body.
19+
20+
In this lesson we only focus on describing these headers in the API
21+
contract. The implementation details of generating digests are out of scope.
22+
23+
While it could be annoying to explicitly state these headers every time,
24+
you can define them once in shared components and reuse them from your
25+
operations.
26+
27+
```yaml
28+
components:
29+
parameters:
30+
Want-Content-Digest:
31+
$ref: 'components.oas3.yaml#/components/parameters/Want-Content-Digest'
32+
headers:
33+
Content-Digest:
34+
$ref: 'components.oas3.yaml#/components/headers/Content-Digest'
35+
```
36+
37+
## Requesting response digests
38+
39+
Now we can use these reusable definitions in our `get /echo` operation.
40+
41+
```yaml
42+
paths:
43+
/echo:
44+
get:
45+
parameters:
46+
- $ref: '#/components/parameters/tz'
47+
- $ref: '#/components/parameters/Want-Content-Digest'
48+
responses:
49+
'200':
50+
headers:
51+
Content-Digest:
52+
$ref: 'components.oas3.yaml#/components/headers/Content-Digest'
53+
...
54+
```
55+
56+
### Exercise: document integrity headers
57+
58+
Read the [ex-07-02-integrity-ok.yaml](/edit/notebooks/oas3/ex-07-02-integrity-ok.yaml)
59+
spec and identify:
60+
61+
- where the `Want-Content-Digest` request header is declared;
62+
- where the `Content-Digest` response header is returned;
63+
- how the `get /echo` description explains this behavior to clients.
64+
65+
### Exercise: run the API contract
66+
67+
Run the spec in a terminal using:
68+
69+
```text
70+
connexion run /code/notebooks/oas3/ex-07-02-integrity-ok.yaml
71+
```
72+
73+
Then inspect the API from Swagger UI and try sending a request with
74+
the `Want-Content-Digest` header.
75+
76+
For example:
77+
78+
```python
79+
!curl http://localhost:5000/datetime/v1/echo -kv -ufoo:foo \
80+
-H 'Want-Content-Digest: sha-256=1'
81+
```
82+
83+
Check whether the response documents and exposes a `Content-Digest`
84+
header, and discuss how a client could use it to verify integrity.

0 commit comments

Comments
 (0)