Skip to content

(v2) Refactor HTTP server. Separate HTTP/1.x implementation. Support HTTP/2 using nghttp2#93386

Open
m0r0zk01 wants to merge 2 commits intoClickHouse:masterfrom
m0r0zk01:http2
Open

(v2) Refactor HTTP server. Separate HTTP/1.x implementation. Support HTTP/2 using nghttp2#93386
m0r0zk01 wants to merge 2 commits intoClickHouse:masterfrom
m0r0zk01:http2

Conversation

@m0r0zk01
Copy link
Copy Markdown

@m0r0zk01 m0r0zk01 commented Jan 5, 2026

Changelog category (leave one):

  • Experimental Feature

Changelog entry (a user-readable short description of the changes that goes into CHANGELOG.md):

Refactor HTTP server. Separate HTTP/1.x implementation. Support HTTP/2 using nghttp2

Documentation entry for user-facing changes

  • Documentation is written (mandatory for new features)

Technical details

Move changes from #80141.

HTTPRequestHandler now has a single virtual method handleRequest that takes HTTPServerRequest and HTTPServerResponseBase.

HTTPServerRequest stores the request method, path, and header fields. It also provides a ReadBuffer to read the body from. This ReadBuffer is passed to HTTPServerRequest's constructor, and handleRequest knows nothing about its implementation.

HTTPServerResponseBase provides storage for the response status and header fields. It also has an abstract makeUniqueStream method that returns a WriteBufferFromHTTPServerResponseBase for the response body. Now, this is the only way to send a response to the client. Previously, there were two ways that duplicated each other's logic: HTTPServerResponse::send() and WriteBufferFromHTTPServerResponse. They are now unified.

HTTP/2 support is enabled via the <http2_server></http2_server> config section.

If HTTP/2 is enabled, HTTPServerConnectionFactory can decide whether the connection should be handled as HTTP/2. If the connection is secure, it checks ALPN. Otherwise, it checks if the client has sent an HTTP/2 preface.

Now, there are two connection handlers: HTTP1ServerConnection and HTTP2ServerConnection. The first one works as before. It creates an HTTPServerRequest with the ReadBuffer from the HTTP/1.x stream (fixed length/chunked) and an HTTPServerResponseBase with the WriteBufferFromHTTPServerResponseBase implementation based on the old WriteBufferFromHTTPServerResponse class.

HTTP2ServerConnection handles an HTTP/2 connection. It has a main IO thread that exchanges HTTP/2 frames with the client. For each new stream, it creates a new thread that runs handleRequest. The HTTP/2 stream provides its own implementations of ReadBuffer and WriteBufferFromHTTPServerResponseBase.

One important thing to mention: the HTTP/1.x server had a feature for sending X-ClickHouse-Progress headers to the client over time to report query progress. For HTTP/2, we can't implement the same thing easily (at least because HEADERS (+CONTINUATION) frames must be sent together, without any other frame in between (RFC 9113 section 4.3.)). So, WriteBufferFromHTTPServerResponseBase::onProgress implementation for HTTP/1.x remains the same as before, while its HTTP/2 implementation is a no-op. I believe the correct way to implement progress reporting for HTTP/2 is via 1xx informational responses.

@m0r0zk01 m0r0zk01 force-pushed the http2 branch 4 times, most recently from f2c307e to fed3d37 Compare January 5, 2026 05:30
@scanhex12 scanhex12 self-assigned this Jan 5, 2026
@scanhex12 scanhex12 added the can be tested Allows running workflows for external contributors label Jan 5, 2026
@clickhouse-gh
Copy link
Copy Markdown
Contributor

clickhouse-gh bot commented Jan 5, 2026

Workflow [PR], commit [a0c1081]

Summary:

job_name test_name status info comment
Integration tests (amd_asan, db disk, old analyzer, 3/6) failure
test_http2/test.py::test_parallel_requests FAIL cidb
Integration tests (amd_binary, 2/5) failure
test_userspace_page_cache/test.py::test_size_adjustment FAIL cidb, issue
test_zookeeper_fallback_session/test.py::test_fallback_session FAIL cidb
Integration tests (amd_binary, 4/5) failure
test_http2/test.py::test_parallel_requests FAIL cidb
Integration tests (arm_binary, distributed plan, 1/4) failure
test_keeper_http_control_cli/test.py::test_http_commands_basic_responses FAIL cidb
test_keeper_http_control_cli/test.py::test_http_commands_cli_response FAIL cidb
test_projection_rebuild_with_required_columns/test.py::test_projection_rebuild_uses_only_required_columns FAIL cidb, issue
Integration tests (arm_binary, distributed plan, 2/4) failure
test_http2/test.py::test_parallel_requests FAIL cidb
Integration tests (amd_tsan, 5/6) failure
test_http2/test.py::test_parallel_requests FAIL cidb
BuzzHouse (amd_debug) failure
Logical error: 'Inconsistent AST formatting: the query: (STID: 1941-1bfa) FAIL cidb, issue

@clickhouse-gh clickhouse-gh bot added pr-experimental Experimental Feature submodule changed At least one submodule changed in this PR. labels Jan 5, 2026
@m0r0zk01 m0r0zk01 force-pushed the http2 branch 7 times, most recently from e316438 to b709d7a Compare January 5, 2026 12:09
@ClickHouse ClickHouse deleted a comment from IArtNextI Jan 5, 2026
@m0r0zk01 m0r0zk01 force-pushed the http2 branch 11 times, most recently from a7a30a0 to cf47e29 Compare January 5, 2026 21:50
@m0r0zk01 m0r0zk01 force-pushed the http2 branch 2 times, most recently from 92ec712 to b37efaf Compare January 5, 2026 23:30
…TP/1.x implementation. Support HTTP/2 using nghttp2
Resolve merge conflicts between the HTTP/2 PR and master:
- CI/infrastructure files (.gitmodules, requirements.txt): take master's version
- `contrib/CMakeLists.txt`, `src/configure_config.cmake`, `src/Common/config.h.in`: keep both nghttp2 and new master additions (libcotp, clickstack, simdcomp, wasmedge, wasmtime)
- `programs/server/Server.cpp`: merge PR's `http1_params`/`http2_params`/`thread_pool` with master's `server_settings` refactoring and `handlers_config_key`
- `src/Server/HTTPHandler.cpp`, `src/Server/HTTPHandler.h`: adapt `CurrentThread::QueryScope` to new `QueryScope` type while keeping PR's `HTTPServerResponseBase` interface
- `src/Server/WebUIRequestHandler.cpp`, `src/Server/WebUIRequestHandler.h`: adapt new `JemallocWebUIRequestHandler` and `ClickStackUIRequestHandler` to PR's `HTTPServerResponseBase` interface
- `src/Server/IndexRequestHandler.cpp`: keep PR's `response.makeStream()` with master's `#embed` resource naming
- `src/Server/HTTP/HTTP1/HTTP1ServerConnection.cpp`, `.h`: keep PR's free-function `sendErrorResponse` pattern
- `src/Server/HTTP/HTTP1/HTTP1ServerResponse.cpp`: keep PR's version (master's fixed-length buffer handling requires methods not yet in PR's class hierarchy)
- `src/IO/HTTPCommon.cpp`: keep PR's `HTTPServerResponseBase.h` include

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@clickhouse-gh clickhouse-gh bot added the manual approve Manual approve required to run CI label Mar 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

can be tested Allows running workflows for external contributors manual approve Manual approve required to run CI pr-experimental Experimental Feature submodule changed At least one submodule changed in this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants