Files
api-python-001/README.md
T
hcornet 1121efecd5
build / build (push) Successful in 57s
add site web
2026-09-21 18:27:03 +02:00

64 lines
3.0 KiB
Markdown

# api-python-001
Réécriture en Python (FastAPI + SQLite) de [afuh/rick-and-morty-api](https://github.com/afuh/rick-and-morty-api)
(Node.js/Express + MongoDB) — https://api-python-001.tips-of-mine.com
## Correspondance avec l'original
| Original (Node.js) | Ici (Python) |
|---|---|
| `server.js` (Express) | `app/main.py` (FastAPI) |
| `routes/` + `handlers/` | `app/routers/` (+ `common.py` : pagination, filtres, ids multiples) |
| `models/` (Mongoose / MongoDB) | `app/models.py` (SQLAlchemy / SQLite) |
| `utils/helpers.js` (messages) | `app/errors.py` |
| lecture seule | + POST / PUT, DELETE protégé par `X-API-Key` |
| `images/` servies sur `/api/character/avatar/N.jpeg` | idem, fichiers envoyés par upload dans `data/avatars` |
| — | site web de consultation (`/`, Jinja2, sans JavaScript) |
| `graphql/` | chantier suivant |
## Endpoints
| Méthode | Chemin |
|---|---|
| GET | `/api` — index des ressources |
| GET | `/api/{character,location,episode}` — 20 par page, `?page=N` + filtres |
| GET | `/api/{ressource}/1`, `/1,2,3`, `/[1,2,3]` |
| POST | `/api/{ressource}` — `id` et `created` facultatifs (conservés si fournis) |
| PUT | `/api/{ressource}/{id}` — remplacement complet (`id`/`created` du corps ignorés) |
| DELETE | `/api/{ressource}/{id}` — en-tête `X-API-Key` |
| PUT | `/api/character/{id}/avatar` — corps brut JPEG/PNG (2 Mo max), `X-API-Key` ; met à jour `image` |
| GET | `/api/character/avatar/{id}.jpeg` (ou `.png`) |
| GET | `/health`, `/hello`, `/docs` |
Filtres (partiels, insensibles à la casse) : character `name status species type gender`,
location `name type dimension`, episode `name episode`.
## Format et relations
Réponses identiques à l'original, plus un champ `modified` (date de dernière modification, égale à `created` tant que l'objet n'a pas été modifié) ; une ressource lue en GET peut être renvoyée telle quelle en POST.
Les URL (`origin`, `location`, `episode`, `residents`) sont décodées sur `/api/<ressource>/<id>`, quel que soit l'hôte.
- `character.episode` ↔ `episode.characters` : une seule relation. Le champ `characters` d'un épisode en entrée est ignoré.
- `location.residents` : liste saisie telle quelle (ordre conservé), indépendante de `character.location`.
**Ordre d'import (n8n)** : locations → episodes → characters → avatars.
## Site web
`/` accueil, `/characters`, `/locations`, `/episodes` (listes paginées + filtres) et leurs fiches `/<ressource>/<id>`.
Rendu serveur sans JavaScript, contenu échappé et en-tête CSP strict (les données sont saisissables via l'API).
## CI/CD
`.gitea/workflows/build.yml` : tests (étape `test` du Dockerfile) puis push Harbor
`${HARBOR_REGISTRY}/api-python-001/api-python-001` — `main` → `latest` + `sha-xxx`, tag `v1.2.3` → `1.2.3`, `1.2`.
## Déploiement SLDOKP03
```bash
mkdir -p /opt/api-python-001/data && cd /opt/api-python-001
# copier docker-compose.yml et .env.example -> .env
chown 10001:10001 data
docker compose pull && docker compose up -d
```