Esta es una implementación del Protocolo de transferencia de hipertexto versión 2 en C.
La capa de estructura de HTTP/2 se implementa como una biblioteca C reutilizable. Además de eso, hemos implementado un cliente, servidor y proxy HTTP/2. También hemos desarrollado herramientas de prueba de carga y evaluación comparativa para HTTP/2.
Un codificador y decodificador HPACK están disponibles como API pública.
nghttp2 se desarrolló originalmente basándose en RFC 7540 HTTP/2 y RFC 7541 HPACK - Compresión de encabezado para HTTP/2. Ahora estamos actualizando nuestro código para implementar RFC 9113.
La base del código nghttp2 se bifurcó del proyecto spdylay (https://github.com/tatsuhiro-t/spdylay).
Los siguientes puntos finales están disponibles para probar nuestra implementación nghttp2.
https://nghttp2.org/ (TLS + ALPN y HTTP/3)
Este punto final admite h2
, h2-16
, h2-14
y http/1.1
a través de ALPN y requiere TLSv1.2 para la conexión HTTP/2.
También es compatible con HTTP/3.
http://nghttp2.org/ (Actualización HTTP y HTTP/2 Directo)
h2c
y http/1.1
.
Se requiere el siguiente paquete para construir la biblioteca libnghttp2:
Para compilar la documentación, necesita instalar:
Si solo necesita libnghttp2 (biblioteca C), entonces los paquetes anteriores son todo lo que necesita. Utilice --enable-lib-only
para asegurarse de que solo se cree libnghttp2. Esto evita posibles errores de compilación relacionados con la creación de aplicaciones empaquetadas.
Para compilar y ejecutar los programas de aplicación ( nghttp
, nghttpd
, nghttpx
y h2load
) en el directorio src
, se requieren los siguientes paquetes:
Para habilitar la opción -a
(obtener recursos vinculados del recurso descargado) en nghttp
, se requiere el siguiente paquete:
Para habilitar la compatibilidad con systemd en nghttpx, se requiere el siguiente paquete:
Las herramientas HPACK requieren el siguiente paquete:
Para crear fuentes en el directorio de ejemplos, se requiere libevent:
Para mitigar la fragmentación del montón en programas de servidor de larga ejecución ( nghttpd
y nghttpx
), se recomienda jemalloc:
jemalloc
Nota
Actualmente, Alpine Linux no admite el reemplazo de malloc debido a limitaciones de musl. Consulte los detalles en el número 762.
Para BoringSSL o aws-lc build, para habilitar la compresión de certificados TLS RFC 8879 en aplicaciones, se requiere la siguiente biblioteca:
Para habilitar la compatibilidad con mruby para nghttpx, se requiere mruby. Necesitamos compilar mruby con C++ ABI explícitamente activado, y probablemente necesitemos otros mrgems, mruby es administrado por el submódulo git en el directorio de terceros/mruby. Actualmente, la compatibilidad con mruby para nghttpx está deshabilitada de forma predeterminada. Para habilitar la compatibilidad con mruby, utilice la opción de configuración --with-mruby
. Tenga en cuenta que al momento de escribir este artículo, los paquetes libmruby-dev y mruby en Debian/Ubuntu no se pueden utilizar para nghttp2, ya que no habilitan C++ ABI. Para construir mruby, se requieren los siguientes paquetes:
nghttpx admite el motor de separación de privilegios neverbleed para OpenSSL. En resumen, minimiza el riesgo de fuga de clave privada cuando se explota un error grave como Heartbleed. Neverbleed está deshabilitado de forma predeterminada. Para habilitarlo, use la opción de configuración --with-neverbleed
.
Para habilitar el soporte experimental de HTTP/3 para h2load y nghttpx, se requieren las siguientes bibliotecas:
Utilice la opción de configuración --enable-http3
para habilitar la función HTTP/3 para h2load y nghttpx.
Para crear un programa eBPF opcional para dirigir un datagrama QUIC UDP entrante a un socket correcto para nghttpx, se requieren las siguientes bibliotecas:
Utilice la opción de configuración --with-libbpf
para crear el programa eBPF. Se necesita libelf-dev para construir libbpf.
Para Ubuntu 20.04, puede compilar libbpf a partir del código fuente. nghttpx requiere el programa eBPF para recargar su configuración e intercambiar en caliente su ejecutable.
La compilación del código fuente C de libnghttp2 requiere un compilador C99. Se sabe que gcc 4.8 es adecuado. Para compilar el código fuente de C++, se requiere un compilador compatible con C++ 20. Se sabe que al menos g++ >= 12 y clang++ >= 15 funcionan.
Nota
Para habilitar la compatibilidad con mruby en nghttpx, utilice la opción de configuración --with-mruby
.
Nota
Los usuarios de Mac OS X pueden necesitar la opción de configuración --disable-threads
para desactivar los subprocesos múltiples en nghttpd, nghttpx y h2load para evitar que fallen. Se agradece un parche para que los subprocesos múltiples funcionen en la plataforma Mac OS X.
Nota
Para compilar las aplicaciones asociadas (nghttp, nghttpd, nghttpx y h2load), debe utilizar la opción de configuración --enable-app
y asegurarse de que se cumplan los requisitos especificados anteriormente. Normalmente, configure las comprobaciones de secuencias de comandos de las dependencias necesarias para crear estas aplicaciones y habilite --enable-app
automáticamente, para que no tenga que usarlo explícitamente. Pero si descubrió que las aplicaciones no se crearon, entonces el uso de --enable-app
puede encontrar esa causa, como la dependencia faltante.
Nota
Para detectar bibliotecas de terceros, se usa pkg-config (sin embargo, no usamos pkg-config para algunas bibliotecas (por ejemplo, libev)). De forma predeterminada, pkg-config busca el archivo *.pc
en las ubicaciones estándar (por ejemplo, /usr/lib/pkgconfig). Si es necesario utilizar el archivo *.pc
en la ubicación personalizada, especifique las rutas a la variable de entorno PKG_CONFIG_PATH
y pásela al script de configuración, así:
$ ./configure PKG_CONFIG_PATH=/ruta/a/pkgconfig
Para las bibliotecas administradas pkg-config, se definen las variables de entorno *_CFLAG
y *_LIBS
(por ejemplo, OPENSSL_CFLAGS
, OPENSSL_LIBS
). Especificar una cadena no vacía para estas variables anula completamente pkg-config. En otras palabras, si se especifican, pkg-config no se utiliza para la detección y el usuario es responsable de especificar los valores correctos para estas variables. Para obtener una lista completa de estas variables, ejecute ./configure -h
.
Si está utilizando Ubuntu 22.04 LTS, ejecute lo siguiente para instalar los paquetes necesarios:
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 bisonte difamación-dev
El proyecto nghttp2 publica periódicamente archivos tar que incluyen el código fuente de nghttp2 y archivos de compilación generados. Se pueden descargar desde la página de Lanzamientos.
La construcción de nghttp2 desde git requiere paquetes de desarrollo de autotools. Construir a partir de archivos tar no los requiere y, por lo tanto, es mucho más fácil. El paso de construcción habitual es el siguiente:
$ tar xf nghttp2-XYZtar.bz2
$ cd nghttp2-XYZ
$ ./configurar
$ hacer
Construir desde git es fácil, pero asegúrese de utilizar al menos autoconf 2.68:
$ actualización del submódulo git --init
$ autorconf -i
$ automake
$ configuración automática
$ ./configurar
$ hacer
La forma más sencilla de crear una dll nghttp2 nativa de Windows es utilizar cmake. La versión gratuita de Visual C++ Build Tools funciona bien.
cmake
.cmake --build
para construir la biblioteca.Tenga en cuenta que lo más probable es que los pasos anteriores produzcan únicamente la biblioteca nghttp2. No se compilan aplicaciones empaquetadas.
En el entorno Mingw, solo puede compilar la biblioteca, es libnghttp2-X.dll
y libnghttp2.a
.
Si desea compilar las aplicaciones ( h2load
, nghttp
, nghttpx
, nghttpd
), debe utilizar el entorno Cygwin.
En el entorno Cygwin, para compilar las aplicaciones, primero debe compilar e instalar libev.
En segundo lugar, debe anular la definición de la macro __STRICT_ANSI__
; de lo contrario, las funciones fdopen
, fileno
y strptime
no estarán disponibles.
el comando de muestra como este:
$ exportar CFLAGS="-U__STRICT_ANSI__ -I$libev_PREFIX/include -L$libev_PREFIX/lib"
$ exportar CXXFLAGS=$CFLAGS
$ ./configurar
$ hacer
Si desea compilar las aplicaciones en examples/
, debe eliminar o cambiar el nombre de event.h
de la instalación de libev, porque entra en conflicto con la instalación de libevent.
Después de instalar el conjunto de herramientas nghttp2 con make install
es posible que se experimente un error similar:
nghttpx: error al cargar bibliotecas compartidas: libnghttp2.so.14: no se puede abrir el archivo de objeto compartido: no existe tal archivo o directorio
Esto significa que la herramienta no puede localizar la biblioteca compartida libnghttp2.so
.
Para actualizar la caché de la biblioteca compartida, ejecute sudo ldconfig
.
Nota
La documentación aún está incompleta.
Para construir la documentación, ejecute:
$ hacer html
Los documentos se generarán en doc/manual/html/
.
Los documentos generados no se instalarán con make install
.
La documentación en línea está disponible en https://nghttp2.org/documentation/
Para compilar h2load y nghttpx con la función HTTP/3 habilitada, ejecute el script de configuración con --enable-http3
.
Para que nghttpx recargue las configuraciones e intercambie su ejecutable mientras finaliza correctamente los procesos de trabajo antiguos, se requiere eBPF. Ejecute el script de configuración con --enable-http3 --with-libbpf
para crear el programa eBPF. El material de claves QUIC debe configurarse con --frontend-quic-secret-file
para mantener activas las conexiones existentes durante la recarga.
A continuación se detallan los pasos para construir h2load y nghttpx habilitados para HTTP/3.
Construya aws-lc:
$ git clon --profundidad 1 -b v1.39.0 https://github.com/aws/aws-lc
$ cd aws-lc
$ cmake -B build -DDISABLE_GO=ON --install-prefix=$PWD/opt
$ hacer -j$(nproc) -C construir
$ cmake --instalar compilación
$cd..
Construya nghttp3:
$ git clon --profundidad 1 -b v1.6.0 https://github.com/ngtcp2/nghttp3
$ cd nghttp3
$ actualización del submódulo git --init --profundidad 1
$ autorconf -i
$ ./configure --prefix=$PWD/build --enable-lib-only
$ hacer -j$(nproc)
$ hacer instalación
$cd..
Construya ngtcp2:
$ git clon --profundidad 1 -b v1.9.1 https://github.com/ngtcp2/ngtcp2
$ cd ngtcp2
$ actualización del submódulo git --init --profundidad 1
$ autorconf -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"
$ hacer -j$(nproc)
$ hacer instalación
$cd..
Si su distribución de Linux no tiene libbpf-dev >= 0.7.0, compílelo desde el código fuente:
$ git clon --profundidad 1 -b v1.4.6 https://github.com/libbpf/libbpf
$ cd libbpf
$ PREFIX=$PWD/build make -C src instalar
$cd..
Construya nghttp2:
$ git clon https://github.com/nghttp2/nghttp2
$ cd nghttp2
$ actualización del submódulo git --init
$ autorconf -i
$ ./configure --with-mruby --enable-http3 --with-libbpf
CC=sonido metálico-15 CXX=sonido metálico++-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"
$ hacer -j$(nproc)
El programa eBPF reuseport_kern.o
debe encontrarse en el directorio bpf. Pase la opción --quic-bpf-program-file=bpf/reuseport_kern.o
a nghttpx para cargarlo. Consulte también la sección HTTP/3 en nghttpx - Proxy HTTP/2 - CÓMO.
Las pruebas unitarias se realizan simplemente ejecutando make check
.
Tenemos las pruebas de integración para el servidor proxy nghttpx. Las pruebas están escritas en el lenguaje de programación Go y utilizan su marco de prueba. Dependemos de las siguientes bibliotecas:
Los módulos Go descargarán estas dependencias automáticamente.
Para ejecutar las pruebas, ejecute el siguiente comando en el directorio integration-tests
:
$ hazlo
Dentro de las pruebas, utilizamos el puerto 3009 para ejecutar el servidor sujeto de prueba.
nghttp2 v1.0.0 introdujo varios cambios incompatibles con versiones anteriores. En esta sección, describimos estos cambios y cómo migrar a la versión 1.0.0.
h2
y h2c
Anteriormente anunciamos h2-14
y h2c-14
. v1.0.0 implementa la versión final del protocolo y cambiamos ALPN ID a h2
y h2c
. Las macros NGHTTP2_PROTO_VERSION_ID
, NGHTTP2_PROTO_VERSION_ID_LEN
, NGHTTP2_CLEARTEXT_PROTO_VERSION_ID
y NGHTTP2_CLEARTEXT_PROTO_VERSION_ID_LEN
se han actualizado para reflejar este cambio.
Básicamente, las aplicaciones existentes no tienen que hacer nada, simplemente recompilarlas es suficiente para este cambio.
Usamos "prefacio de conexión del cliente" para referirnos a los primeros 24 bytes del prefacio de la conexión del cliente. Esto técnicamente no es correcto, ya que el prefacio de la conexión del cliente se compone de una cadena de bytes mágicos del cliente de 24 bytes seguida del marco de CONFIGURACIÓN. Para aclarar, llamamos "magia del cliente" a esta cadena de 24 bytes y API actualizada.
NGHTTP2_CLIENT_CONNECTION_PREFACE
fue reemplazado por NGHTTP2_CLIENT_MAGIC
.NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN
fue reemplazado por NGHTTP2_CLIENT_MAGIC_LEN
.NGHTTP2_BAD_PREFACE
pasó a llamarse NGHTTP2_BAD_CLIENT_MAGIC
Se eliminaron los ya obsoletos NGHTTP2_CLIENT_CONNECTION_HEADER
y NGHTTP2_CLIENT_CONNECTION_HEADER_LEN
.
Si la aplicación utiliza estas macros, simplemente reemplace las antiguas por otras nuevas. Desde la versión 1.0.0, la magia del cliente se envía mediante la biblioteca (consulte la siguiente subsección), por lo que la aplicación del cliente puede simplemente eliminar el uso de estas macros.
Anteriormente, la biblioteca nghttp2 no enviaba magia del cliente, que es la primera cadena de 24 bytes del prefacio de la conexión del cliente, y las aplicaciones del cliente tienen que enviarla por sí mismas. Desde v1.0.0, la biblioteca envía la magia del cliente mediante la primera llamada de nghttp2_session_send()
o nghttp2_session_mem_send2()
.
Las aplicaciones cliente que envían magia de cliente deben eliminar el código correspondiente.
La especificación Alt-Svc aún no está finalizada. Para que nuestra API sea estable, hemos decidido eliminar todas las API relacionadas con Alt-Svc de nghttp2.
NGHTTP2_EXT_ALTSVC
fue eliminado.nghttp2_ext_altsvc
fue eliminado.Ya hemos eliminado la funcionalidad de Alt-Svc en la serie v0.7 y esencialmente han sido inútiles. La aplicación que utiliza estas macros y estructuras elimina esas líneas.
Anteriormente, nghttp2_on_invalid_frame_recv_cb_called
tomaba el error_code
, definido en nghttp2_error_code
, como parámetro. Pero no son lo suficientemente detallados como para depurarlos. Por lo tanto, decidimos utilizar valores nghttp2_error
más detallados.
La aplicación que utiliza esta devolución de llamada debe actualizar la firma de la devolución de llamada. Si trata error_code
como código de error HTTP/2, actualice el código para que se trate como nghttp2_error
.
Anteriormente, nghttp2 no procesaba la magia del cliente (cadena de bytes de 24 bytes). Para solucionarlo, tuvimos que usar nghttp2_option_set_recv_client_preface()
. Desde v1.0.0, nghttp2 procesa la magia del cliente de forma predeterminada y se eliminó nghttp2_option_set_recv_client_preface()
.
Es posible que alguna aplicación quiera desactivar este comportamiento, por lo que agregamos nghttp2_option_set_no_recv_client_magic()
para lograrlo.
La aplicación que utiliza nghttp2_option_set_recv_client_preface()
con un valor distinto de cero, simplemente elimínela.
La aplicación que usa nghttp2_option_set_recv_client_preface()
con valor cero o que no lo usa debe usar nghttp2_option_set_no_recv_client_magic()
con valor distinto de cero.
El directorio src
contiene los programas de cliente, servidor y proxy HTTP/2.
nghttp
es un cliente HTTP/2. Puede conectarse al servidor HTTP/2 con conocimientos previos, actualización HTTP y extensión ALPN TLS.
Tiene un modo de salida detallado para enmarcar información. A continuación se muestra un resultado de muestra del cliente nghttp
:
$ nghttp -nv https://nghttp2.org
[0.190] Conectado
El protocolo negociado: h2
[0.212] marco de CONFIGURACIÓN de recepción
(niv=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[0.212] enviar cuadro de CONFIGURACIÓN
(niv=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[0.212] enviar cuadro de CONFIGURACIÓN
; ACK
(niv=0)
[0.212] envía trama PRIORIDAD
(dep_stream_id=0, peso=201, exclusivo=0)
[0.212] envía trama PRIORIDAD
(dep_stream_id=0, peso=101, exclusivo=0)
[0.212] envía trama PRIORIDAD
(dep_stream_id=0, peso=1, exclusivo=0)
[0.212] envía trama PRIORIDAD
(dep_stream_id=7, peso=1, exclusivo=0)
[0.212] envía trama PRIORIDAD
(dep_stream_id=3, peso=1, exclusivo=0)
[0.212] envía el marco HEADERS
; END_STREAM | END_HEADERS | PRIORIDAD
(padlen=0, dep_stream_id=11, peso=16, exclusivo=0)
; Abrir nueva transmisión
:método: OBTENER
:camino: /
:esquema: https
:autoridad: nghttp2.org
aceptar: */*
aceptar codificación: gzip, desinflar
agente de usuario: nghttp2/1.0.1-DEV
[0.221] marco de CONFIGURACIÓN de recepción
; ACK
(niv=0)
[0.221] recv (stream_id=13): método: OBTENER
[0.221] recv (stream_id=13): esquema: https
[0.221] recv (stream_id=13): ruta: /stylesheets/screen.css
[0.221] recv (stream_id=13): autoridad: nghttp2.org
[0.221] recv (stream_id=13) aceptar codificación: gzip, deflate
[0.222] recv (stream_id=13) agente de usuario: nghttp2/1.0.1-DEV
[0.222] recv marco PUSH_PROMISE
; END_HEADERS
(padlen=0, prometido_stream_id=2)
[0.222] recv (stream_id=13): estado: 200
[0.222] recv (stream_id=13) fecha: jueves, 21 de mayo de 2015 16:38:14 GMT
[0.222] recv (stream_id=13) tipo de contenido: texto/html
[0.222] recv (stream_id=13) última modificación: viernes, 15 de mayo de 2015 15:38:06 GMT
[0.222] recv (stream_id=13) etag: W/"555612de-19f6"
[0.222] enlace recv (stream_id=13): ; rel=precarga; como=hoja de estilo
[0.222] recv (stream_id=13) codificación de contenido: gzip
[0.222] servidor recv (stream_id=13): nghttpx nghttp2/1.0.1-DEV
[0.222] recv (stream_id=13) vía: 1.1 nghttpx
[0.222] recv (stream_id=13) seguridad-de-transporte-estricta: edad-máxima=31536000
[0.222] recv HEADERS frame
; END_HEADERS
(padlen=0)
; Encabezado de primera respuesta
[0.222] recv trama de DATOS
; END_STREAM
[0.222] recv (stream_id=2): estado: 200
[0.222] recv (stream_id=2) fecha: jueves, 21 de mayo de 2015 16:38:14 GMT
[0.222] recv (stream_id=2) tipo de contenido: texto/css
[0.222] recv (stream_id=2) última modificación: viernes, 15 de mayo de 2015 15:38:06 GMT
[0.222] recv (stream_id=2) etag: W/"555612de-9845"
[0.222] recv (stream_id=2) codificación de contenido: gzip
[0.222] servidor recv (stream_id=2): nghttpx nghttp2/1.0.1-DEV
[0.222] recv (stream_id=2) vía: 1.1 nghttpx
[0.222] recv (stream_id=2) seguridad-de-transporte-estricta: edad-máxima=31536000
[0.222] recv HEADERS frame
; END_HEADERS
(padlen=0)
; Encabezado de respuesta del primer envío
[0.228] recv trama de DATOS
; END_STREAM
[0.228] envía trama GOAWAY
(last_stream_id=2, error_code=NO_ERROR(0x00), opaque_data(0)=[])
La actualización HTTP se realiza así:
$ nghttp -nvu http://nghttp2.org
[0.011] Conectado
[0.011] Solicitud de actualización HTTP
OBTENER / HTTP/1.1
Anfitrión: nghttp2.org
Conexión: Actualización, Configuración HTTP2
Actualización: h2c
Configuración HTTP2: AAMAAABkAAQAAP__
Aceptar: */*
Agente de usuario: nghttp2/1.0.1-DEV
[0.018] Respuesta de actualización HTTP
HTTP/1.1 101 protocolos de conmutación
Conexión: Actualizar
Actualización: h2c
[0.018] Actualización HTTP exitosa
[0.018] marco de CONFIGURACIÓN de recepción
(niv=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[0.018] enviar cuadro de CONFIGURACIÓN
(niv=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[0.018] enviar cuadro de CONFIGURACIÓN
; ACK
(niv=0)
[0.018] envía trama PRIORIDAD
(dep_stream_id=0, peso=201, exclusivo=0)
[0.018] envía trama PRIORIDAD
(dep_stream_id=0, peso=101, exclusivo=0)
[0.018] envía trama PRIORIDAD
(dep_stream_id=0, peso=1, exclusivo=0)
[0.018] envía trama PRIORIDAD
(dep_stream_id=7, peso=1, exclusivo=0)
[0.018] envía trama PRIORIDAD
(dep_stream_id=3, peso=1, exclusivo=0)
[0.018] envía trama PRIORIDAD
(dep_stream_id=11, peso=16, exclusivo=0)
[0.019] recv (stream_id=1): método: OBTENER
[0.019] recv (stream_id=1): esquema: http
[0.019] recv (stream_id=1): ruta: /stylesheets/screen.css
[0.019] recv (stream_id=1) host: nghttp2.org
[0.019] recv (stream_id=1) agente de usuario: nghttp2/1.0.1-DEV
[0.019] recv marco PUSH_PROMISE
; END_HEADERS
(padlen=0, prometido_stream_id=2)
[0.019] recv (stream_id=1): estado: 200
[0.019] recv (stream_id=1) fecha: jueves, 21 de mayo de 2015 16:39:16 GMT
[0.019] recv (stream_id=1) tipo de contenido: texto/html
[0.019] recv (stream_id=1) longitud del contenido: 6646
[0.019] recv (stream_id=1) última modificación: viernes, 15 de mayo de 2015 15:38:06 GMT
[0.019] recv (stream_id=1) etag: "555612de-19f6"
[0.019] enlace recv (stream_id=1): ; rel=precarga; como=hoja de estilo
[0.019] recv (stream_id=1) rangos de aceptación: bytes
[0.019] recv (stream_id=1) servidor: nghttpx nghttp2/1.0.1-DEV
[0.019] recv (stream_id=1) vía: 1.1 nghttpx
[0.019] recv HEADERS frame
; END_HEADERS
(padlen=0)
; Encabezado de primera respuesta
[0.019] recv trama de DATOS
; END_STREAM
[0.019] recv (stream_id=2): estado: 200
[0.019] recv (stream_id=2) fecha: jueves, 21 de mayo de 2015 16:39:16 GMT
[0.019] recv (stream_id=2) tipo de contenido: texto/css
[0.019] recv (stream_id=2) longitud del contenido: 38981
[0.019] recv (stream_id=2) última modificación: viernes, 15 de mayo de 2015 15:38:06 GMT
[0.019] recv (stream_id=2) etag: "555612de-9845"
[0.019] recv (stream_id=2) rangos de aceptación: bytes
[0.019] servidor recv (stream_id=2): nghttpx nghttp2/1.0.1-DEV
[0.019] recv (stream_id=2) vía: 1.1 nghttpx
[0.019] recv HEADERS frame
; END_HEADERS
(padlen=0)
; Encabezado de respuesta del primer envío
[0.026] recv trama de DATOS
[0.027] recv trama de DATOS
[0.027] enviar trama WINDOW_UPDATE
(incremento_tamaño_ventana=33343)
[0.032] enviar trama WINDOW_UPDATE
(incremento_tamaño_ventana=33707)
[0.032] recv trama de DATOS
; END_STREAM
[0.032] marco de CONFIGURACIÓN de recepción
; ACK
(niv=0)
[0.032] envía trama GOAWAY
(last_stream_id=2, error_code=NO_ERROR(0x00), opaque_data(0)=[])
Usando la opción -s
, nghttp
imprime información de tiempo para las solicitudes, ordenada por tiempo de finalización:
$ nghttp -nas https://nghttp2.org/
***** Estadísticas *****
Horario de solicitud:
fin de respuesta: la hora en la que se recibió el último byte de respuesta
relativo a connectEnd
requestStart: el tiempo justo antes de que se enviara el primer byte de la solicitud
relativo a connectEnd. Si se muestra '*', esto fue
empujado por el servidor.
proceso: respuestaFin - solicitudInicio
código: código de estado HTTP
tamaño: número de bytes recibidos como cuerpo de respuesta sin
inflación.
URI: solicitar URI
ver http://www.w3.org/TR/resource-timing/#processing-model
ordenado por 'completo'
ID de respuestaFinalizar solicitudIniciar código de proceso tamaño ruta de solicitud
13 +37,19ms +280us 36,91ms 200 2K /
2 +72,65 ms * +36,38 ms 36,26 ms 200 8K /hojas de estilo/pantalla.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
Usando la opción -r
, nghttp
escribe datos de tiempo más detallados en el archivo dado en formato HAR.
nghttpd
es un servidor web estático de subprocesos múltiples.
De forma predeterminada, utiliza una conexión SSL/TLS. Utilice la opción --no-tls
para desactivarla.
nghttpd
solo acepta conexiones HTTP/2 a través de ALPN o conexiones HTTP/2 directas. No se admite ninguna actualización HTTP.
La opción -p
permite a los usuarios configurar la inserción del servidor.
Al igual que nghttp
, tiene un modo de salida detallado para enmarcar información. Aquí hay un ejemplo de salida de nghttpd
:
$ nghttpd --no-tls -v 8080
IPv4: escuchar 0.0.0.0:8080
IPv6: escuchar :::8080
[id=1] [1.521] enviar cuadro de CONFIGURACIÓN
(niv=1)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[id=1] [ 1.521] marco de CONFIGURACIÓN de recepción
(niv=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[id=1] [ 1.521] marco de CONFIGURACIÓN de recepción
; ACK
(niv=0)
[id=1] [ 1.521] recv trama PRIORIDAD
(dep_stream_id=0, peso=201, exclusivo=0)
[id=1] [ 1.521] recv trama PRIORIDAD
(dep_stream_id=0, peso=101, exclusivo=0)
[id=1] [ 1.521] recv trama PRIORIDAD
(dep_stream_id=0, peso=1, exclusivo=0)
[id=1] [ 1.521] recv trama PRIORIDAD
(dep_stream_id=7, peso=1, exclusivo=0)
[id=1] [ 1.521] recv trama PRIORIDAD
(dep_stream_id=3, peso=1, exclusivo=0)
[id=1] [1.521] recv (stream_id=13): método: OBTENER
[id=1] [ 1.521] recv (stream_id=13) :ruta: /
[id=1] [1.521] recv (stream_id=13): esquema: http
[id=1] [1.521] recv (stream_id=13): autoridad: localhost:8080
[id=1] [ 1.521] recv (stream_id=13) aceptar: */*
[id=1] [1.521] recv (stream_id=13) aceptar codificación: gzip, deflate
[id=1] [1.521] recv (stream_id=13) agente de usuario: nghttp2/1.0.0-DEV
[id=1] [ 1.521] recv HEADERS marco
; END_STREAM | END_HEADERS | PRIORIDAD
(padlen=0, dep_stream_id=11, peso=16, exclusivo=0)
; Abrir nueva transmisión
[id=1] [1.521] enviar cuadro de CONFIGURACIÓN
; ACK
(niv=0)
[id=1] [1.521] enviar trama HEADERS
; END_HEADERS
(padlen=0)
; Encabezado de primera respuesta
:estado: 200
servidor: nghttpd nghttp2/1.0.0-DEV
longitud del contenido: 10
control de caché: edad máxima = 3600
fecha: viernes 15 de mayo de 2015 14:49:04 GMT
última modificación: martes, 30 de septiembre de 2014 12:40:52 GMT
[id=1] [1.522] enviar trama de DATOS
; END_STREAM
[id=1] [ 1.522] stream_id=13 cerrado
[id=1] [1.522] recv trama GOAWAY
(last_stream_id=0, error_code=NO_ERROR(0x00), opaque_data(0)=[])
[id=1] [ 1.522] cerrado
nghttpx
es un proxy inverso de subprocesos múltiples para HTTP/3, HTTP/2 y HTTP/1.1, impulsa http://nghttp2.org y admite la inserción del servidor HTTP/2.
Modificamos la interfaz de línea de comandos nghttpx
y, como resultado, hay varios archivos incompatibles desde 1.8.0 o anteriores. Esto es necesario para ampliar su capacidad y garantizar más mejoras de funciones en la versión futura. Lea Migración desde nghttpx v1.8.0 o anterior para saber cómo migrar desde versiones anteriores.
nghttpx
implementa importantes funciones orientadas al rendimiento en TLS, como ID de sesión, tickets de sesión (con rotación automática de claves), grapado OCSP, tamaño de registro dinámico, ALPN, secreto directo y HTTP/2. nghttpx
también ofrece la funcionalidad de compartir caché de sesión y claves de ticket entre múltiples instancias nghttpx
a través de memcached.
nghttpx
tiene 2 modos de operación:
Opción de modo | Interfaz | backend | Nota |
---|---|---|---|
modo predeterminado | HTTP/3, HTTP/2, HTTP/1.1 | HTTP/1.1, HTTP/2 | proxy inverso |
--http2-proxy | HTTP/3, HTTP/2, HTTP/1.1 | HTTP/1.1, HTTP/2 | proxy directo |
El modo interesante en este momento es el modo predeterminado. Funciona como un proxy inverso y escucha HTTP/3, HTTP/2 y HTTP/1.1 y se puede implementar como un terminador SSL/TLS para un servidor web existente.
En todos los modos, las conexiones frontend están cifradas mediante SSL/TLS de forma predeterminada. Para deshabilitar el cifrado, use la palabra clave no-tls
en la opción --frontend
. Si el cifrado está deshabilitado, las conexiones HTTP/1.1 entrantes se pueden actualizar a HTTP/2 mediante la actualización HTTP. Por otro lado, las conexiones backend no están cifradas de forma predeterminada. Para cifrar conexiones de backend, use la palabra clave tls
en la opción --backend
.
nghttpx
admite un archivo de configuración. Consulte la opción --conf
y el archivo de configuración de muestra nghttpx.conf.sample
.
En el modo predeterminado, nghttpx
funciona como proxy inverso para el servidor backend:
Cliente <-- (HTTP/3, HTTP/2, HTTP/1.1) --> nghttpx <-- (HTTP/1.1, HTTP/2) --> Servidor web
[proxy inverso]
Con la opción --http2-proxy
, funciona como proxy directo y se denomina proxy HTTP/2 seguro:
Cliente <-- (HTTP/3, HTTP/2, HTTP/1.1) --> nghttpx <-- (HTTP/1.1) --> Proxy
[proxy seguro] (p. ej., Squid, ATS)
El Client
del ejemplo anterior debe configurarse para utilizar nghttpx
como proxy seguro.
En el momento de escribir este artículo, tanto Chrome como Firefox admiten el proxy HTTP/2 seguro. Una forma de configurar Chrome para usar un proxy seguro es crear un script proxy.pac como este:
function FindProxyForURL ( url , host ) {
return "HTTPS SERVERADDR:PORT" ;
}
SERVERADDR
y PORT
son el nombre de host/dirección y el puerto de la máquina en la que se ejecuta nghttpx. Tenga en cuenta que Chrome requiere un certificado válido para un proxy seguro.
Luego ejecute Chrome con los siguientes argumentos:
$ google-chrome --proxy-pac-url=file:///path/to/proxy.pac --use-npn
Las conexiones HTTP/2 de backend se pueden canalizar a través de un proxy HTTP. El proxy se especifica mediante --backend-http-proxy-uri
. La siguiente figura ilustra cómo nghttpx se comunica con el proxy HTTP/2 externo a través de un proxy HTTP:
Cliente <-- (HTTP/3, HTTP/2, HTTP/1.1) --> nghttpx <-- (HTTP/2) --
--====================---> Proxy HTTP/2
(túnel de proxy HTTP) (p. ej., nghttpx -s)
El programa h2load
es una herramienta de evaluación comparativa para HTTP/3, HTTP/2 y HTTP/1.1. La interfaz de usuario de h2load
está fuertemente inspirada en weighttp
(https://github.com/lighttpd/weighttp). El uso típico es el siguiente:
$ h2load -n100000 -c100 -m100 https://localhost:8443/
punto de referencia inicial...
hilo de generación #0: 100 clientes simultáneos, 100000 solicitudes en total
Protocolo: TLSv1.2
Cifrado: ECDHE-RSA-AES128-GCM-SHA256
Clave temporal del servidor: ECDH P-256 256 bits
progreso: 10% hecho
progreso: 20% hecho
progreso: 30% hecho
progreso: 40% hecho
progreso: 50% hecho
progreso: 60% hecho
progreso: 70% hecho
progreso: 80% hecho
progreso: 90% hecho
progreso: 100% hecho
terminado en 771,26 ms, 129658 solicitudes/s, 4,71 MB/s
solicitudes: 100000 en total, 100000 iniciadas, 100000 realizadas, 100000 exitosas, 0 fallidas, 0 con errores
códigos de estado: 100000 2xx, 0 3xx, 0 4xx, 0 5xx
tráfico: 3812300 bytes en total, 1009900 bytes de encabezados, 1000000 bytes de datos
mín máx media sd +/- sd
tiempo de solicitud: 25.12ms 124.55ms 51.07ms 15.36ms 84.87%
tiempo de conexión: 208,94 ms 254,67 ms 241,38 ms 7,95 ms 63,00 %
tiempo hasta el 1er byte: 209,11 ms 254,80 ms 241,51 ms 7,94 ms 63,00 %
El ejemplo anterior emitió un total de 100.000 solicitudes, utilizando 100 clientes simultáneos (en otras palabras, 100 sesiones HTTP/2) y un máximo de 100 transmisiones por cliente. Con la opción -t
, h2load
utilizará múltiples subprocesos nativos para evitar saturar un solo núcleo en el lado del cliente.
Advertencia
No utilice esta herramienta en servidores disponibles públicamente. Eso se considera un ataque de DOS. Úselo solo contra sus servidores privados.
Si el HTTP/3 experimental está habilitado, h2load puede enviar solicitudes al servidor HTTP/3. Para hacer esto, especifique h3
en la opción --alpn-list
así:
$ h2load --alpn-lista h3 https://127.0.0.1:4433
Para nghttp2 v1.58 o anterior, use --npn-list
en lugar de --alpn-list
.
El directorio src
contiene las herramientas HPACK. El programa deflatehd
es una herramienta de compresión de encabezados de línea de comandos. El programa inflatehd
es una herramienta de descompresión de encabezados de línea de comandos. Ambas herramientas leen la entrada de stdin y escriben la salida en stdout. Los errores se escriben en stderr. Toman JSON como entrada y salida. Usamos (principalmente) el mismo formato de datos JSON descrito en https://github.com/http2jp/hpack-test-case.
El programa deflatehd
lee datos JSON o campos de encabezado de estilo HTTP/1 de Stdin y sale el bloque de encabezado comprimido en JSON.
Para la entrada JSON, el objeto JSON raíz debe incluir una clave cases
. Su valor debe incluir la secuencia del conjunto de encabezados de entrada. Comparten el mismo contexto de compresión y se procesan en el orden en que aparecen. Cada elemento en la secuencia es un objeto JSON y debe incluir una tecla headers
. Su valor es una matriz de objetos JSON, que incluye exactamente un par de nombre/valor.
Ejemplo:
{
"cases" :
[
{
"headers" : [
{ ":method" : " GET " },
{ ":path" : " / " }
]
},
{
"headers" : [
{ ":method" : " POST " },
{ ":path" : " / " }
]
}
]
}
Con la opción -t
, el programa puede aceptar bloques de campo de encabezado HTTP/1 más familiares. Cada conjunto de encabezado está delimitado por una línea vacía:
Ejemplo:
: método: obtener
: esquema: https
:camino: /
: método: publicar
agente de usuario: NGHTTP2
La salida está en objeto JSON. Debe incluir una clave cases
y su valor es una matriz de objetos JSON, que tiene al menos las siguientes claves:
output_length
/ input_length
* 100Ejemplos:
{
"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 salida se puede usar como entrada para inflatehd
y deflatehd
.
Con la opción -d
, se agrega la tecla header_table
adicional y su valor asociado incluye el estado de la tabla de encabezado dinámico después de que se procesó el conjunto de encabezado correspondiente. El valor incluye al menos las siguientes claves:
referenced
es true
, está en el conjunto de referencia. El size
incluye la sobrecarga (32 bytes). El index
corresponde al índice de la tabla de encabezado. El name
es el nombre del campo del encabezado y el value
es el valor del campo del encabezado.max_deflate_size
.max_size
. En este caso, el codificador solo usa hasta First max_deflate_size
Buffer. Dado que el tamaño de la tabla de encabezado sigue siendo max_size
, el codificador debe realizar un seguimiento de las entradas fuera del max_deflate_size
pero dentro del max_size
y asegurarse de que ya no sean referenciadas.Ejemplo:
{
"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
}