Il s'agit d'une implémentation du Hypertext Transfer Protocol version 2 en C.
La couche de tramage de HTTP/2 est implémentée en tant que bibliothèque C réutilisable. En plus de cela, nous avons implémenté un client, un serveur et un proxy HTTP/2. Nous avons également développé des outils de test de charge et d'analyse comparative pour HTTP/2.
Un encodeur et un décodeur HPACK sont disponibles en tant qu'API publique.
nghttp2 a été initialement développé sur la base des RFC 7540 HTTP/2 et RFC 7541 HPACK - Header Compression for HTTP/2. Nous mettons maintenant à jour notre code pour implémenter la RFC 9113.
La base de code nghttp2 a été dérivée du projet spdylay (https://github.com/tatsuhiro-t/spdylay).
Les points de terminaison suivants sont disponibles pour tester notre implémentation nghttp2.
https://nghttp2.org/ (TLS + ALPN et HTTP/3)
Ce point de terminaison prend en charge h2
, h2-16
, h2-14
et http/1.1
via ALPN et nécessite TLSv1.2 pour la connexion HTTP/2.
Il prend également en charge HTTP/3.
http://nghttp2.org/ (Mise à niveau HTTP et HTTP/2 Direct)
h2c
et http/1.1
.
Le package suivant est requis pour construire la bibliothèque libnghttp2 :
Pour construire la documentation, vous devez installer :
Si vous avez uniquement besoin de libnghttp2 (bibliothèque C), les packages ci-dessus sont tout ce dont vous avez besoin. Utilisez --enable-lib-only
pour vous assurer que seule libnghttp2 est construite. Cela évite les erreurs de génération potentielles liées à la création d'applications groupées.
Pour créer et exécuter les programmes d'application ( nghttp
, nghttpd
, nghttpx
et h2load
) dans le répertoire src
, les packages suivants sont requis :
Pour activer l'option -a
(obtention des actifs liés à partir de la ressource téléchargée) dans nghttp
, le package suivant est requis :
Pour activer la prise en charge de systemd dans nghttpx, le package suivant est requis :
Les outils HPACK nécessitent le package suivant :
Pour construire des sources dans le répertoire examples, libevent est requis :
Pour atténuer la fragmentation du tas dans les programmes serveur de longue durée ( nghttpd
et nghttpx
), jemalloc est recommandé :
jemalloc
Note
Alpine Linux ne prend actuellement pas en charge le remplacement de malloc en raison des limitations de Musl. Voir les détails dans le numéro 762.
Pour la version BoringSSL ou aws-lc, pour activer la compression de certificat TLS RFC 8879 dans les applications, la bibliothèque suivante est requise :
Pour activer la prise en charge de mruby pour nghttpx, mruby est requis. Nous devons construire mruby avec C++ ABI explicitement activé, et avons probablement besoin d'autres mrgems, mruby est géré par le sous-module git dans le répertoire tiers/mruby. Actuellement, la prise en charge de mruby pour nghttpx est désactivée par défaut. Pour activer la prise en charge de mruby, utilisez l'option de configuration --with-mruby
. Notez qu'au moment d'écrire ces lignes, les packages libmruby-dev et mruby dans Debian/Ubuntu ne sont pas utilisables pour nghttp2, car ils n'activent pas l'ABI C++. Pour construire mruby, les packages suivants sont requis :
nghttpx prend en charge le moteur de séparation des privilèges Neverbleed pour OpenSSL. En bref, cela minimise le risque de fuite de clé privée lorsqu'un bug grave comme Heartbleed est exploité. Le Neverbleed est désactivé par défaut. Pour l'activer, utilisez l'option de configuration --with-neverbleed
.
Pour activer la prise en charge expérimentale HTTP/3 pour h2load et nghttpx, les bibliothèques suivantes sont requises :
Utilisez l'option de configuration --enable-http3
pour activer la fonctionnalité HTTP/3 pour h2load et nghttpx.
Afin de créer un programme eBPF facultatif pour diriger un datagramme QUIC UDP entrant vers un socket correct pour nghttpx, les bibliothèques suivantes sont requises :
Utilisez l'option de configuration --with-libbpf
pour créer le programme eBPF. libelf-dev est nécessaire pour construire libbpf.
Pour Ubuntu 20.04, vous pouvez créer libbpf à partir du code source. nghttpx nécessite le programme eBPF pour recharger sa configuration et échanger à chaud son exécutable.
La compilation du code source libnghttp2 C nécessite un compilateur C99. gcc 4.8 est connu pour être adéquat. Afin de compiler le code source C++, un compilateur compatible C++20 est requis. Au moins g++ >= 12 et clang++ >= 15 sont connus pour fonctionner.
Note
Pour activer la prise en charge de mruby dans nghttpx et utilisez l'option de configuration --with-mruby
.
Note
Les utilisateurs de Mac OS X peuvent avoir besoin de l'option de configuration --disable-threads
pour désactiver le multithreading dans nghttpd, nghttpx et h2load afin d'éviter qu'ils ne plantent. Un correctif est le bienvenu pour faire fonctionner le multithreading sur la plateforme Mac OS X.
Note
Pour compiler les applications associées (nghttp, nghttpd, nghttpx et h2load), vous devez utiliser l'option de configuration --enable-app
et vous assurer que les exigences spécifiées ci-dessus sont remplies. Normalement, configurez le script vérifie les dépendances requises pour créer ces applications et activez --enable-app
automatiquement, afin que vous n'ayez pas à l'utiliser explicitement. Mais si vous constatez que les applications n'ont pas été créées, l'utilisation --enable-app
peut trouver cette cause, telle que la dépendance manquante.
Note
Afin de détecter les bibliothèques tierces, pkg-config est utilisé (cependant, nous n'utilisons pas pkg-config pour certaines bibliothèques (par exemple, libev)). Par défaut, pkg-config recherche le fichier *.pc
dans les emplacements standard (par exemple, /usr/lib/pkgconfig). S'il est nécessaire d'utiliser le fichier *.pc
dans l'emplacement personnalisé, spécifiez les chemins vers la variable d'environnement PKG_CONFIG_PATH
et transmettez-le pour configurer le script, comme ceci :
$ ./configure PKG_CONFIG_PATH=/path/to/pkgconfig
Pour les bibliothèques gérées par pkg-config, les variables d'environnement *_CFLAG
et *_LIBS
sont définies (par exemple, OPENSSL_CFLAGS
, OPENSSL_LIBS
). La spécification d'une chaîne non vide pour ces variables remplace complètement pkg-config. En d'autres termes, si elles sont spécifiées, pkg-config n'est pas utilisé pour la détection et l'utilisateur est responsable de spécifier les valeurs correctes pour ces variables. Pour la liste complète de ces variables, exécutez ./configure -h
.
Si vous utilisez Ubuntu 22.04 LTS, exécutez ce qui suit pour installer les packages requis :
sudo apt-get install g++ clang make binutils autoconf automake
autotools-dev libtool pkg-config
zlib1g-dev libssl-dev libxml2-dev libev-dev
libevent-dev libjansson-dev
libc-ares-dev libjemalloc-dev libsystemd-dev
ruby-dev bison libelf-dev
Le projet nghttp2 publie régulièrement des archives tar qui incluent le code source nghttp2 et les fichiers de construction générés. Ils peuvent être téléchargés à partir de la page Versions.
Construire nghttp2 à partir de git nécessite des packages de développement autotools. Construire à partir d'archives tar n'en nécessite pas, et c'est donc beaucoup plus facile. L'étape de construction habituelle est la suivante :
$ tar xf nghttp2-XYZtar.bz2
$ cd nghttp2-XYZ
$ ./configurer
$ faire
Construire à partir de git est facile, mais assurez-vous qu'au moins autoconf 2.68 est utilisé :
$ mise à jour du sous-module git --init
$ autoreconf -i
$ fabrication automatique
$ autoconf
$ ./configurer
$ faire
Le moyen le plus simple de créer une DLL Windows nghttp2 native consiste à utiliser cmake. La version gratuite de Visual C++ Build Tools fonctionne correctement.
cmake
.cmake --build
pour créer la bibliothèque.Notez que les étapes ci-dessus produisent très probablement uniquement la bibliothèque nghttp2. Aucune application groupée n'est compilée.
Sous l'environnement Mingw, vous ne pouvez compiler que la bibliothèque, il s'agit libnghttp2-X.dll
et libnghttp2.a
.
Si vous souhaitez compiler les applications ( h2load
, nghttp
, nghttpx
, nghttpd
), vous devez utiliser l'environnement Cygwin.
Sous l'environnement Cygwin, pour compiler les applications, vous devez d'abord compiler et installer la libev.
Deuxièmement, vous devez annuler la définition de la macro __STRICT_ANSI__
, sinon les fonctions fdopen
, fileno
et strptime
ne seront pas disponibles.
l'exemple de commande comme ceci :
$ export CFLAGS="-U__STRICT_ANSI__ -I$libev_PREFIX/include -L$libev_PREFIX/lib"
$ export CXXFLAGS=$CFLAGS
$ ./configurer
$ faire
Si vous souhaitez compiler les applications sous examples/
, vous devez supprimer ou renommer event.h
de l'installation de libev, car il entre en conflit avec l'installation de libev.
Après avoir installé la suite d'outils nghttp2 avec make install
vous pourriez rencontrer une erreur similaire :
nghttpx : erreur lors du chargement des bibliothèques partagées : libnghttp2.so.14 : impossible d'ouvrir le fichier objet partagé : aucun fichier ou répertoire de ce type
Cela signifie que l'outil ne parvient pas à localiser la bibliothèque partagée libnghttp2.so
.
Pour mettre à jour le cache de la bibliothèque partagée, exécutez sudo ldconfig
.
Note
La documentation est encore incomplète.
Pour créer la documentation, exécutez :
$ faire du HTML
Les documents seront générés sous doc/manual/html/
.
Les documents générés ne seront pas installés avec make install
.
La documentation en ligne est disponible sur https://nghttp2.org/documentation/
Pour créer h2load et nghttpx avec la fonctionnalité HTTP/3 activée, exécutez le script de configuration avec --enable-http3
.
Pour que nghttpx recharge les configurations et échange son exécutable tout en mettant fin en douceur aux anciens processus de travail, eBPF est requis. Exécutez le script de configuration avec --enable-http3 --with-libbpf
pour créer le programme eBPF. Le matériel de chiffrement QUIC doit être défini avec --frontend-quic-secret-file
afin de maintenir les connexions existantes actives pendant le rechargement.
Les étapes détaillées pour créer h2load et nghttpx compatibles HTTP/3 suivent.
Créez AWS-LC :
$ git clone --profondeur 1 -b v1.39.0 https://github.com/aws/aws-lc
$ cd aws-lc
$ cmake -B build -DDISABLE_GO=ON --install-prefix=$PWD/opt
$ make -j$(nproc) -C build
$ cmake --install build
$ cd ..
Construisez nghttp3 :
$ git clone --profondeur 1 -b v1.6.0 https://github.com/ngtcp2/nghttp3
$ cd nghttp3
$ mise à jour du sous-module git --init --profondeur 1
$ autoreconf -i
$ ./configure --prefix=$PWD/build --enable-lib-only
$ make -j$(nproc)
$ faire installer
$ cd ..
Construisez ngtcp2 :
$ git clone --profondeur 1 -b v1.9.1 https://github.com/ngtcp2/ngtcp2
$ cd ngtcp2
$ mise à jour du sous-module git --init --profondeur 1
$ autoreconf -i
$ ./configure --prefix=$PWD/build --enable-lib-only --with-boringssl
BORINGSSL_CFLAGS="-I$PWD/../aws-lc/opt/include"
BORINGSSL_LIBS="-L$PWD/../aws-lc/opt/lib -lssl -lcrypto"
$ make -j$(nproc)
$ faire installer
$ cd ..
Si votre distribution Linux n'a pas libbpf-dev >= 0.7.0, compilez à partir des sources :
$ git clone --profondeur 1 -b v1.4.6 https://github.com/libbpf/libbpf
$ cd libbpf
$ PREFIX=$PWD/build make -C src install
$ cd ..
Construisez nghttp2 :
$ git clone https://github.com/nghttp2/nghttp2
$ cd nghttp2
$ mise à jour du sous-module git --init
$ autoreconf -i
$ ./configure --with-mruby --enable-http3 --with-libbpf
CC=clang-15 CXX=clang++-15
PKG_CONFIG_PATH="$PWD/../aws-lc/opt/lib/pkgconfig:$PWD/../nghttp3/build/lib/pkgconfig:$PWD/../ngtcp2/build/lib/pkgconfig:$PWD/ ../libbpf/build/lib64/pkgconfig"
LDFLAGS="$LDFLAGS -Wl,-rpath,$PWD/../aws-lc/opt/lib -Wl,-rpath,$PWD/../libbpf/build/lib64"
$ make -j$(nproc)
Le programme eBPF reuseport_kern.o
doit se trouver dans le répertoire bpf. Passez l'option --quic-bpf-program-file=bpf/reuseport_kern.o
à nghttpx pour le charger. Voir aussi la section HTTP/3 dans nghttpx - Proxy HTTP/2 - HOW-TO.
Les tests unitaires sont effectués en exécutant simplement make check
.
Nous avons les tests d'intégration pour le serveur proxy nghttpx. Les tests sont écrits dans le langage de programmation Go et utilisent son framework de test. Nous dépendons des bibliothèques suivantes :
Les modules Go téléchargeront automatiquement ces dépendances.
Pour exécuter les tests, exécutez la commande suivante dans le répertoire integration-tests
:
$ fais-le
Dans les tests, nous utilisons le port 3009 pour exécuter le serveur du sujet de test.
nghttp2 v1.0.0 a introduit plusieurs modifications rétrocompatibles. Dans cette section, nous décrivons ces modifications et comment migrer vers la v1.0.0.
h2
et h2c
Auparavant, nous avions annoncé h2-14
et h2c-14
. La v1.0.0 implémente la version finale du protocole et nous avons changé l'ID ALPN en h2
et h2c
. Les macros NGHTTP2_PROTO_VERSION_ID
, NGHTTP2_PROTO_VERSION_ID_LEN
, NGHTTP2_CLEARTEXT_PROTO_VERSION_ID
et NGHTTP2_CLEARTEXT_PROTO_VERSION_ID_LEN
ont été mises à jour pour refléter ce changement.
Fondamentalement, les applications existantes n'ont rien à faire, une simple recompilation suffit pour ce changement.
Nous utilisons « préface de connexion client » pour désigner les 24 premiers octets de la préface de connexion client. Ceci n'est techniquement pas correct, car la préface de connexion client est composée d'une chaîne d'octets magique client de 24 octets suivie de la trame SETTINGS. Pour plus de clarté, nous appelons « magie client » pour cette chaîne d'octets de 24 octets et cette API mise à jour.
NGHTTP2_CLIENT_CONNECTION_PREFACE
a été remplacé par NGHTTP2_CLIENT_MAGIC
.NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN
a été remplacé par NGHTTP2_CLIENT_MAGIC_LEN
.NGHTTP2_BAD_PREFACE
a été renommé NGHTTP2_BAD_CLIENT_MAGIC
Les NGHTTP2_CLIENT_CONNECTION_HEADER
et NGHTTP2_CLIENT_CONNECTION_HEADER_LEN
déjà obsolètes ont été supprimés.
Si l'application utilise ces macros, remplacez simplement les anciennes par de nouvelles. Depuis la version 1.0.0, la magie client est envoyée par la bibliothèque (voir la sous-section suivante), donc l'application client peut simplement supprimer cette utilisation de macro.
Auparavant, la bibliothèque nghttp2 n'envoyait pas la magie client, qui est la première chaîne de 24 octets de la préface de connexion client, et les applications clientes devaient l'envoyer elles-mêmes. Depuis la v1.0.0, la magie client est envoyée par la bibliothèque via le premier appel de nghttp2_session_send()
ou nghttp2_session_mem_send2()
.
Les applications clientes qui envoient de la magie client doivent supprimer le code correspondant.
La spécification Alt-Svc n’est pas encore finalisée. Pour rendre notre API stable, nous avons décidé de supprimer toutes les API liées à Alt-Svc de nghttp2.
NGHTTP2_EXT_ALTSVC
a été supprimé.nghttp2_ext_altsvc
a été supprimé.Nous avons déjà supprimé la fonctionnalité Alt-Svc dans la série v0.7 et elles ont été essentiellement noop. L'application utilisant ces macro et structure supprime ces lignes.
Auparavant, nghttp2_on_invalid_frame_recv_cb_called
prenait le error_code
, défini dans nghttp2_error_code
, comme paramètre. Mais ils ne sont pas suffisamment détaillés pour être débogués. Par conséquent, nous avons décidé d'utiliser plutôt des valeurs nghttp2_error
plus détaillées.
L'application utilisant ce rappel doit mettre à jour la signature de rappel. S'il traite error_code
comme code d'erreur HTTP/2, mettez à jour le code afin qu'il soit traité comme nghttp2_error
.
Auparavant, nghttp2 ne traitait pas la magie du client (chaîne d'octets de 24 octets). Pour y faire face, nous avons dû utiliser nghttp2_option_set_recv_client_preface()
. Depuis la version 1.0.0, nghttp2 traite la magie du client par défaut et nghttp2_option_set_recv_client_preface()
a été supprimé.
Certaines applications peuvent souhaiter désactiver ce comportement, nous avons donc ajouté nghttp2_option_set_no_recv_client_magic()
pour y parvenir.
L'application utilisant nghttp2_option_set_recv_client_preface()
avec une valeur différente de zéro, supprimez-la simplement.
L'application utilisant nghttp2_option_set_recv_client_preface()
avec une valeur nulle ou ne l'utilisant pas doit utiliser nghttp2_option_set_no_recv_client_magic()
avec une valeur différente de zéro.
Le répertoire src
contient les programmes client, serveur et proxy HTTP/2.
nghttp
est un client HTTP/2. Il peut se connecter au serveur HTTP/2 avec des connaissances préalables, une mise à niveau HTTP et une extension ALPN TLS.
Il dispose d'un mode de sortie détaillé pour le cadrage des informations. Voici un exemple de sortie du client nghttp
:
$ nghttp -nv https://nghttp2.org
[ 0,190] Connecté
Le protocole négocié : h2
[ 0.212] cadre RECV SETTINGS
(niv=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[ 0.212] envoyer la trame SETTINGS
(niv=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[ 0.212] envoyer la trame SETTINGS
; ACCK
(niv=0)
[ 0.212] envoyer la trame PRIORITY
(dep_stream_id=0, poids=201, exclusif=0)
[ 0.212] envoyer la trame PRIORITY
(dep_stream_id=0, poids=101, exclusif=0)
[ 0.212] envoyer la trame PRIORITY
(dep_stream_id=0, poids=1, exclusif=0)
[ 0.212] envoyer la trame PRIORITY
(dep_stream_id=7, poids=1, exclusif=0)
[ 0.212] envoyer la trame PRIORITY
(dep_stream_id=3, poids=1, exclusif=0)
[ 0.212] envoyer la trame HEADERS
; END_STREAM | END_HEADERS | PRIORITÉ
(padlen=0, dep_stream_id=11, poids=16, exclusif=0)
; Ouvrir un nouveau flux
:méthode: OBTENIR
:chemin: /
:schéma : https
:autorité: nghttp2.org
accepter: */*
accepter-encodage : gzip, dégonfler
agent utilisateur : nghttp2/1.0.1-DEV
[ 0.221] cadre RECV SETTINGS
; ACCK
(niv=0)
[ 0.221] recv (stream_id=13) :méthode: GET
[ 0.221] recv (stream_id=13) :scheme: https
[ 0.221] recv (stream_id=13) :chemin: /stylesheets/screen.css
[ 0.221] recv (stream_id=13) :autorité : nghttp2.org
[ 0.221] recv (stream_id=13) accepter-encodage : gzip, dégonfler
[ 0.222] agent utilisateur recv (stream_id=13) : nghttp2/1.0.1-DEV
[ 0,222] trame recv PUSH_PROMISE
; END_HEADERS
(padlen=0, promise_stream_id=2)
[ 0,222] recv (stream_id=13) :statut : 200
[ 0,222] recv (stream_id=13) date : jeu. 21 mai 2015 16:38:14 GMT
[ 0,222] recv (stream_id=13) type de contenu : texte/html
[ 0,222] recv (stream_id=13) dernière modification : vendredi 15 mai 2015 15:38:06 GMT
[ 0.222] recv (stream_id=13) etag : W/"555612de-19f6"
[ 0.222] lien recv (stream_id=13) : ; rel=préchargement ; as=feuille de style
[ 0.222] recv (stream_id=13) encodage de contenu : gzip
[0.222] serveur recv (stream_id=13) : nghttpx nghttp2/1.0.1-DEV
[ 0,222] recv (stream_id=13) via : 1.1 nghttpx
[ 0,222] recv (stream_id=13) strict-transport-security : max-age=31536000
[ 0,222] trame HEADERS recv
; END_HEADERS
(padlen=0)
; En-tête de première réponse
[ 0,222] trame recv DATA
; END_STREAM
[ 0,222] recv (stream_id=2) :statut : 200
[ 0.222] recv (stream_id=2) date : jeu. 21 mai 2015 16:38:14 GMT
[ 0.222] recv (stream_id=2) type de contenu : texte/css
[ 0,222] recv (stream_id=2) dernière modification : vendredi 15 mai 2015 15:38:06 GMT
[ 0.222] recv (stream_id=2) etag : W/"555612de-9845"
[ 0.222] recv (stream_id=2) encodage de contenu : gzip
[0.222] serveur recv (stream_id=2) : nghttpx nghttp2/1.0.1-DEV
[ 0,222] recv (stream_id=2) via : 1.1 nghttpx
[ 0,222] recv (stream_id=2) strict-transport-security : max-age=31536000
[ 0,222] trame HEADERS recv
; END_HEADERS
(padlen=0)
; Premier en-tête de réponse push
[ 0,228] trame recv DATA
; END_STREAM
[ 0.228] envoyer la trame GOAWAY
(last_stream_id=2, error_code=NO_ERROR(0x00), opaque_data(0)=[])
La mise à niveau HTTP s'effectue comme suit :
$ nghttp -nvu http://nghttp2.org
[ 0,011] Connecté
[ 0.011] Demande de mise à niveau HTTP
OBTENIR / HTTP/1.1
Hébergeur : nghttp2.org
Connexion : mise à niveau, paramètres HTTP2
Mise à niveau : h2c
Paramètres HTTP2 : AAMAAABkAAQAAP__
Accepter: */*
Agent utilisateur : nghttp2/1.0.1-DEV
[ 0.018] Réponse de mise à niveau HTTP
HTTP/1.1 101 protocoles de commutation
Connexion : mise à niveau
Mise à niveau : h2c
[ 0.018] Réussite de la mise à niveau HTTP
[ 0.018] cadre RECV SETTINGS
(niv=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[ 0.018] envoyer la trame SETTINGS
(niv=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[ 0.018] envoyer la trame SETTINGS
; ACCK
(niv=0)
[ 0,018] envoyer la trame PRIORITY
(dep_stream_id=0, poids=201, exclusif=0)
[ 0,018] envoyer la trame PRIORITY
(dep_stream_id=0, poids=101, exclusif=0)
[ 0,018] envoyer la trame PRIORITY
(dep_stream_id=0, poids=1, exclusif=0)
[ 0,018] envoyer la trame PRIORITY
(dep_stream_id=7, poids=1, exclusif=0)
[ 0,018] envoyer la trame PRIORITY
(dep_stream_id=3, poids=1, exclusif=0)
[ 0,018] envoyer la trame PRIORITY
(dep_stream_id=11, poids=16, exclusif=0)
[ 0.019] recv (stream_id=1) :méthode: GET
[ 0.019] recv (stream_id=1) :scheme: http
[ 0.019] recv (stream_id=1) :chemin: /stylesheets/screen.css
[ 0,019] hôte recv (stream_id=1) : nghttp2.org
[ 0.019] agent utilisateur recv (stream_id=1) : nghttp2/1.0.1-DEV
[ 0,019] trame recv PUSH_PROMISE
; END_HEADERS
(padlen=0, promise_stream_id=2)
[ 0,019] recv (stream_id=1) :statut : 200
[ 0.019] recv (stream_id=1) date : jeu. 21 mai 2015 16:39:16 GMT
[ 0,019] recv (stream_id=1) type de contenu : texte/html
[ 0,019] recv (stream_id=1) longueur du contenu : 6646
[ 0,019] recv (stream_id=1) dernière modification : vendredi 15 mai 2015 15:38:06 GMT
[ 0.019] recv (stream_id=1) etag : "555612de-19f6"
[ 0.019] lien recv (stream_id=1) : ; rel=préchargement ; as=feuille de style
[ 0,019] recv (stream_id=1) plages d'acceptation : octets
[0.019] serveur recv (stream_id=1) : nghttpx nghttp2/1.0.1-DEV
[ 0,019] recv (stream_id=1) via : 1.1 nghttpx
[ 0,019] trame HEADERS recv
; END_HEADERS
(padlen=0)
; En-tête de première réponse
[ 0,019] trame recv DATA
; END_STREAM
[ 0,019] recv (stream_id=2) :statut : 200
[ 0.019] recv (stream_id=2) date : jeu. 21 mai 2015 16:39:16 GMT
[ 0,019] recv (stream_id=2) type de contenu : texte/css
[ 0,019] recv (stream_id=2) longueur du contenu : 38981
[ 0,019] recv (stream_id=2) dernière modification : vendredi 15 mai 2015 15:38:06 GMT
[ 0.019] recv (stream_id=2) etag : "555612de-9845"
[ 0,019] recv (stream_id=2) plages d'acceptation : octets
[0.019] serveur recv (stream_id=2) : nghttpx nghttp2/1.0.1-DEV
[ 0,019] recv (stream_id=2) via : 1.1 nghttpx
[ 0,019] trame HEADERS recv
; END_HEADERS
(padlen=0)
; Premier en-tête de réponse push
[ 0,026] trame recv DATA
[ 0,027] trame recv DATA
[ 0,027] envoyer la trame WINDOW_UPDATE
(window_size_increment=33343)
[ 0,032] envoyer la trame WINDOW_UPDATE
(window_size_increment=33707)
[ 0,032] trame recv DATA
; END_STREAM
[ 0.032] cadre RECV SETTINGS
; ACCK
(niv=0)
[ 0,032] envoyer la trame GOAWAY
(last_stream_id=2, error_code=NO_ERROR(0x00), opaque_data(0)=[])
En utilisant l'option -s
, nghttp
affiche des informations de synchronisation pour les requêtes, triées par heure d'achèvement :
$ nghttp -nas https://nghttp2.org/
***** Statistiques *****
Calendrier de la demande :
ResponseEnd : l'heure à laquelle le dernier octet de réponse a été reçu
par rapport à connectEnd
requestStart : l'heure juste avant l'envoi du premier octet de la requête
par rapport à connectEnd. Si '*' est affiché, c'était
poussé par le serveur.
processus : réponseEnd - requestStart
code : code d'état HTTP
size : nombre d'octets reçus comme corps de réponse sans
inflation.
URI : demande d'URI
voir http://www.w3.org/TR/resource-timing/#processing-model
triés par 'complet'
id réponseEnd requestStart processus code taille chemin de la demande
13 +37,19ms +280us 36,91ms 200 2K /
2 +72,65 ms * +36,38 ms 36,26 ms 200 8K /feuilles de style/screen.css
17 +77,43 ms +38,67 ms 38,75 ms 200 3K /javascripts/octopress.js
15 +78,12 ms +38,66 ms 39,46 ms 200 3K /javascripts/modernizr-2.0.js
En utilisant l'option -r
, nghttp
écrit des données de synchronisation plus détaillées dans le fichier donné au format HAR.
nghttpd
est un serveur Web statique multithread.
Par défaut, il utilise une connexion SSL/TLS. Utilisez l'option --no-tls
pour le désactiver.
nghttpd
n'accepte que les connexions HTTP/2 via ALPN ou les connexions HTTP/2 directes. Aucune mise à niveau HTTP n'est prise en charge.
L'option -p
permet aux utilisateurs de configurer le push du serveur.
Tout comme nghttp
, il dispose d'un mode de sortie détaillé pour le cadrage des informations. Voici un exemple de sortie de nghttpd
:
$ nghttpd --no-tls -v 8080
IPv4 : écoutez 0.0.0.0:8080
IPv6 : écouter :::8080
[id=1] [ 1.521] envoyer la trame SETTINGS
(niv=1)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[id=1] [ 1.521] cadre RECV SETTINGS
(niv=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[id=1] [ 1.521] cadre RECV SETTINGS
; ACCK
(niv=0)
[id=1] [ 1.521] trame PRIORITY recv
(dep_stream_id=0, poids=201, exclusif=0)
[id=1] [ 1.521] trame PRIORITY recv
(dep_stream_id=0, poids=101, exclusif=0)
[id=1] [ 1.521] trame PRIORITY recv
(dep_stream_id=0, poids=1, exclusif=0)
[id=1] [ 1.521] trame PRIORITY recv
(dep_stream_id=7, poids=1, exclusif=0)
[id=1] [ 1.521] trame PRIORITY recv
(dep_stream_id=3, poids=1, exclusif=0)
[id=1] [ 1.521] recv (stream_id=13) :method: GET
[id=1] [ 1.521] recv (stream_id=13) :chemin: /
[id=1] [ 1.521] recv (stream_id=13) :scheme: http
[id=1] [ 1.521] recv (stream_id=13) :authority: localhost:8080
[id=1] [ 1.521] recv (stream_id=13) accepter : */*
[id=1] [ 1.521] recv (stream_id=13) accepter-encodage : gzip, dégonfler
[id=1] [ 1.521] recv (stream_id=13) agent utilisateur : nghttp2/1.0.0-DEV
[id=1] [ 1.521] trame recv HEADERS
; END_STREAM | END_HEADERS | PRIORITÉ
(padlen=0, dep_stream_id=11, poids=16, exclusif=0)
; Ouvrir un nouveau flux
[id=1] [ 1.521] envoyer la trame SETTINGS
; ACCK
(niv=0)
[id=1] [ 1.521] envoyer la trame HEADERS
; END_HEADERS
(padlen=0)
; En-tête de première réponse
:statut : 200
serveur : nghttpd nghttp2/1.0.0-DEV
longueur du contenu : 10
contrôle du cache : âge maximum = 3 600
date: vendredi 15 mai 2015 14:49:04 GMT
dernière modification : mar. 30 septembre 2014 12:40:52 GMT
[id=1] [ 1.522] envoyer la trame DATA
; END_STREAM
[id=1] [ 1.522] stream_id=13 fermé
[id=1] [ 1.522] trame recv GOAWAY
(last_stream_id=0, error_code=NO_ERROR(0x00), opaque_data(0)=[])
[id=1] [ 1.522] fermé
nghttpx
est un proxy inverse multithread pour HTTP/3, HTTP/2 et HTTP/1.1, alimente http://nghttp2.org et prend en charge le serveur push HTTP/2.
Nous avons retravaillé l'interface de ligne de commande nghttpx
et, par conséquent, il existe plusieurs incompatibles à partir de la version 1.8.0 ou antérieure. Cela est nécessaire pour étendre ses capacités et garantir les améliorations supplémentaires des fonctionnalités dans la prochaine version. Veuillez lire Migration à partir de nghttpx v1.8.0 ou version antérieure pour savoir comment migrer à partir de versions antérieures.
nghttpx
implémente d'importantes fonctionnalités axées sur les performances dans TLS, telles que les identifiants de session, les tickets de session (avec rotation automatique des clés), l'agrafage OCSP, le dimensionnement dynamique des enregistrements, ALPN, la confidentialité de transfert et HTTP/2. nghttpx
offre également la fonctionnalité permettant de partager le cache de session et les clés de ticket entre plusieurs instances nghttpx
via memcached.
nghttpx
a 2 modes de fonctionnement :
Options de mode | L'extrémité avant | Back-end | Note |
---|---|---|---|
mode par défaut | HTTP/3, HTTP/2, HTTP/1.1 | HTTP/1.1, HTTP/2 | Proxy inverse |
--http2-proxy | HTTP/3, HTTP/2, HTTP/1.1 | HTTP/1.1, HTTP/2 | Proxy direct |
Le mode intéressant pour le moment est le mode par défaut. Il fonctionne comme un proxy inverse et écoute HTTP/3, HTTP/2 et HTTP/1.1 et peut être déployé en tant que terminateur SSL/TLS pour le serveur Web existant.
Dans tous les modes, les connexions frontend sont cryptées par SSL/TLS par défaut. Pour désactiver le cryptage, utilisez le mot-clé no-tls
dans l'option --frontend
. Si le cryptage est désactivé, les connexions HTTP/1.1 entrantes peuvent être mises à niveau vers HTTP/2 via HTTP Upgrade. D’un autre côté, les connexions backend ne sont pas chiffrées par défaut. Pour chiffrer les connexions backend, utilisez le mot-clé tls
dans l'option --backend
.
nghttpx
prend en charge un fichier de configuration. Consultez l'option --conf
et l'exemple de fichier de configuration nghttpx.conf.sample
.
Dans le mode par défaut, nghttpx
fonctionne comme proxy inverse pour le serveur backend :
Client <-- (HTTP/3, HTTP/2, HTTP/1.1) --> nghttpx <-- (HTTP/1.1, HTTP/2) --> Serveur Web
[proxy inverse]
Avec l'option --http2-proxy
, il fonctionne comme un proxy direct, et c'est ce qu'on appelle un proxy HTTP/2 sécurisé :
Client <-- (HTTP/3, HTTP/2, HTTP/1.1) --> nghttpx <-- (HTTP/1.1) --> Proxy
[proxy sécurisé] (par exemple, Squid, ATS)
Le Client
dans l'exemple ci-dessus doit être configuré pour utiliser nghttpx
comme proxy sécurisé.
Au moment d’écrire ces lignes, Chrome et Firefox prennent en charge le proxy HTTP/2 sécurisé. Une façon de configurer Chrome pour utiliser un proxy sécurisé consiste à créer un script proxy.pac comme celui-ci :
function FindProxyForURL ( url , host ) {
return "HTTPS SERVERADDR:PORT" ;
}
SERVERADDR
et PORT
sont le nom d'hôte/l'adresse et le port de la machine sur laquelle nghttpx s'exécute. Veuillez noter que Chrome nécessite un certificat valide pour un proxy sécurisé.
Exécutez ensuite Chrome avec les arguments suivants :
$ google-chrome --proxy-pac-url=file:///path/to/proxy.pac --use-npn
Les connexions HTTP/2 backend peuvent être tunnelisées via un proxy HTTP. Le proxy est spécifié à l'aide de --backend-http-proxy-uri
. La figure suivante illustre comment nghttpx communique avec le proxy HTTP/2 externe via un proxy HTTP :
Client <-- (HTTP/3, HTTP/2, HTTP/1.1) --> nghttpx <-- (HTTP/2) --
--====================---> Proxy HTTP/2
(tunnel proxy HTTP) (par exemple, nghttpx -s)
Le programme h2load
est un outil d'analyse comparative pour HTTP/3, HTTP/2 et HTTP/1.1. L'interface utilisateur de h2load
est fortement inspirée weighttp
(https://github.com/lighttpd/weighttp). L'utilisation typique est la suivante :
$ h2load -n100000 -c100 -m100 https://localhost:8443/
benchmark de départ...
thread de génération n°0 : 100 clients simultanés, 100 000 requêtes au total
Protocole : TLSv1.2
Chiffre : ECDHE-RSA-AES128-GCM-SHA256
Clé temporaire du serveur : ECDH P-256 256 bits
progression : 10 % réalisé
progrès : 20 % réalisé
progrès : 30% réalisé
progrès : 40% réalisé
progrès : 50% réalisé
progrès : 60% réalisé
progrès : 70% réalisé
progrès : 80% réalisé
progrès : 90% réalisé
progression : 100% réalisé
terminé en 771,26 ms, 129658 req/s, 4,71 Mo/s
requêtes : 100 000 au total, 100 000 démarrées, 100 000 terminées, 100 000 réussies, 0 échouée, 0 erronée
codes d'état : 100000 2xx, 0 3xx, 0 4xx, 0 5xx
trafic : 3 812 300 octets au total, 1 009 900 octets d'en-têtes, 1 000 000 octets de données
min max moyenne sd +/- sd
temps de demande : 25,12 ms 124,55 ms 51,07 ms 15,36 ms 84,87 %
temps de connexion : 208,94 ms 254,67 ms 241,38 ms 7,95 ms 63,00 %
temps jusqu'au 1er octet : 209,11 ms 254,80 ms 241,51 ms 7,94 ms 63,00 %
L'exemple ci-dessus a émis un total de 100 000 requêtes, en utilisant 100 clients simultanés (en d'autres termes, 100 sessions HTTP/2) et un maximum de 100 flux par client. Avec l'option -t
, h2load
utilisera plusieurs threads natifs pour éviter de saturer un seul cœur côté client.
Avertissement
N'utilisez pas cet outil sur des serveurs accessibles au public. Ceci est considéré comme une attaque DOS. Veuillez l'utiliser uniquement sur vos serveurs privés.
Si le HTTP/3 expérimental est activé, h2load peut envoyer des requêtes au serveur HTTP/3. Pour ce faire, spécifiez h3
dans l'option --alpn-list
comme ceci :
$ h2load --alpn-list h3 https://127.0.0.1:4433
Pour nghttp2 v1.58 ou version antérieure, utilisez --npn-list
au lieu de --alpn-list
.
Le répertoire src
contient les outils HPACK. Le programme deflatehd
est un outil de compression d'en-tête en ligne de commande. Le programme inflatehd
est un outil de décompression d'en-tête en ligne de commande. Les deux outils lisent les entrées depuis stdin et écrivent la sortie sur stdout. Les erreurs sont écrites dans stderr. Ils prennent JSON comme entrée et sortie. Nous utilisons (principalement) le même format de données JSON décrit sur https://github.com/http2jp/hpack-test-Case.
Le programme deflatehd
lit les données JSON ou les champs d'en-tête HTTP / 1-1 de style de STDIN et publie un bloc d'en-tête compressé dans JSON.
Pour l'entrée JSON, l'objet Root JSON doit inclure une clé cases
. Sa valeur doit inclure la séquence de l'ensemble d'en-tête d'entrée. Ils partagent le même contexte de compression et sont traités dans l'ordre dans lequel ils apparaissent. Chaque élément de la séquence est un objet JSON et il doit inclure une clé headers
. Sa valeur est un tableau d'objets JSON, qui comprend exactement une paire de nom / valeur.
Exemple:
{
"cases" :
[
{
"headers" : [
{ ":method" : " GET " },
{ ":path" : " / " }
]
},
{
"headers" : [
{ ":method" : " POST " },
{ ":path" : " / " }
]
}
]
}
Avec l'option -t
, le programme peut accepter des blocs de champ d'en-tête de style HTTP / 1 plus familiers. Chaque ensemble d'en-tête est délimité par une ligne vide:
Exemple:
: Méthode: obtenir
: Schéma: HTTPS
:chemin: /
: Méthode: post
Agent utilisateur: nghttp2
La sortie est dans l'objet JSON. Il devrait inclure une clé cases
et sa valeur est un tableau d'objets JSON, qui a au moins les clés suivantes:
output_length
/ input_length
* 100Exemples :
{
"cases" :
[
{
"seq" : 0 ,
"input_length" : 66 ,
"output_length" : 20 ,
"percentage_of_original_size" : 30.303030303030305 ,
"wire" : " 01881f3468e5891afcbf83868a3d856659c62e3f " ,
"headers" : [
{
":authority" : " example.org "
},
{
":method" : " GET "
},
{
":path" : " / "
},
{
":scheme" : " https "
},
{
"user-agent" : " nghttp2 "
}
],
"header_table_size" : 4096
}
,
{
"seq" : 1 ,
"input_length" : 74 ,
"output_length" : 10 ,
"percentage_of_original_size" : 13.513513513513514 ,
"wire" : " 88448504252dd5918485 " ,
"headers" : [
{
":authority" : " example.org "
},
{
":method" : " POST "
},
{
":path" : " /account "
},
{
":scheme" : " https "
},
{
"user-agent" : " nghttp2 "
}
],
"header_table_size" : 4096
}
]
}
La sortie peut être utilisée comme entrée pour inflatehd
et deflatehd
.
Avec l'option -d
, la clé d' header_table
supplémentaire_tique est ajoutée et sa valeur associée inclut l'état de table d'en-tête dynamique après le traitement de l'ensemble d'en-tête correspondant. La valeur comprend au moins les clés suivantes:
referenced
est true
, il se trouve dans l'ensemble de référence. La size
comprend les frais généraux (32 octets). L' index
correspond à l'index de la table d'en-tête. Le name
est le nom du champ d'en-tête et la value
est la valeur du champ d'en-tête.max_deflate_size
.max_size
. Dans ce cas, l'encodeur utilise uniquement jusqu'à premier tampon max_deflate_size
. Étant donné que la taille de la table d'en-tête est toujours max_size
, l'encodeur doit garder une trace des entrées à l'extérieur du max_deflate_size
mais à l'intérieur du max_size
et assurez-vous qu'ils ne sont plus référencés.Exemple:
{
"cases" :
[
{
"seq" : 0 ,
"input_length" : 66 ,
"output_length" : 20 ,
"percentage_of_original_size" : 30.303030303030305 ,
"wire" : " 01881f3468e5891afcbf83868a3d856659c62e3f " ,
"headers" : [
{
":authority" : " example.org "
},
{
":method" : " GET "
},
{
":path" : " / "
},
{
":scheme" : " https "
},
{
"user-agent" : " nghttp2 "
}
],
"header_table_size" : 4096 ,
"header_table" : {
"entries" : [
{
"index" : 1 ,
"name" : " user-agent " ,
"value" : " nghttp2 " ,
"referenced" : true ,
"size" : 49
},
{
"index" : 2 ,
"name" : " :scheme " ,
"value" : " https " ,
"referenced" : true ,
"size" : 44
},
{
"index" : 3 ,
"name" : " :path " ,
"value" : " / " ,
"referenced" : true ,
"size" : 38
},
{
"index" : 4 ,
"name" : " :method " ,
"value" : " GET " ,
"referenced" : true ,
"size" : 42
},
{
"index" : 5 ,
"name" : " :authority " ,
"value" : " example.org " ,
"referenced" : true ,
"size" : 53
}
],
"size" : 226 ,
"max_size" : 4096 ,
"deflate_size" : 226 ,
"max_deflate_size" : 4096
}
}
,
{
"seq" : 1 ,
"input_length" : 74 ,
"output_length" : 10 ,
"percentage_of_original_size" : 13.513513513513514 ,
"wire" : " 88448504252dd5918485 " ,
"headers" : [
{
":authority" : " example.org "
},
{
":method" : " POST "
},
{
":path" : " /account "
},
{
":scheme" : " https "
},
{
"user-agent" : " nghttp2 "
}
],
"header_table_size" : 4096 ,
"header_table" : {
"entries" : [
{
"index" : 1 ,
"name" : " :method " ,
"value" : " POST " ,
"referenced" : true ,
"size" : 43
},
{
"index" : 2 ,
"name" : " user-agent " ,
"value" : " nghttp2 " ,
"referenced" : true ,
"size" : 49
},
{
"index" : 3 ,
"name" : " :scheme " ,
"value" : " https " ,
"referenced" : true ,
"size" : 44
},
{
"index" : 4 ,
"name" : " :path " ,
"value" : " / " ,
"referenced" : false ,
"size" : 38
},
{
"index" : 5 ,
"name" : " :method " ,
"value" : " GET " ,
"referenced" : false ,
"size" : 42
},
{
"index" : 6 ,
"name" : " :authority " ,
"value" : " example.org " ,
"referenced" : true ,
"size" : 53
}