Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions .github/workflows/gh-pages-connexion-101.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Converts connexion-101 notebooks to reveal.js slide decks and deploys them
# to the gh-pages branch under connexion-101/.
#
# Other top-level directories in gh-pages (docker-101/, …) are never touched.
# The connexion-101/ directory is always wiped and recreated from scratch.
#
# After the first run, enable GitHub Pages in:
# Settings → Pages → Source: gh-pages branch / (root)
# The slides will be available at:
# https://ioggstream.github.io/python-course/connexion-101/
name: Deploy connexion-101 to GitHub Pages
on:
push:
branches: [main]
paths:
- 'connexion-101/**'
workflow_dispatch:
permissions:
contents: write
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: '3.14'
cache: pip
- name: Install tox
run: pip install tox
- name: Build slides
run: |
cd connexion-101 && tox -e make
mkdir -p ../_site
cp notebooks/*.slides.html ../_site/
cp notebooks/custom.css ../_site/ 2>/dev/null || true
- name: Generate index.html
run: |
python3 - <<'EOF'
import os, glob
files = sorted(glob.glob("_site/*.slides.html")) # produced by tox -e make
items = "\n".join(
f' <li><a href="{os.path.basename(f)}">{os.path.basename(f)}</a></li>'
for f in files
)
html = (
"<!DOCTYPE html>\n<html lang=\"en\">\n"
"<head><meta charset=\"utf-8\"><title>connexion-101</title></head>\n"
"<body>\n<h1>connexion-101</h1>\n<ul>\n"
+ items +
"\n</ul>\n</body>\n</html>\n"
)
with open("_site/index.html", "w") as fh:
fh.write(html)
EOF
# clean: true → wipes connexion-101/ before deploying (scratch rebuild)
# Files outside connexion-101/ in gh-pages are never modified.
- uses: JamesIves/github-pages-deploy-action@d92aa235d04922e8f08b40ce78cc5442fcfbfa2f # v4
with:
branch: gh-pages
folder: _site
target-folder: connexion-101
clean: true
2 changes: 1 addition & 1 deletion connexion-101/000-intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ all the course under `/code`.
└── startup # startup files for jupyter, don't touch ;)
```

## Customizing the flask app
## Customizing the app

To simplify things, during the training we'll run the connexion-flask app with the `connexion run` command.
You can always provide a custom `__main__.py` like you normally do with your flask app (eg: enable TLS, ...).
Expand Down
15 changes: 2 additions & 13 deletions connexion-101/000-teaser.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,7 @@ Author: <roberto.polli@par-tec.it>

---

## Agenda

- 15' Contract-First or Code-First?
- 15' API Canvas Design Methodology
- 15' Introducing OpenAPI, JSON Schema and service HTTP headers

break

- 15' Assisted API Design (with Spectral and validation tools)
- 15' Secure schema modeling

### Hints
## Hints

- **Type in** exercises so you can learn from your mistakes
- If your notebook get stuck, **restart the kernel and run all** cells
Expand Down Expand Up @@ -101,4 +90,4 @@ cat generated_model.py

And some tools to visually navigate API Schemas:

- [Schema Editor](https://teamdigitale.github.io/dati-semantic-schema-editor/)
- [Schema Editor](https://teamdigitale.github.io/dati-semantic-schema-editor/latest/#url=https://raw.githubusercontent.com/ioggstream/python-course/refs/heads/main/connexion-101/notebooks/oas3/person.yaml)
91 changes: 56 additions & 35 deletions connexion-101/010-interoperable-apis.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,22 @@
# Interoperable APIs

Writing an API seems simple ... but what happens when
you have to maintain tens of APIs across different organizations, with different teams and frameworks?
Writing APIs seems simple ... but what happens when
you have to maintain tens of APIs across different organizations, with different teams and frameworks?

The Italian Government - like other Countries - is standardizing REST APIs
to create an uniform developer experience for software provided by its:
This workshop is about creating an interoperable API ecosystem
with an uniform developer experience
for country-wide contexts.

---

In particular, this is based on the Italian public administration context, which includes:

- 20 Regions
- 8_000 municipalities
- 20_000 local and central agencies
- cross-border services with the European Union

At the core of this interoperability strategy we have:

- API First Approach based on OpenAPI v3
- HTTPS everywhere
- Service Management with standardized throttling and circuit-breaker patterns
- Standardized approach to metrics

[See Slides](https://docs.google.com/presentation/d/1L6R4ZKhLoZAPEmai1KSED1nrq0GNrx3-TU53sGhfrO8/edit#slide=id.g3aa6058ea8_0_0)

- [Do we still need SOAP?](https://www.youtube.com/watch?v=9a2n8s1j5l0)
- [Extending HTTP for fun and non-profit](https://ep2020.europython.eu/talks/9mbcXTU-extending-http-for-fun-and-non-profit/)
- [Designing Secure APIs](https://ep2021.europython.eu/media/conference/slides/P8PaA9g-designing-secure-apis.pdf)
- [Self-explaining APIs](https://ep2021.europython.eu/media/conference/slides/9a2n8s1j5l0-self-explaining-apis.pdf)

## Agenda

In this training we'll show how to:

- model interoperable APIs
- leverage interoperability by reuse

We'll use [connexion](https://github.com/spec-first/connexion), a python framework which streamlines API creation.
---

## Interoperability requirements

Expand All @@ -40,7 +25,7 @@ An API ecosystem starts with communication requirements such as:
- Reliability & Security (e.g., CIA triad: Confidentiality, Integrity and Availability)
- Consistent Design & Schema Standardization

See also [Extending HTTP for fun and non-profit](https://ep2020.europython.eu/talks/9mbcXTU-extending-http-for-fun-and-non-profit/)
----

Basic standardization features to support these requirements include:

Expand All @@ -52,6 +37,9 @@ Basic standardization features to support these requirements include:

- Availability strategy based on a distributed circuit-breaker and throttling patterns;

<!-- Let's see how to manage such requirements -->
---

## REST and RPC

The historical API approach was to view any interaction like a function call.
Expand All @@ -62,42 +50,56 @@ used by:
- SOAP web services, that use XML as a data format and HTTP as a transport protocol;
- gRPC, that uses HTTP/2 as a transport protocol and Protocol Buffers as a data format.

----

The widespread of HTTP as a distributed computation protocol, and the rise of data give birth to REST.

REST, aka REpresentation State Transfer, is not a protocol,
but an architectural style which mimics the distributed characteristics of the web.

----

In REST, everything is a [resource](https://ietf.org/rfc/rfc9110.html#name-resources):

- identified by an Uniform Resource Locator URL;
- conveyed by a `representation`. A resource could be represented as `application/json` or as [`application/xml`](https://tools.ietf.org/html/rfc7303), in different languages (see `Content-Language`) and differently encoded (see `Content-Encoding`);
- identified by an **Uniform Resource Locator** (URL);
- conveyed by a **representation**.
A resource can be represented in different formats, such as `application/json` or [`application/xml`](https://tools.ietf.org/html/rfc7303),
in different languages (see `Content-Language`) and differently encoded (see `Content-Encoding`);
- whose state is transferred between an Origin Server and a User Agent (see RFC9110);

----

There are no "functions" but everything is modeled as a resource.
Moreover all the HTTP semantics ([RFC9110](https://datatracker.ietf.org/doc/html/rfc9110)) applies, including idempotent and non-idempotent methods and caching.

----

The REST architectural style **leverages the distributed nature of the web**
and the features of HTTP which are redesigned with REST in mind (see RFC911x).

**REST & Public services**: while REST is not a silver bullet, public services are usually about data:
this makes REST a good fit for public service modeling.
this makes REST a good fit for modeling public services.

Moreover a semantic approach to URIs simplifies routing and auditing
based on http status, method and path.

## REST API & HTTP Standards
---

For the rest of the course, we will give for granted
that you are familiar with the HTTP protocol.
## REST API & HTTP Standards

Just for a quick recap, here are some examples of HTTP requests and responses.
While we assume
that you are familiar with the HTTP protocol,
but just for a quick recap, here are some examples of HTTP requests and responses.

HTTP messages are composed by:

- a start line (request line or status line)
- headers (includes metadata about the representation, such as content type, content language, content encoding, etc.)
- an optional content

----


### HTTP Message Examples

A request to <http://api.example.com/datetime/v1/now>
Expand All @@ -109,6 +111,8 @@ Host: api.example.com
Accept: application/json
```

----

Response with a JSON representation of the current date and time:

```http
Expand All @@ -121,6 +125,8 @@ Content-Length: 30
}
```

----

The same resource could have more representations,
in different formats ...

Expand All @@ -137,6 +143,8 @@ Content-Type: text/plain
2024-06-01T12:00:00Z
```

----

Security features are usually implemented using HTTP functionalities
such as headers and status codes.

Expand All @@ -155,6 +163,8 @@ HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer
```

----

TODO: http ongoing work on API description:

- Integrity: Digest, HTTP Signatures, Unencoded Digest, etc.
Expand All @@ -163,8 +173,19 @@ TODO: http ongoing work on API description:
- Security: QUERY method
- Efficiency: Resumable uploads

https://datatracker.ietf.org/wg/httpapi/about/
<https://datatracker.ietf.org/wg/httpapi/about/>

- lifecycle: Deprecation, Sunset, etc.
- catalog: RFC 9727
- YAML media type

---

## References

[See Slides]

- [Do we still need SOAP?](https://docs.google.com/presentation/d/1AqVoCmqVF4TrIw_QowEzdWh8F42wNZuHnIFyP3H2Qc0) [video](https://www.youtube.com/watch?v=9a2n8s1j5l0)
- [Extending HTTP for fun and non-profit](https://ep2020.europython.eu/talks/9mbcXTU-extending-http-for-fun-and-non-profit/)
- [Designing Secure APIs](https://ep2021.europython.eu/media/conference/slides/P8PaA9g-designing-secure-apis.pdf)
- [Self-explaining APIs](https://ep2021.europython.eu/media/conference/slides/9a2n8s1j5l0-self-explaining-apis.pdf)
12 changes: 6 additions & 6 deletions connexion-101/Makefile
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
FILES=$(wildcard [0-9]*.md)
BOOKS = $(patsubst %.md,notebooks/%.ipynb,$(FILES))
SLIDES = $(patsubst %.ipynb,%.html,$(BOOKS))
SLIDES = $(patsubst %.ipynb,%.slides.html,$(BOOKS))


all: $(BOOKS)
@echo $(BOOKS) $(SLIDES)
all: $(SLIDES)
@echo $(SLIDES)

notebooks/%.ipynb: %.md

notedown --to notebook $^ > $@

%.html: %.ipynb
%.slides.html: %.ipynb

jupyter nbconvert --to slides $^ --post serve
jupyter nbconvert --to slides $<

clean:
rm notebooks/*.ipynb -f
rm -f notebooks/*.ipynb notebooks/*.slides.html
5 changes: 4 additions & 1 deletion connexion-101/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ break
10' Rate Limiting
10' Caching
10' Closing remarks
Preparation

### Preparation

The workshop requires:

Expand All @@ -56,6 +57,8 @@ The workshop requires:
Sources, docker-compose and further materials
will be available on github.com before the date.

We'll use [connexion](https://github.com/spec-first/connexion), a python framework which streamlines API creation.

## Local Setup

This course is based on Docker and Docker compose. As long as you have Docker
Expand Down
2 changes: 2 additions & 0 deletions connexion-101/tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ commands =
deps =
setuptools
git+https://github.com/ioggstream/notedown
jupyter
nbconvert
passenv =
SHOW_SOLUTIONS
allowlist_externals =
Expand Down