Un serveur HTTP 1.1 complet implémenté from scratch en C, conforme aux RFC essentielles, performant et robuste.
Auteur : Rachid Ghodbane
Licence : MIT
Année : 2025
- HTTP/1.1 complet avec support keep-alive
- Multithreading avec thread pool configurable
- Servir des fichiers statiques (HTML, CSS, JS, images, etc.)
- Support GET et POST avec parsing complet des en-têtes
- Upload de fichiers via requêtes POST
- Gestion des types MIME automatique
- Sécurité : prévention de traversée de répertoires
- Logging : access log et error log
- Configuration : arguments en ligne de commande et fichier de config
- Performance : utilisation d'epoll et sendfile()
- Codes de statut : 200, 201, 204, 301/302, 304, 400, 404, 405, 411, 413, 414, 431, 500, 501, 503
src/
├── main.c # Point d'entrée principal
├── server.c/h # Serveur principal avec epoll
├── threadpool.c/h # Pool de threads
├── http_parser.c/h # Parser HTTP 1.1
├── http_response.c/h # Construction des réponses HTTP
├── http_router.c/h # Routage des requêtes
├── fs.c/h # Gestion des fichiers (sendfile, sécurité)
├── mime.c/h # Types MIME
├── config.c/h # Configuration
└── log.c/h # Système de logging
include/ # Fichiers d'en-tête
www/ # Fichiers statiques à servir
tests/ # Scripts de test
scripts/ # Scripts utilitaires
- Système d'exploitation : Linux (testé sur Ubuntu, CentOS, Debian)
- Compilateur : GCC 7+ avec support C99
- Bibliothèques : pthread, epoll (glibc)
- Outils : make, curl (pour les tests)
# Cloner le projet
git clone <repository-url>
cd SERVEUR-HTTP
# Compiler
make
# Compiler en mode debug (avec sanitizers)
make debug
# Nettoyer
make clean
# Installer dans /usr/local/bin
sudo make install
# Désinstaller
sudo make uninstall
# Serveur par défaut (port 8080, répertoire ./www)
./bin/httpd
# Configuration personnalisée
./bin/httpd --host 0.0.0.0 --port 8080 --root ./www --threads 8
Option | Description | Défaut |
---|---|---|
-h, --host |
Adresse IP à écouter | 0.0.0.0 |
-p, --port |
Port à écouter | 8080 |
-r, --root |
Répertoire racine des fichiers statiques | ./www |
-t, --threads |
Nombre de threads worker | 8 |
-H, --max-header |
Taille max des en-têtes (bytes) | 32768 |
-B, --max-body |
Taille max du corps de requête (bytes) | 10485760 |
-k, --keepalive-timeout |
Timeout keep-alive (secondes) | 5 |
-u, --uploads |
Activer les uploads vers ce répertoire | Désactivé |
-g, --gzip |
Activer la compression gzip | Désactivé |
-c, --config |
Fichier de configuration | Aucun |
-?, --help |
Afficher l'aide | - |
Créer un fichier httpd.conf
:
host = 0.0.0.0
port = 8080
root = ./www
threads = 8
max_header = 32768
max_body = 10485760
keepalive_timeout = 5
uploads = ./uploads
gzip = false
Puis lancer avec :
./bin/httpd --config httpd.conf
# Lancer les tests de fumée
make test
# Ou directement
./scripts/smoke.sh
# Tests approfondis (cas limites, performance)
./tests/test_requests.sh
# GET simple
curl -v http://127.0.0.1:8080/
# POST avec upload
curl -v -X POST --data-binary @README.md http://127.0.0.1:8080/upload
# POST chunked
curl -v -X POST -H "Transfer-Encoding: chunked" --data-binary @README.md http://127.0.0.1:8080/upload
# Keep-alive (2 requêtes)
{ printf 'GET / HTTP/1.1\r\nHost: x\r\n\r\nGET /test.html HTTP/1.1\r\nHost: x\r\n\r\n'; sleep 1; } | nc 127.0.0.1 8080
# Test de charge
wrk -t4 -c64 -d15s http://127.0.0.1:8080/
- Connexions simultanées : 1000+
- Requêtes par seconde : 5000+ (sur machine moderne)
- Latence : < 1ms (fichiers statiques)
- Mémoire : ~10MB (base) + ~1KB par connexion
- epoll pour la gestion des événements
- sendfile() pour l'envoi de fichiers
- Thread pool pour la parallélisation
- Keep-alive pour la réutilisation des connexions
- Buffers optimisés (8KB par défaut)
- En-têtes pré-générés (Date, Server)
- Prévention de traversée de répertoires (protection contre
../
) - Normalisation des chemins avec
realpath()
- Limitation de la taille des en-têtes (32KB par défaut)
- Limitation de la taille du corps POST (10MB par défaut)
- Timeouts sur les connexions inactives
- Gestion des erreurs robuste
- Pas de support HTTPS (TLS)
- Pas de compression gzip (optionnel)
- Pas de support HTTP/2
- Pas d'authentification/autorisation
127.0.0.1 - - [25/Dec/2023:10:30:45 +0000] "GET / HTTP/1.1" 200 1234 5
127.0.0.1 - - [25/Dec/2023:10:30:46 +0000] "POST /upload HTTP/1.1" 201 45 12
[2023-12-25 10:30:45.123] INFO server.c:245: Nouvelle connexion de 127.0.0.1:45678
[2023-12-25 10:30:46.234] WARN http_router.c:89: Fichier non trouvé: /nonexistent.html
# Compiler avec sanitizers
make debug
# Lancer avec valgrind
valgrind --leak-check=full ./bin/httpd
# Lancer avec gdb
gdb ./bin/httpd
# Vérification statique
make check
# Formatage du code
make format
- Connexions actives : dans les logs
- Requêtes traitées : access log
- Erreurs : error log
- Performance : via les outils de test
# Surveiller les logs en temps réel
tail -f access.log error.log
# Compter les requêtes par minute
grep "$(date '+%d/%b/%Y:%H:%M')" access.log | wc -l
# Analyser les erreurs
grep "ERROR" error.log | tail -20
- Modulaire : chaque composant dans son propre fichier
- Thread-safe : utilisation de mutex pour les ressources partagées
- Gestion d'erreurs : codes de retour cohérents
- Documentation : commentaires détaillés
- Nouvelle méthode HTTP : modifier
http_parser.c
- Nouveau type MIME : ajouter dans
mime.c
- Nouvelle route : étendre
http_router.c
- Nouvelle option de config : modifier
config.c
# Tests unitaires (à implémenter)
make test-unit
# Tests d'intégration
make test-integration
# Tests de performance
make test-performance
- RFC 7230 - HTTP/1.1 Message Syntax and Routing
- RFC 7231 - HTTP/1.1 Semantics and Content
- RFC 7232 - HTTP/1.1 Conditional Requests
- RFC 7233 - HTTP/1.1 Range Requests
Ce projet est sous licence MIT. Voir le fichier LICENSE
pour plus de détails.
Note : Ce serveur est conçu à des fins éducatives et de démonstration. Pour la production, considérez l'utilisation de serveurs web éprouvés comme Nginx ou Apache.