Skip to content

[HTTP2] Implement HTTP/2 server-side support #406

Description

@kcenon

Summary

Implement HTTP/2 server-side support to complement the existing HTTP/2 client implementation, enabling bidirectional HTTP/2 communication.

Current State

  • HTTP/2 client fully implemented (http2_client.h)
  • HTTP/2 frame handling complete (RFC 7540)
  • HPACK compression implemented (RFC 7541)
  • No HTTP/2 server implementation

Existing client features:

  • Stream multiplexing
  • Flow control
  • HPACK header compression
  • TLS 1.3 with ALPN
  • Streaming support

Proposed Implementation

1. HTTP/2 Server Class

class http2_server : public std::enable_shared_from_this<http2_server> {
public:
    using request_handler_t = std::function<void(
        http2_server_stream& stream,
        const http2_request& request)>;
    
    explicit http2_server(std::string_view server_id);
    ~http2_server();
    
    // Server lifecycle
    auto start(unsigned short port) -> VoidResult;
    auto start_tls(unsigned short port, 
                   const tls_config& config) -> VoidResult;
    auto stop() -> VoidResult;
    [[nodiscard]] auto is_running() const -> bool;
    
    // Request handling
    void set_request_handler(request_handler_t handler);
    void set_error_handler(error_handler_t handler);
    
    // Configuration
    auto set_settings(const http2_settings& settings) -> void;
    [[nodiscard]] auto get_settings() const -> http2_settings;
    
    // Statistics
    [[nodiscard]] auto active_connections() const -> size_t;
    [[nodiscard]] auto active_streams() const -> size_t;

private:
    // Connection management
    void accept_connection(tcp_socket socket);
    void handle_connection(std::shared_ptr<http2_connection> conn);
    
    // Members
    std::string server_id_;
    std::unique_ptr<asio::io_context> io_context_;
    std::unique_ptr<asio::ip::tcp::acceptor> acceptor_;
    std::optional<asio::ssl::context> ssl_context_;
    request_handler_t request_handler_;
    http2_settings settings_;
    std::map<uint64_t, std::shared_ptr<http2_connection>> connections_;
    std::mutex connections_mutex_;
};

2. Server Stream Class

class http2_server_stream {
public:
    // Response methods
    auto send_headers(int status_code, 
                      const std::vector<http_header>& headers,
                      bool end_stream = false) -> VoidResult;
    
    auto send_data(const std::vector<uint8_t>& data,
                   bool end_stream = false) -> VoidResult;
    
    auto send_data(std::string_view data,
                   bool end_stream = false) -> VoidResult;
    
    // Streaming response
    auto start_response(int status_code,
                        const std::vector<http_header>& headers) -> VoidResult;
    auto write(const std::vector<uint8_t>& chunk) -> VoidResult;
    auto end_response() -> VoidResult;
    
    // Stream control
    auto reset(uint32_t error_code) -> VoidResult;
    
    // Request info
    [[nodiscard]] auto stream_id() const -> uint32_t;
    [[nodiscard]] auto method() const -> std::string_view;
    [[nodiscard]] auto path() const -> std::string_view;
    [[nodiscard]] auto headers() const -> const std::vector<http_header>&;
    
private:
    uint32_t stream_id_;
    std::weak_ptr<http2_connection> connection_;
    std::vector<http_header> request_headers_;
    stream_state state_{stream_state::open};
};

3. Request Structure

struct http2_request {
    std::string method;
    std::string path;
    std::string authority;  // :authority pseudo-header
    std::string scheme;     // :scheme pseudo-header
    std::vector<http_header> headers;
    std::vector<uint8_t> body;
    
    // Helpers
    [[nodiscard]] auto get_header(std::string_view name) const 
        -> std::optional<std::string>;
    [[nodiscard]] auto content_type() const -> std::optional<std::string>;
    [[nodiscard]] auto content_length() const -> std::optional<size_t>;
};

4. Usage Example

auto server = std::make_shared<http2_server>("my-server");

server->set_request_handler([](http2_server_stream& stream,
                               const http2_request& request) {
    if (request.method == "GET" && request.path == "/api/health") {
        stream.send_headers(200, {{"content-type", "application/json"}});
        stream.send_data(R"({"status": "ok"})", true);
    } else if (request.method == "POST" && request.path == "/api/echo") {
        stream.send_headers(200, {{"content-type", "application/octet-stream"}});
        stream.send_data(request.body, true);
    } else {
        stream.send_headers(404, {});
        stream.send_data("Not Found", true);
    }
});

server->start_tls(8443, tls_config);

Server Push (Optional - Future Enhancement)

// Server-initiated push
auto push_stream = stream.push_promise("/static/style.css", 
    {{"content-type", "text/css"}});
push_stream.send_data(css_content, true);

Tasks

  • Design http2_server class interface
  • Implement connection acceptance
  • Implement server-side handshake (SETTINGS exchange)
  • Implement request parsing from HEADERS frames
  • Implement http2_server_stream for responses
  • Implement streaming response support
  • Add flow control handling
  • Add HPACK integration for server
  • TLS/ALPN configuration for server
  • Unit tests for server components
  • Integration tests (client-server)
  • Performance benchmarks
  • Documentation and examples

Acceptance Criteria

  • Server accepts HTTP/2 connections
  • Proper SETTINGS exchange
  • Request handling with callback API
  • Stream multiplexing works
  • Flow control respected
  • TLS with ALPN "h2" works
  • Interoperability with http2_client
  • Benchmarks show acceptable performance

Files to Create

  • include/kcenon/network/protocols/http2/http2_server.h
  • include/kcenon/network/protocols/http2/http2_server_stream.h
  • include/kcenon/network/protocols/http2/http2_request.h
  • src/protocols/http2/http2_server.cpp
  • tests/test_http2_server.cpp
  • tests/integration/test_http2_client_server.cpp
  • samples/http2_server_example.cpp

Related

Metadata

Metadata

Assignees

Labels

architectureArchitectural changes and designenhancementNew feature or requestpriority:lowLow priority issue

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions