이는 C에서 Hypertext Transfer Protocol 버전 2를 구현한 것입니다.
HTTP/2의 프레이밍 계층은 재사용 가능한 C 라이브러리로 구현됩니다. 또한 우리는 HTTP/2 클라이언트, 서버 및 프록시를 구현했습니다. 우리는 또한 HTTP/2에 대한 부하 테스트 및 벤치마킹 도구를 개발했습니다.
HPACK 인코더와 디코더는 공개 API로 제공됩니다.
nghttp2는 원래 RFC 7540 HTTP/2 및 RFC 7541 HPACK(HTTP/2용 헤더 압축)을 기반으로 개발되었습니다. 이제 RFC 9113을 구현하기 위해 코드를 업데이트하고 있습니다.
nghttp2 코드 베이스는 spdylay(https://github.com/tatsuhiro-t/spdylay) 프로젝트에서 분기되었습니다.
nghttp2 구현을 시험해 보는 데 다음 끝점을 사용할 수 있습니다.
https://nghttp2.org/(TLS + ALPN 및 HTTP/3)
이 엔드포인트는 ALPN을 통해 h2
, h2-16
, h2-14
및 http/1.1
지원하며 HTTP/2 연결을 위해 TLSv1.2가 필요합니다.
HTTP/3도 지원합니다.
http://nghttp2.org/(HTTP 업그레이드 및 HTTP/2 다이렉트)
h2c
및 http/1.1
.
libnghttp2 라이브러리를 빌드하려면 다음 패키지가 필요합니다.
문서를 작성하려면 다음을 설치해야 합니다.
libnghttp2(C 라이브러리)만 필요한 경우 위 패키지만 있으면 됩니다. libnghttp2만 빌드되도록 하려면 --enable-lib-only
사용하십시오. 이렇게 하면 번들 애플리케이션 빌드와 관련된 잠재적인 빌드 오류를 방지할 수 있습니다.
src
디렉터리에 응용 프로그램( nghttp
, nghttpd
, nghttpx
및 h2load
)을 빌드하고 실행하려면 다음 패키지가 필요합니다.
nghttp
에서 -a
옵션(다운로드한 리소스에서 연결된 자산 가져오기)을 활성화하려면 다음 패키지가 필요합니다.
nghttpx에서 시스템 지원을 활성화하려면 다음 패키지가 필요합니다.
HPACK 도구에는 다음 패키지가 필요합니다.
예제 디렉토리 아래에 소스를 빌드하려면 libevent가 필요합니다.
장기 실행 서버 프로그램( nghttpd
및 nghttpx
)에서 힙 조각화를 완화하려면 jemalloc을 권장합니다.
제말록
메모
Alpine Linux는 현재 musl 제한으로 인해 malloc 대체를 지원하지 않습니다. 자세한 내용은 문제 #762를 참조하세요.
BoringSSL 또는 aws-lc 빌드의 경우 애플리케이션에서 RFC 8879 TLS 인증서 압축을 활성화하려면 다음 라이브러리가 필요합니다.
nghttpx에 대한 mruby 지원을 활성화하려면 mruby가 필요합니다. 우리는 C++ ABI를 명시적으로 활성화하여 mruby를 빌드해야 하며 아마도 다른 mrgems가 필요할 수 있습니다. mruby는 third-party/mruby 디렉토리 아래의 git 하위 모듈에 의해 관리됩니다. 현재 nghttpx에 대한 mruby 지원은 기본적으로 비활성화되어 있습니다. mruby 지원을 활성화하려면 --with-mruby
구성 옵션을 사용하십시오. 이 글을 쓰는 시점에서 Debian/Ubuntu의 libmruby-dev 및 mruby 패키지는 C++ ABI를 활성화하지 않기 때문에 nghttp2에 사용할 수 없습니다. mruby를 빌드하려면 다음 패키지가 필요합니다.
nghttpx는 OpenSSL을 위한 Neverbleed 권한 분리 엔진을 지원합니다. 즉, Heartbleed와 같은 심각한 버그가 악용될 경우 개인 키 유출 위험을 최소화합니다. Neverbleed는 기본적으로 비활성화되어 있습니다. 이를 활성화하려면 --with-neverbleed
구성 옵션을 사용하십시오.
h2load 및 nghttpx에 대한 실험적 HTTP/3 지원을 활성화하려면 다음 라이브러리가 필요합니다.
h2load 및 nghttpx에 대해 HTTP/3 기능을 활성화하려면 --enable-http3
구성 옵션을 사용하십시오.
들어오는 QUIC UDP 데이터그램을 nghttpx에 대한 올바른 소켓으로 보내기 위한 선택적 eBPF 프로그램을 빌드하려면 다음 라이브러리가 필요합니다.
eBPF 프로그램을 빌드하려면 --with-libbpf
구성 옵션을 사용하세요. libbpf를 빌드하려면 libelf-dev가 필요합니다.
Ubuntu 20.04의 경우 소스 코드에서 libbpf를 빌드할 수 있습니다. nghttpx에는 구성을 다시 로드하고 실행 파일을 핫 스와핑하려면 eBPF 프로그램이 필요합니다.
libnghttp2 C 소스 코드를 컴파일하려면 C99 컴파일러가 필요합니다. gcc 4.8이 적절한 것으로 알려져 있습니다. C++ 소스 코드를 컴파일하려면 C++20 호환 컴파일러가 필요합니다. 최소한 g++ >= 12 및 clang++ >= 15가 작동하는 것으로 알려져 있습니다.
메모
nghttpx에서 mruby 지원을 활성화하려면 --with-mruby
구성 옵션을 사용하세요.
메모
Mac OS X 사용자는 충돌을 방지하기 위해 nghttpd, nghttpx 및 h2load에서 멀티스레딩을 비활성화하려면 --disable-threads
구성 옵션이 필요할 수 있습니다. Mac OS X 플랫폼에서 멀티 스레딩이 작동하도록 패치를 환영합니다.
메모
관련 애플리케이션(nghttp, nghttpd, nghttpx 및 h2load)을 컴파일하려면 --enable-app
구성 옵션을 사용하고 위에 지정된 요구 사항이 충족되는지 확인해야 합니다. 일반적으로 구성 스크립트는 이러한 애플리케이션을 빌드하는 데 필요한 종속성을 확인하고 --enable-app
자동으로 활성화하므로 명시적으로 사용할 필요가 없습니다. 그러나 애플리케이션이 빌드되지 않은 것으로 확인된 경우 --enable-app
사용하면 종속성 누락과 같은 원인을 찾을 수 있습니다.
메모
타사 라이브러리를 감지하기 위해 pkg-config가 사용됩니다(그러나 일부 라이브러리(예: libev)에서는 pkg-config를 사용하지 않습니다). 기본적으로 pkg-config는 표준 위치(예: /usr/lib/pkgconfig)에서 *.pc
파일을 검색합니다. 사용자 정의 위치에서 *.pc
파일을 사용해야 하는 경우 다음과 같이 PKG_CONFIG_PATH
환경 변수에 대한 경로를 지정하고 이를 구성 스크립트에 전달합니다.
$ ./configure PKG_CONFIG_PATH=/path/to/pkgconfig
pkg-config 관리 라이브러리의 경우 *_CFLAG
및 *_LIBS
환경 변수가 정의됩니다(예: OPENSSL_CFLAGS
, OPENSSL_LIBS
). 비어 있지 않은 문자열을 이러한 변수에 지정하면 pkg-config가 완전히 무시됩니다. 즉, 지정하는 경우 pkg-config는 탐지에 사용되지 않으며 사용자는 이러한 변수에 올바른 값을 지정해야 합니다. 이러한 변수의 전체 목록을 보려면 ./configure -h
실행하세요.
Ubuntu 22.04 LTS를 사용하는 경우 다음을 실행하여 필수 패키지를 설치합니다.
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 바이슨 libelf-dev
nghttp2 프로젝트는 nghttp2 소스 코드와 생성된 빌드 파일이 포함된 tar 아카이브를 정기적으로 릴리스합니다. 릴리스 페이지에서 다운로드할 수 있습니다.
git에서 nghttp2를 빌드하려면 autotools 개발 패키지가 필요합니다. tar 아카이브에서 빌드하는 데는 필요하지 않으므로 훨씬 쉽습니다. 일반적인 빌드 단계는 다음과 같습니다.
$ tar xf nghttp2-XYZtar.bz2
$ cd nghttp2-XYZ
$ ./구성
$만들다
Git에서 빌드하는 것은 쉽지만 최소한 autoconf 2.68이 사용되는지 확인하세요.
$ git 하위 모듈 업데이트 --init
$ 자동 재설정 -i
$ 자동 제작
$ 자동 설정
$ ./구성
$만들다
기본 Windows nghttp2 dll을 빌드하는 가장 쉬운 방법은 cmake를 사용하는 것입니다. Visual C++ Build Tools의 무료 버전은 잘 작동합니다.
cmake
실행합니다.cmake --build
실행하여 라이브러리를 빌드합니다.위 단계에서는 nghttp2 라이브러리만 생성될 가능성이 높습니다. 번들 애플리케이션은 컴파일되지 않습니다.
Mingw 환경에서는 libnghttp2-X.dll
및 libnghttp2.a
라이브러리만 컴파일할 수 있습니다.
애플리케이션( h2load
, nghttp
, nghttpx
, nghttpd
)을 컴파일하려면 Cygwin 환경을 사용해야 합니다.
Cygwin 환경에서 애플리케이션을 컴파일하려면 먼저 libev를 컴파일하고 설치해야 합니다.
둘째, 매크로 __STRICT_ANSI__
정의를 해제해야 합니다. 그렇지 않으면 fdopen
, fileno
및 strptime
함수를 사용할 수 없습니다.
샘플 명령은 다음과 같습니다.
$ 내보내기 CFLAGS="-U__STRICT_ANSI__ -I$libev_PREFIX/include -L$libev_PREFIX/lib"
$ 내보내기 CXXFLAGS=$CFLAGS
$ ./구성
$만들다
examples/
에서 애플리케이션을 컴파일하려면 libevent 설치와 충돌하므로 libev 설치에서 event.h
를 제거하거나 이름을 바꿔야 합니다.
make install
사용하여 nghttp2 도구 모음을 설치한 후 비슷한 오류가 발생할 수 있습니다.
nghttpx: 공유 라이브러리를 로드하는 중 오류가 발생했습니다. libnghttp2.so.14: 공유 개체 파일을 열 수 없습니다. 해당 파일이나 디렉터리가 없습니다.
이는 도구가 libnghttp2.so
공유 라이브러리를 찾을 수 없음을 의미합니다.
공유 라이브러리 캐시를 업데이트하려면 sudo ldconfig
실행하세요.
메모
문서가 아직 불완전합니다.
문서를 작성하려면 다음을 실행하세요.
$ HTML 만들기
문서는 doc/manual/html/
아래에 생성됩니다.
생성된 문서는 make install
로 설치되지 않습니다.
온라인 설명서는 https://nghttp2.org/documentation/에서 확인할 수 있습니다.
HTTP/3 기능이 활성화된 h2load 및 nghttpx를 빌드하려면 --enable-http3
사용하여 구성 스크립트를 실행하세요.
nghttpx가 구성을 다시 로드하고 실행 파일을 교체하는 동시에 이전 작업자 프로세스를 정상적으로 종료하려면 eBPF가 필요합니다. eBPF 프로그램을 빌드하려면 --enable-http3 --with-libbpf
와 함께 구성 스크립트를 실행하세요. 다시 로드하는 동안 기존 연결을 유지하려면 --frontend-quic-secret-file
사용하여 QUIC 키 자료를 설정해야 합니다.
HTTP/3 지원 h2load 및 nghttpx를 빌드하는 자세한 단계는 다음과 같습니다.
aws-lc 빌드:
$ git clone --깊이 1 -b v1.39.0 https://github.com/aws/aws-lc
$ cd aws-lc
$ cmake -B 빌드 -DDISABLE_GO=ON --install-prefix=$PWD/opt
$ make -j$(nproc) -C 빌드
$ cmake --설치 빌드
$ CD ..
nghttp3 빌드:
$ git clone --깊이 1 -b v1.6.0 https://github.com/ngtcp2/nghttp3
$ CD NGhttp3
$ git 하위 모듈 업데이트 --init --깊이 1
$ 자동 재설정 -i
$ ./configure --prefix=$PWD/build --enable-lib-only
$ make -j$(nproc)
$ 설치하다
$ CD ..
ngtcp2 빌드:
$ git clone --깊이 1 -b v1.9.1 https://github.com/ngtcp2/ngtcp2
$ CD ngtcp2
$ git 하위 모듈 업데이트 --init --깊이 1
$ 자동 재설정 -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)
$ 설치하다
$ CD ..
Linux 배포판에 libbpf-dev >= 0.7.0이 없으면 소스에서 빌드하세요.
$ git clone --깊이 1 -b v1.4.6 https://github.com/libbpf/libbpf
$ CD libbpf
$ PREFIX=$PWD/build make -C src install
$ CD ..
nghttp2 빌드:
$ 자식 클론 https://github.com/nghttp2/nghttp2
$ cd nghttp2
$ git 하위 모듈 업데이트 --init
$ 자동 재설정 -i
$ ./configure --with-mruby --enable-http3 --with-libbpf
CC=씨랑-15 CXX=씨랑++-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)
eBPF 프로그램 reuseport_kern.o
bpf 디렉토리에서 찾을 수 있습니다. --quic-bpf-program-file=bpf/reuseport_kern.o
옵션을 nghttpx에 전달하여 로드합니다. nghttpx - HTTP/2 프록시 - HOW-TO의 HTTP/3 섹션도 참조하세요.
단위 테스트는 간단히 make check
실행하여 수행됩니다.
nghttpx 프록시 서버에 대한 통합 테스트가 있습니다. 테스트는 Go 프로그래밍 언어로 작성되었으며 해당 테스트 프레임워크를 사용합니다. 우리는 다음 라이브러리에 의존합니다:
Go 모듈은 이러한 종속성을 자동으로 다운로드합니다.
테스트를 실행하려면 integration-tests
디렉터리에서 다음 명령을 실행합니다.
$ 해내세요
테스트 내에서는 포트 3009를 사용하여 테스트 대상 서버를 실행합니다.
nghttp2 v1.0.0에는 이전 버전과 호환되지 않는 몇 가지 변경 사항이 도입되었습니다. 이 섹션에서는 이러한 변경 사항과 v1.0.0으로 마이그레이션하는 방법을 설명합니다.
h2
및 h2c
입니다. 이전에 우리는 h2-14
및 h2c-14
발표했습니다. v1.0.0은 최종 프로토콜 버전을 구현하며 ALPN ID를 h2
및 h2c
로 변경했습니다. 이 변경 사항을 반영하기 위해 매크로 NGHTTP2_PROTO_VERSION_ID
, NGHTTP2_PROTO_VERSION_ID_LEN
, NGHTTP2_CLEARTEXT_PROTO_VERSION_ID
및 NGHTTP2_CLEARTEXT_PROTO_VERSION_ID_LEN
업데이트되었습니다.
기본적으로 기존 애플리케이션은 아무 작업도 수행할 필요가 없으며 재컴파일만 하면 이러한 변경이 가능합니다.
클라이언트 연결 서문의 처음 24바이트를 의미하기 위해 "클라이언트 연결 서문"을 사용합니다. 클라이언트 연결 서문은 24바이트 클라이언트 매직 바이트 문자열과 그 뒤에 오는 SETTINGS 프레임으로 구성되므로 이는 기술적으로 올바르지 않습니다. 설명을 위해 이 24바이트 문자열과 업데이트된 API에 대해 "클라이언트 매직"을 호출합니다.
NGHTTP2_CLIENT_CONNECTION_PREFACE
NGHTTP2_CLIENT_MAGIC
으로 대체되었습니다.NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN
이 NGHTTP2_CLIENT_MAGIC_LEN
으로 대체되었습니다.NGHTTP2_BAD_PREFACE
이름이 NGHTTP2_BAD_CLIENT_MAGIC
으로 변경되었습니다. 이미 더 이상 사용되지 않는 NGHTTP2_CLIENT_CONNECTION_HEADER
및 NGHTTP2_CLIENT_CONNECTION_HEADER_LEN
이 제거되었습니다.
응용 프로그램이 이러한 매크로를 사용하는 경우 기존 매크로를 새 매크로로 바꾸십시오. v1.0.0부터 클라이언트 매직은 라이브러리에 의해 전송되므로(다음 하위 섹션 참조) 클라이언트 애플리케이션은 이러한 매크로 사용을 제거할 수 있습니다.
이전에는 nghttp2 라이브러리가 클라이언트 연결 서문의 첫 24바이트 바이트 문자열인 클라이언트 매직을 보내지 않았으며 클라이언트 애플리케이션이 이를 직접 보내야 했습니다. v1.0.0부터 클라이언트 매직은 nghttp2_session_send()
또는 nghttp2_session_mem_send2()
의 첫 번째 호출을 통해 라이브러리에 의해 전송됩니다.
클라이언트 매직을 보내는 클라이언트 애플리케이션은 관련 코드를 제거해야 합니다.
Alt-Svc 사양은 아직 확정되지 않았습니다. API를 안정적으로 만들기 위해 nghttp2에서 Alt-Svc 관련 API를 모두 제거하기로 결정했습니다.
NGHTTP2_EXT_ALTSVC
가 제거되었습니다.nghttp2_ext_altsvc
제거되었습니다.우리는 이미 v0.7 시리즈에서 Alt-Svc 기능을 제거했으며 본질적으로 아무런 문제가 없습니다. 이러한 매크로와 구조체를 사용하는 애플리케이션은 해당 줄을 제거합니다.
이전에는 nghttp2_on_invalid_frame_recv_cb_called
nghttp2_error_code
에 정의된 error_code
를 매개변수로 사용했습니다. 그러나 디버깅할 만큼 상세하지 않습니다. 따라서 우리는 대신 더 자세한 nghttp2_error
값을 사용하기로 결정했습니다.
이 콜백을 사용하는 애플리케이션은 콜백 서명을 업데이트해야 합니다. error_code
HTTP/2 오류 코드로 처리하는 경우 nghttp2_error
로 처리되도록 코드를 업데이트하세요.
이전에는 nghttp2가 클라이언트 매직(24바이트 바이트 문자열)을 처리하지 않았습니다. 이를 처리하려면 nghttp2_option_set_recv_client_preface()
사용해야 했습니다. v1.0.0부터 nghttp2는 기본적으로 클라이언트 매직을 처리하며 nghttp2_option_set_recv_client_preface()
제거되었습니다.
일부 애플리케이션에서는 이 동작을 비활성화하려고 할 수 있으므로 이를 달성하기 위해 nghttp2_option_set_no_recv_client_magic()
추가했습니다.
0이 아닌 값으로 nghttp2_option_set_recv_client_preface()
사용하는 애플리케이션은 제거하면 됩니다.
0 값으로 nghttp2_option_set_recv_client_preface()
사용하거나 이를 사용하지 않는 애플리케이션은 0이 아닌 값으로 nghttp2_option_set_no_recv_client_magic()
사용해야 합니다.
src
디렉토리에는 HTTP/2 클라이언트, 서버 및 프록시 프로그램이 포함되어 있습니다.
nghttp
HTTP/2 클라이언트입니다. 사전 지식, HTTP 업그레이드 및 ALPN TLS 확장을 통해 HTTP/2 서버에 연결할 수 있습니다.
정보 프레이밍을 위한 자세한 출력 모드가 있습니다. 다음은 nghttp
클라이언트의 샘플 출력입니다.
$ nghttp -nv https://nghttp2.org
[ 0.190] 연결됨
협상된 프로토콜: h2
[ 0.212] Recv SETTINGS 프레임 <길이=12, 플래그=0x00, stream_id=0>
(니브=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[ 0.212] SETTINGS 프레임 전송 <길이=12, 플래그=0x00, stream_id=0>
(니브=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[ 0.212] SETTINGS 프레임 전송 <길이=0, 플래그=0x01, stream_id=0>
; ACK
(니브=0)
[ 0.212] 우선순위 프레임 전송 <길이=5, 플래그=0x00, stream_id=3>
(dep_stream_id=0, 가중치=201, 배타적=0)
[ 0.212] 우선 순위 프레임 전송 <길이=5, 플래그=0x00, stream_id=5>
(dep_stream_id=0, 가중치=101, 배타적=0)
[ 0.212] 우선순위 프레임 전송 <길이=5, 플래그=0x00, stream_id=7>
(dep_stream_id=0, 가중치=1, 배타적=0)
[ 0.212] 우선 순위 프레임 전송 <길이=5, 플래그=0x00, stream_id=9>
(dep_stream_id=7, 가중치=1, 배타적=0)
[ 0.212] 우선 순위 프레임 전송 <길이=5, 플래그=0x00, stream_id=11>
(dep_stream_id=3, 가중치=1, 배타적=0)
[ 0.212] HEADERS 프레임 전송 <길이=39, 플래그=0x25, stream_id=13>
; END_STREAM | END_HEADERS | 우선 사항
(padlen=0, dep_stream_id=11, 가중치=16, 배타적=0)
; 새 스트림 열기
:방법: GET
:길: /
:구성표: https
:권한:nghttp2.org
수용하다: */*
승인 인코딩: gzip, deflate
사용자 에이전트: nghttp2/1.0.1-DEV
[ 0.221] Recv SETTINGS 프레임 <길이=0, 플래그=0x01, stream_id=0>
; ACK
(니브=0)
[ 0.221] recv (stream_id=13) :방법: GET
[ 0.221] recv (stream_id=13) :scheme: https
[ 0.221] recv (stream_id=13) :path: /stylesheets/screen.css
[ 0.221] recv (stream_id=13) :authority: nghttp2.org
[ 0.221] recv (stream_id=13) 승인 인코딩: gzip, deflate
[ 0.222] recv (stream_id=13) 사용자 에이전트: nghttp2/1.0.1-DEV
[ 0.222] Recv PUSH_PROMISE 프레임 <길이=50, 플래그=0x04, stream_id=13>
; END_HEADERS
(padlen=0, promise_stream_id=2)
[ 0.222] recv (stream_id=13) :상태: 200
[ 0.222] recv (stream_id=13) 날짜: 2015년 5월 21일 목요일 16:38:14 GMT
[ 0.222] recv (stream_id=13) 콘텐츠 유형: 텍스트/html
[ 0.222] recv (stream_id=13) 마지막 수정: 2015년 5월 15일 금요일 15:38:06 GMT
[ 0.222] recv (stream_id=13) etag: W/"555612de-19f6"
[ 0.222] recv (stream_id=13) 링크: ; rel=예압; as=스타일시트
[ 0.222] recv (stream_id=13) 콘텐츠 인코딩: gzip
[ 0.222] recv (stream_id=13) 서버: nghttpx nghttp2/1.0.1-DEV
[ 0.222] recv (stream_id=13) 다음을 통해: 1.1 nghttpx
[ 0.222] recv (stream_id=13) 엄격한 전송 보안: max-age=31536000
[ 0.222] Recv HEADERS 프레임 <길이=166, 플래그=0x04, stream_id=13>
; END_HEADERS
(패들렌=0)
; 첫 번째 응답 헤더
[ 0.222] Recv DATA 프레임 <길이=2601, 플래그=0x01, stream_id=13>
; END_STREAM
[ 0.222] recv (stream_id=2) :상태: 200
[ 0.222] recv (stream_id=2) 날짜: 2015년 5월 21일 목요일 16:38:14 GMT
[ 0.222] recv (stream_id=2) 콘텐츠 유형: 텍스트/css
[ 0.222] recv (stream_id=2) 마지막 수정: 2015년 5월 15일 금요일 15:38:06 GMT
[ 0.222] recv (stream_id=2) etag: W/"555612de-9845"
[ 0.222] recv (stream_id=2) 콘텐츠 인코딩: gzip
[ 0.222] recv (stream_id=2) 서버: nghttpx nghttp2/1.0.1-DEV
[ 0.222] recv (stream_id=2) 다음을 통해: 1.1 nghttpx
[ 0.222] recv (stream_id=2) 엄격한 전송 보안: max-age=31536000
[ 0.222] Recv HEADERS 프레임 <길이=32, 플래그=0x04, stream_id=2>
; END_HEADERS
(패들렌=0)
; 첫 번째 푸시 응답 헤더
[ 0.228] Recv DATA 프레임 <길이=8715, 플래그=0x01, stream_id=2>
; END_STREAM
[ 0.228] GOAWAY 프레임 전송 <길이=8, 플래그=0x00, stream_id=0>
(last_stream_id=2, error_code=NO_ERROR(0x00), opaque_data(0)=[])
HTTP 업그레이드는 다음과 같이 수행됩니다.
$ nghttp -nvu http://nghttp2.org
[0.011] 연결됨
[ 0.011] HTTP 업그레이드 요청
GET / HTTP/1.1
호스트: nghttp2.org
연결: 업그레이드, HTTP2-설정
업그레이드: h2c
HTTP2-설정: AAMAAABkAAQAAP__
수용하다: */*
사용자 에이전트: nghttp2/1.0.1-DEV
[0.018] HTTP 업그레이드 응답
HTTP/1.1 101 스위칭 프로토콜
연결: 업그레이드
업그레이드: h2c
[0.018] HTTP 업그레이드 성공
[ 0.018] Recv SETTINGS 프레임 <길이=12, 플래그=0x00, stream_id=0>
(니브=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[ 0.018] SETTINGS 프레임 전송 <길이=12, 플래그=0x00, stream_id=0>
(니브=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[ 0.018] SETTINGS 프레임 전송 <길이=0, 플래그=0x01, stream_id=0>
; ACK
(니브=0)
[ 0.018] 우선 순위 프레임 전송 <길이=5, 플래그=0x00, stream_id=3>
(dep_stream_id=0, 가중치=201, 배타적=0)
[ 0.018] 우선순위 프레임 전송 <길이=5, 플래그=0x00, stream_id=5>
(dep_stream_id=0, 가중치=101, 배타적=0)
[ 0.018] 우선 순위 프레임 전송 <길이=5, 플래그=0x00, stream_id=7>
(dep_stream_id=0, 가중치=1, 배타적=0)
[ 0.018] 우선 순위 프레임 전송 <길이=5, 플래그=0x00, stream_id=9>
(dep_stream_id=7, 가중치=1, 배타적=0)
[ 0.018] 우선순위 프레임 전송 <길이=5, 플래그=0x00, stream_id=11>
(dep_stream_id=3, 가중치=1, 배타적=0)
[ 0.018] 우선순위 프레임 전송 <길이=5, 플래그=0x00, stream_id=1>
(dep_stream_id=11, 가중치=16, 배타적=0)
[ 0.019] recv (stream_id=1) :방법: GET
[ 0.019] recv (stream_id=1) :scheme: http
[ 0.019] recv (stream_id=1) :path: /stylesheets/screen.css
[ 0.019] recv (stream_id=1) 호스트: nghttp2.org
[ 0.019] recv (stream_id=1) 사용자 에이전트: nghttp2/1.0.1-DEV
[ 0.019] Recv PUSH_PROMISE 프레임 <길이=49, 플래그=0x04, stream_id=1>
; END_HEADERS
(padlen=0, promise_stream_id=2)
[ 0.019] recv (stream_id=1) :상태: 200
[ 0.019] recv (stream_id=1) 날짜: 2015년 5월 21일 목요일 16:39:16 GMT
[ 0.019] recv (stream_id=1) 콘텐츠 유형: 텍스트/html
[ 0.019] recv (stream_id=1) 콘텐츠 길이: 6646
[ 0.019] recv (stream_id=1) 마지막 수정: 2015년 5월 15일 금요일 15:38:06 GMT
[ 0.019] recv (stream_id=1) etag: "555612de-19f6"
[ 0.019] recv (stream_id=1) 링크: ; rel=예압; as=스타일시트
[ 0.019] recv (stream_id=1) 허용 범위: 바이트
[ 0.019] recv (stream_id=1) 서버: nghttpx nghttp2/1.0.1-DEV
[ 0.019] recv (stream_id=1) 다음을 통해: 1.1 nghttpx
[ 0.019] Recv HEADERS 프레임 <길이=157, 플래그=0x04, stream_id=1>
; END_HEADERS
(패들렌=0)
; 첫 번째 응답 헤더
[ 0.019] Recv DATA 프레임 <길이=6646, 플래그=0x01, stream_id=1>
; END_STREAM
[ 0.019] recv (stream_id=2) :상태: 200
[ 0.019] recv (stream_id=2) 날짜: 2015년 5월 21일 목요일 16:39:16 GMT
[ 0.019] recv (stream_id=2) 콘텐츠 유형: 텍스트/css
[ 0.019] recv (stream_id=2) 콘텐츠 길이: 38981
[ 0.019] recv (stream_id=2) 마지막 수정: 2015년 5월 15일 금요일 15:38:06 GMT
[ 0.019] recv (stream_id=2) etag: "555612de-9845"
[ 0.019] recv (stream_id=2) 허용 범위: 바이트
[ 0.019] recv (stream_id=2) 서버: nghttpx nghttp2/1.0.1-DEV
[0.019] recv (stream_id=2) 다음을 통해: 1.1 nghttpx
[ 0.019] Recv HEADERS 프레임 <길이=36, 플래그=0x04, stream_id=2>
; END_HEADERS
(패들렌=0)
; 첫 번째 푸시 응답 헤더
[ 0.026] Recv DATA 프레임 <길이=16384, 플래그=0x00, stream_id=2>
[ 0.027] Recv DATA 프레임 <길이=7952, 플래그=0x00, stream_id=2>
[ 0.027] WINDOW_UPDATE 프레임 <길이=4, 플래그=0x00, stream_id=0> 보내기
(window_size_increment=33343)
[ 0.032] WINDOW_UPDATE 프레임 <길이=4, 플래그=0x00, stream_id=2> 보내기
(window_size_increment=33707)
[ 0.032] Recv DATA 프레임 <길이=14645, 플래그=0x01, stream_id=2>
; END_STREAM
[ 0.032] Recv SETTINGS 프레임 <길이=0, 플래그=0x01, stream_id=0>
; ACK
(니브=0)
[ 0.032] GOAWAY 프레임 전송 <길이=8, 플래그=0x00, stream_id=0>
(last_stream_id=2, error_code=NO_ERROR(0x00), opaque_data(0)=[])
-s
옵션을 사용하면 nghttp
요청에 대한 일부 타이밍 정보를 완료 시간별로 정렬하여 인쇄합니다.
$ nghttp -nas https://nghttp2.org/
***** 통계 *****
요청 시기:
responseEnd: 응답의 마지막 바이트가 수신된 시간
connectEnd를 기준으로
requestStart: 요청의 첫 번째 바이트가 전송되기 직전 시간
connectEnd에 상대적입니다. '*'가 표시된 경우
서버에서 푸시함.
프로세스: responseEnd - requestStart
코드: HTTP 상태 코드
크기: 응답 본문 없이 수신된 바이트 수
인플레이션.
URI: 요청 URI
http://www.w3.org/TR/resource-timing/#processing-model을 참조하세요.
'완료'로 정렬됨
id responseEnd requestStart 프로세스 코드 크기 요청 경로
13 +37.19ms +280us 36.91ms 200 2K /
2 +72.65ms * +36.38ms 36.26ms 200 8K /stylesheets/screen.css
17 +77.43ms +38.67ms 38.75ms 200 3K /javascripts/octopress.js
15 +78.12ms +38.66ms 39.46ms 200 3K /javascripts/modernizr-2.0.js
-r
옵션을 사용하면 nghttp
HAR 형식으로 지정된 파일에 더 자세한 타이밍 데이터를 기록합니다.
nghttpd
다중 스레드 정적 웹 서버입니다.
기본적으로 SSL/TLS 연결을 사용합니다. 비활성화하려면 --no-tls
옵션을 사용하십시오.
nghttpd
ALPN 또는 직접 HTTP/2 연결을 통한 HTTP/2 연결만 허용합니다. HTTP 업그레이드는 지원되지 않습니다.
-p
옵션을 사용하면 사용자가 서버 푸시를 구성할 수 있습니다.
nghttp
와 마찬가지로 정보 프레이밍을 위한 자세한 출력 모드가 있습니다. 다음은 nghttpd
의 샘플 출력입니다.
$ nghttpd --no-tls -v 8080
IPv4: 청취 0.0.0.0:8080
IPv6: 듣기 :::8080
[id=1] [ 1.521] SETTINGS 프레임 전송 <길이=6, 플래그=0x00, stream_id=0>
(니브=1)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[id=1] [ 1.521] recv SETTINGS 프레임 <길이=12, 플래그=0x00, stream_id=0>
(니브=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[id=1] [ 1.521] recv SETTINGS 프레임 <길이=0, 플래그=0x01, stream_id=0>
; ACK
(니브=0)
[id=1] [ 1.521] 수신 우선순위 프레임 <길이=5, 플래그=0x00, stream_id=3>
(dep_stream_id=0, 가중치=201, 배타적=0)
[id=1] [ 1.521] 수신 우선순위 프레임 <길이=5, 플래그=0x00, stream_id=5>
(dep_stream_id=0, 가중치=101, 배타적=0)
[id=1] [ 1.521] 수신 우선순위 프레임 <길이=5, 플래그=0x00, stream_id=7>
(dep_stream_id=0, 가중치=1, 배타적=0)
[id=1] [ 1.521] 수신 우선순위 프레임 <길이=5, 플래그=0x00, stream_id=9>
(dep_stream_id=7, 가중치=1, 배타적=0)
[id=1] [ 1.521] 수신 우선순위 프레임 <길이=5, 플래그=0x00, stream_id=11>
(dep_stream_id=3, 가중치=1, 배타적=0)
[id=1] [ 1.521] recv (stream_id=13) :방법: GET
[id=1] [ 1.521] recv (stream_id=13) :경로: /
[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) 수락: */*
[id=1] [ 1.521] recv (stream_id=13) accept-encoding: gzip, deflate
[id=1] [ 1.521] recv (stream_id=13) 사용자 에이전트: nghttp2/1.0.0-DEV
[id=1] [ 1.521] recv HEADERS 프레임 <길이=41, 플래그=0x25, stream_id=13>
; END_STREAM | END_HEADERS | 우선 사항
(padlen=0, dep_stream_id=11, 가중치=16, 배타적=0)
; 새 스트림 열기
[id=1] [ 1.521] SETTINGS 프레임 전송 <길이=0, 플래그=0x01, stream_id=0>
; ACK
(니브=0)
[id=1] [ 1.521] HEADERS 프레임 전송 <길이=86, 플래그=0x04, stream_id=13>
; END_HEADERS
(패들렌=0)
; 첫 번째 응답 헤더
:상태: 200
서버: nghttpd nghttp2/1.0.0-DEV
콘텐츠 길이: 10
캐시 제어: 최대 연령=3600
날짜: 2015년 5월 15일 금요일 14:49:04 GMT
최종 수정: 2014년 9월 30일 화요일 12:40:52 GMT
[id=1] [ 1.522] DATA 프레임 전송 <길이=10, 플래그=0x01, stream_id=13>
; END_STREAM
[id=1] [ 1.522] stream_id=13 폐쇄됨
[id=1] [ 1.522] recv GOAWAY 프레임 <길이=8, 플래그=0x00, stream_id=0>
(last_stream_id=0, error_code=NO_ERROR(0x00), opaque_data(0)=[])
[id=1] [ 1.522] 폐쇄됨
nghttpx
HTTP/3, HTTP/2 및 HTTP/1.1을 위한 다중 스레드 역방향 프록시이며 http://nghttp2.org를 지원하고 HTTP/2 서버 푸시를 지원합니다.
nghttpx
명령줄 인터페이스를 재작업했으며 그 결과 1.8.0 이하 버전과 호환되지 않는 부분이 여러 개 있습니다. 이는 기능을 확장하고 향후 릴리스에서 추가 기능 향상을 확보하는 데 필요합니다. 이전 릴리스에서 마이그레이션하는 방법을 알아보려면 nghttpx v1.8.0 이하에서 마이그레이션을 읽어보세요.
nghttpx
세션 ID, 세션 티켓(자동 키 순환 포함), OCSP 스테이플링, 동적 레코드 크기 조정, ALPN, 전달 보안 및 HTTP/2와 같은 중요한 성능 중심 기능을 TLS에 구현합니다. nghttpx
memcached를 통해 여러 nghttpx
인스턴스 간에 세션 캐시와 티켓 키를 공유하는 기능도 제공합니다.
nghttpx
에는 2가지 작동 모드가 있습니다:
모드 옵션 | 프런트엔드 | 백엔드 | 메모 |
---|---|---|---|
기본 모드 | HTTP/3, HTTP/2, HTTP/1.1 | HTTP/1.1, HTTP/2 | 역방향 프록시 |
--http2-proxy | HTTP/3, HTTP/2, HTTP/1.1 | HTTP/1.1, HTTP/2 | 순방향 프록시 |
현재 흥미로운 모드는 기본 모드입니다. 이는 역방향 프록시처럼 작동하고 HTTP/3, HTTP/2 및 HTTP/1.1을 수신하며 기존 웹 서버에 대한 SSL/TLS 터미네이터로 배포될 수 있습니다.
모든 모드에서 프런트엔드 연결은 기본적으로 SSL/TLS로 암호화됩니다. 암호화를 비활성화하려면 --frontend
옵션에 no-tls
키워드를 사용하십시오. 암호화가 비활성화된 경우 HTTP 업그레이드를 통해 수신 HTTP/1.1 연결을 HTTP/2로 업그레이드할 수 있습니다. 반면에 백엔드 연결은 기본적으로 암호화되지 않습니다. 백엔드 연결을 암호화하려면 --backend
옵션에 tls
키워드를 사용하세요.
nghttpx
구성 파일을 지원합니다. --conf
옵션과 샘플 구성 파일 nghttpx.conf.sample
참조하세요.
기본 모드에서 nghttpx
백엔드 서버에 대한 역방향 프록시로 작동합니다.
클라이언트 <-- (HTTP/3, HTTP/2, HTTP/1.1) --> nghttpx <-- (HTTP/1.1, HTTP/2) --> 웹 서버
[역방향 프록시]
--http2-proxy
옵션을 사용하면 정방향 프록시로 작동하며 이를 보안 HTTP/2 프록시라고 합니다.
클라이언트 <-- (HTTP/3, HTTP/2, HTTP/1.1) --> nghttpx <-- (HTTP/1.1) --> 프록시
[보안 프록시] (예: Squid, ATS)
위 예의 Client
nghttpx
보안 프록시로 사용하도록 구성되어야 합니다.
이 글을 쓰는 시점에서 Chrome과 Firefox는 모두 보안 HTTP/2 프록시를 지원합니다. 보안 프록시를 사용하도록 Chrome을 구성하는 한 가지 방법은 다음과 같이 Proxy.pac 스크립트를 만드는 것입니다.
function FindProxyForURL ( url , host ) {
return "HTTPS SERVERADDR:PORT" ;
}
SERVERADDR
및 PORT
nghttpx가 실행 중인 시스템의 호스트 이름/주소 및 포트입니다. Chrome에는 보안 프록시를 위한 유효한 인증서가 필요합니다.
그런 다음 다음 인수를 사용하여 Chrome을 실행합니다.
$ google-chrome --proxy-pac-url=file:///path/to/proxy.pac --use-npn
백엔드 HTTP/2 연결은 HTTP 프록시를 통해 터널링될 수 있습니다. 프록시는 --backend-http-proxy-uri
사용하여 지정됩니다. 다음 그림은 nghttpx가 HTTP 프록시를 통해 외부 HTTP/2 프록시와 통신하는 방법을 보여줍니다.
클라이언트 <-- (HTTP/3, HTTP/2, HTTP/1.1) --> nghttpx <-- (HTTP/2) --
--====================> HTTP/2 프록시
(HTTP 프록시 터널)(예: nghttpx -s)
h2load
프로그램은 HTTP/3, HTTP/2 및 HTTP/1.1에 대한 벤치마킹 도구입니다. h2load
의 UI는 weighttp
(https://github.com/lighttpd/weighttp)에서 많은 영감을 받았습니다. 일반적인 사용법은 다음과 같습니다.
$ h2load -n100000 -c100 -m100 https://localhost:8443/
벤치마크 시작 중...
생성 스레드 #0: 동시 클라이언트 100개, 총 요청 100000개
프로토콜: TLSv1.2
암호: ECDHE-RSA-AES128-GCM-SHA256
서버 임시 키: ECDH P-256 256비트
진행률: 10% 완료
진행률: 20% 완료
진행률: 30% 완료
진행률: 40% 완료
진행률: 50% 완료
진행률: 60% 완료
진행률: 70% 완료
진행률: 80% 완료
진행률: 90% 완료
진행률: 100% 완료
771.26ms, 129658 req/s, 4.71MB/s로 완료되었습니다.
요청: 총 100000개, 시작 100000개, 완료 100000개, 성공 100000개, 실패 0개, 오류 0개
상태 코드: 100000 2xx, 0 3xx, 0 4xx, 0 5xx
트래픽: 총 3812300바이트, 헤더 1009900바이트, 데이터 1000000바이트
최소 최대 평균 sd +/- sd
요청 시간: 25.12ms 124.55ms 51.07ms 15.36ms 84.87%
연결 시간: 208.94ms 254.67ms 241.38ms 7.95ms 63.00%
첫 번째 바이트까지의 시간: 209.11ms 254.80ms 241.51ms 7.94ms 63.00%
위의 예에서는 100개의 동시 클라이언트(즉, 100개의 HTTP/2 세션)와 클라이언트당 최대 100개의 스트림을 사용하여 총 100,000개의 요청을 발행했습니다. -t
옵션을 사용하면 h2load
여러 기본 스레드를 사용하여 클라이언트 측의 단일 코어가 포화되는 것을 방지합니다.
경고
공개적으로 사용 가능한 서버에 대해서는 이 도구를 사용하지 마십시오. 이는 DOS 공격으로 간주됩니다. 개인 서버에 대해서만 사용하십시오.
실험적인 HTTP/3이 활성화되면 h2load는 HTTP/3 서버에 요청을 보낼 수 있습니다. 이렇게 하려면 다음과 같이 --alpn-list
옵션에 h3
지정하십시오.
$ h2load --alpn-list h3 https://127.0.0.1:4433
nghttp2 v1.58 이하의 경우 --npn-list
--alpn-list
list를 사용하세요.
src
디렉토리에는 HPACK 도구가 포함되어 있습니다. deflatehd
프로그램은 명령줄 헤더 압축 도구입니다. inflatehd
프로그램은 명령줄 헤더 압축 해제 도구입니다. 두 도구 모두 stdin에서 입력을 읽고 stdout에 출력을 씁니다. 오류는 stderr에 기록됩니다. JSON을 입력 및 출력으로 사용합니다. 우리는 (대부분) https://github.com/http2jp/hpack-test-case에 설명된 것과 동일한 JSON 데이터 형식을 사용합니다.
deflatehd
프로그램은 Stdin에서 JSON 데이터 또는 HTTP/1 스타일 헤더 필드를 읽고 JSON의 압축 헤더 블록을 출력합니다.
JSON 입력의 경우 루트 JSON 객체에는 cases
키를 포함해야합니다. 그 값에는 입력 헤더 세트의 시퀀스가 포함되어야합니다. 그들은 동일한 압축 컨텍스트를 공유하고 나타나는 순서대로 처리됩니다. 순서의 각 항목은 JSON 객체이며 headers
키가 포함되어야합니다. 그 값은 정확히 하나의 이름/값 쌍을 포함하는 JSON 객체의 배열입니다.
예:
{
"cases" :
[
{
"headers" : [
{ ":method" : " GET " },
{ ":path" : " / " }
]
},
{
"headers" : [
{ ":method" : " POST " },
{ ":path" : " / " }
]
}
]
}
-t
옵션을 사용하면 프로그램이 더 친숙한 HTTP/1 스타일 헤더 필드 블록을 허용 할 수 있습니다. 각 헤더 세트는 빈 줄로 구분됩니다.
예:
: 방법 : 얻습니다
: 체계 : https
:길: /
: 방법 : 게시
사용자 에이전트 : NGHTTP2
출력은 JSON 객체에 있습니다. cases
키가 포함되어야하며 그 값은 JSON 객체의 배열이며, 여기에는 다음 키가 있습니다.
output_length
/ input_length
* 100예:
{
"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
}
]
}
출력은 inflatehd
및 deflatehd
의 입력으로 사용할 수 있습니다.
-d
옵션을 사용하면 추가 header_table
키가 추가되고 관련 값에는 해당 헤더 세트가 처리 된 후 동적 헤더 테이블의 상태가 포함됩니다. 값에는 최소한 다음 키가 포함됩니다.
referenced
true
이면 참조 세트에 있습니다. size
에는 오버 헤드 (32 바이트)가 포함됩니다. index
헤더 테이블의 인덱스에 해당합니다. name
은 헤더 필드 이름이고 value
은 헤더 필드 값입니다.max_deflate_size
내에서 점유 된 공백 항목의 합.max_size
보다 작을 수 있습니다. 이 경우 인코더는 첫 번째 max_deflate_size
버퍼까지만 사용합니다. 헤더 테이블 크기는 여전히 max_size
이므로 인코더는 max_deflate_size
외부의 항목을 추적해야하지만 max_size
내부에서 더 이상 참조되지 않도록해야합니다.예:
{
"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
}