v0.27.57
Changes
feature: enable h2c for server handler, proxy client and net client (#4171)
Enabling h2c for client to skipper requires skipper server handler to be configured by -enable-h2c-server.
Enabling h2c from skipper to backend is done automatically by choosing h2c:// as scheme. In kubernetes this can be achieved, if you have enabled -enable-kubernetes-endpointslices, and choose the appProtocol on your Kubernetes service, examples:
eskip
h2c: * -> "h2c://127.0.0.1:9000";
h2c_lb: * -> <roundRobin, "h2c://127.0.0.1:9000", "h2c://127.0.0.1:9001">;
kubernetes
apiVersion: v1
kind: Service
metadata:
name: app-svc
spec:
ports:
- port: 80
appProtocol: kubernetes.io/h2cDetails
Test Direct Prior Knowledge:
% nghttp -v http://localhost:9001/path
[ 0.000] Connected
[ 0.000] send SETTINGS frame <length=12, flags=0x00, stream_id=0>
(niv=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[ 0.001] send PRIORITY frame <length=5, flags=0x00, stream_id=3>
(dep_stream_id=0, weight=201, exclusive=0)
[ 0.001] send PRIORITY frame <length=5, flags=0x00, stream_id=5>
(dep_stream_id=0, weight=101, exclusive=0)
[ 0.001] send PRIORITY frame <length=5, flags=0x00, stream_id=7>
(dep_stream_id=0, weight=1, exclusive=0)
[ 0.001] send PRIORITY frame <length=5, flags=0x00, stream_id=9>
(dep_stream_id=7, weight=1, exclusive=0)
[ 0.001] send PRIORITY frame <length=5, flags=0x00, stream_id=11>
(dep_stream_id=3, weight=1, exclusive=0)
[ 0.001] send HEADERS frame <length=43, flags=0x25, stream_id=13>
; END_STREAM | END_HEADERS | PRIORITY
(padlen=0, dep_stream_id=11, weight=16, exclusive=0)
; Open new stream
:method: GET
:path: /path
:scheme: http
:authority: localhost:9001
accept: */*
accept-encoding: gzip, deflate
user-agent: nghttp2/1.59.0
[ 0.001] recv SETTINGS frame <length=30, flags=0x00, stream_id=0>
(niv=5)
[SETTINGS_MAX_FRAME_SIZE(0x05):1048576]
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):250]
[SETTINGS_MAX_HEADER_LIST_SIZE(0x06):1048896]
[SETTINGS_HEADER_TABLE_SIZE(0x01):4096]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):1048576]
[ 0.001] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
; ACK
(niv=0)
[ 0.001] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
; ACK
(niv=0)
[ 0.001] recv WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>
(window_size_increment=983041)
[ 0.008] recv (stream_id=13) :status: 201
[ 0.008] recv (stream_id=13) date: Tue, 04 Aug 2026 22:19:10 GMT
[ 0.008] recv (stream_id=13) server: Skipper
[ 0.008] recv HEADERS frame <length=36, flags=0x04, stream_id=13>
; END_HEADERS
(padlen=0)
; First response header
[ 0.008] recv DATA frame <length=0, flags=0x01, stream_id=13>
; END_STREAM
[ 0.008] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
(last_stream_id=0, error_code=NO_ERROR(0x00), opaque_data(0)=[])
test with upgrade does not work:
% nghttp -uv http://localhost:9001/path
[ 0.000] Connected
[ 0.000] HTTP Upgrade request
GET /path HTTP/1.1
host: localhost:9001
connection: Upgrade, HTTP2-Settings
upgrade: h2c
http2-settings: AAMAAABkAAQAAP__
accept: */*
user-agent: nghttp2/1.59.0
[ 0.002] HTTP Upgrade response
HTTP/1.1 500 Internal Server Error
Content-Length: 22
Content-Type: text/plain; charset=utf-8
Server: Skipper
X-Content-Type-Options: nosniff
Date: Tue, 04 Aug 2026 22:19:39 GMT
Internal Server Error
[ERROR] HTTP Upgrade failed
Some requests were not processed. total=1, processed=0
Multiarch Docker image
Multiarch Docker image is available in GitHub's docker registry:
docker run -it ghcr.io/zalando/skipper:v0.27.57 skipper --help