api-tube
API REST en PHP natif (POO) pour gérer des liens de vidéos YouTube.
- PHP natif uniquement : aucun framework, aucune dépendance, aucun Composer
- Stockage SQLite via PDO
Prérequis
- PHP >= 8.1 avec l'extension
pdo_sqlite
Activer l'extension si absente (Debian/Ubuntu) :
sudo apt install php8.5-sqlite3
php -m | grep -i sqlite # doit afficher pdo_sqlite et/ou sqlite3
Lancement
php -S localhost:8000 -t public
La base database/api_tube.sqlite et son schéma sont créés automatiquement au premier appel (via les migrations).
Migrations
Les migrations sont des fichiers SQL numérotés dans database/migrations/, appliqués une seule fois et tracés dans la table migrations.
Elles sont exécutées automatiquement à la connexion à la base. Pour les appliquer manuellement (hors serveur web) :
php database/migrate.php
Ajouter une migration :
# fichier database/migrations/002_ajout_colonne.sql
echo "ALTER TABLE links ADD COLUMN visible INTEGER DEFAULT 1;" > database/migrations/002_ajout_colonne.sql
php database/migrate.php
Endpoints
| Méthode | Route | Description | Codes retour |
|---|---|---|---|
| GET | /links |
Lister tous les liens | 200 |
| GET | /links/{id} |
Lire un lien | 200 / 404 |
| POST | /links |
Créer un lien | 201 / 409 / 422 |
| PUT | /links/{id} |
Modifier un lien | 200 / 404 / 409 / 422 |
| DELETE | /links/{id} |
Supprimer un lien | 204 / 404 |
Corps attendu (POST / PUT, JSON)
{
"title": "Titre de la vidéo",
"description": "Description",
"link_url": "https://youtube.com/watch?v=VIDEO_ID",
"thumbnail": "https://img.youtube.com/vi/VIDEO_ID/hqdefault.jpg"
}
title et link_url sont obligatoires ; description et thumbnail sont optionnels. link_url doit être une URL valide et unique.
Tests manuels
bash tests/curl.sh
Sécurité
Éléments de sécurité implémentés dans l'API :
- Injection SQL : toutes les requêtes avec paramètres utilisent des requêtes préparées PDO (
prepare()+execute()) danssrc/LinkRepository.php, jamais de concaténation de variables dans le SQL. - Validation des entrées : champs obligatoires vérifiés,
trim()systématique, et validation delink_urlviaFILTER_VALIDATE_URL(src/LinkController.php). - Pas de fuite d'informations : toute erreur (base, rendu) renvoie une réponse 500 générique
Erreur interne du serveur.sans stack trace ni détail (public/index.php).display_errorsn'est pas activé. - Exposition minimale au web : le DocumentRoot Apache (Docker) pointe vers
public/uniquement ;src/,database/et la base SQLite ne sont pas servis publiquement. Le.htaccessréécrit toute requête versindex.php. - CORS restreint : méthodes limitées à
GET, POST, PUT, DELETE, OPTIONSet en-têtes àContent-Type(public/index.php). - Base hors de l'image Docker :
*.sqliteest exclu via.dockerignoreet stocké dans le volumedb-data, pas dans les layers de l'image. - Typage strict :
declare(strict_types=1)dans tous les fichiers PHP, paramètres et retours typés.
Docker
Lancement
docker compose up -d --build
# API accessible sur http://localhost:8000
Arrêter
docker compose down # conserve la base (volume)
docker compose down -v # supprime la base (reset complet)
Persistance
La base SQLite est stockée dans le Docker volume db-data : elle survit aux down/up successifs. Un down -v la supprime ; le prochain démarrage recrée la base via les migrations.
Rebuild après modification du code
docker compose up -d --build
Arborescence
public/
index.php # point d'entrée unique
.htaccess # réécriture vers index.php
src/
Database.php # connexion PDO SQLite + exécution des migrations
LinkRepository.php # CRUD SQL
LinkController.php # routage, validation, orchestration
database/
migrate.php # runner de migrations (CLI)
migrations/ # fichiers SQL versionnés
Dockerfile # image PHP 8.4 Apache + mod_rewrite
docker-compose.yml # service web + volume db-data
.dockerignore