Network System 0.1.1
High-performance modular networking library for scalable client-server applications
Loading...
Searching...
No Matches
http2_server_example.cpp
Go to the documentation of this file.
1/*****************************************************************************
2BSD 3-Clause License
3
4Copyright (c) 2024, 🍀☀🌕🌥 🌊
5All rights reserved.
6*****************************************************************************/
7
9#include <iostream>
10#include <csignal>
11#include <atomic>
12
14
15namespace
16{
17 std::atomic<bool> g_running{true};
18
19 void signal_handler(int /*signal*/)
20 {
21 g_running = false;
22 }
23}
24
25int main()
26{
27 std::cout << "=== HTTP/2 Server Example ===" << std::endl;
28 std::cout << "Note: This example uses h2c (HTTP/2 cleartext) for simplicity." << std::endl;
29 std::cout << " For production, use start_tls() with proper certificates." << std::endl;
30 std::cout << std::endl;
31
32 // Setup signal handler for graceful shutdown
33 std::signal(SIGINT, signal_handler);
34 std::signal(SIGTERM, signal_handler);
35
36 // Create HTTP/2 server instance
37 auto server = std::make_shared<http2_server>("http2-example-server");
38
39 // Configure HTTP/2 settings (optional)
42 settings.initial_window_size = 65535;
43 settings.max_frame_size = 16384;
44 server->set_settings(settings);
45
46 // Set error handler for debugging
47 server->set_error_handler([](const std::string& error_msg)
48 {
49 std::cerr << "[ERROR] " << error_msg << std::endl;
50 });
51
52 // Set request handler
53 server->set_request_handler([](http2_server_stream& stream,
54 const http2_request& request)
55 {
56 std::cout << "[REQUEST] " << request.method << " " << request.path << std::endl;
57
58 // Route handling
59 if (request.method == "GET" && request.path == "/")
60 {
61 // Home page
62 std::string body = R"({
63 "message": "Welcome to HTTP/2 Server",
64 "protocol": "h2c",
65 "endpoints": [
66 "GET /",
67 "GET /api/health",
68 "GET /api/echo",
69 "POST /api/data"
70 ]
71})";
72 stream.send_headers(200, {
73 {"content-type", "application/json"},
74 {"server", "network-system-http2"}
75 });
76 stream.send_data(body, true);
77 }
78 else if (request.method == "GET" && request.path == "/api/health")
79 {
80 // Health check endpoint
81 stream.send_headers(200, {
82 {"content-type", "application/json"}
83 });
84 stream.send_data(R"({"status": "healthy"})", true);
85 }
86 else if (request.method == "GET" && request.path == "/api/echo")
87 {
88 // Echo query parameters
89 std::string response = R"({"path": ")" + request.path + R"(", "authority": ")" +
90 request.authority + R"("})";
91 stream.send_headers(200, {
92 {"content-type", "application/json"}
93 });
94 stream.send_data(response, true);
95 }
96 else if (request.method == "POST" && request.path == "/api/data")
97 {
98 // Echo POST body
99 auto content_type = request.content_type();
100
101 std::string response = R"({"received_bytes": )" +
102 std::to_string(request.body.size()) + R"(, "content_type": ")" +
103 content_type.value_or("unknown") + R"("})";
104
105 stream.send_headers(200, {
106 {"content-type", "application/json"}
107 });
108 stream.send_data(response, true);
109 }
110 else
111 {
112 // 404 Not Found
113 stream.send_headers(404, {
114 {"content-type", "application/json"}
115 });
116 stream.send_data(R"({"error": "Not Found"})", true);
117 }
118 });
119
120 // Start server on port 8080 (h2c - cleartext HTTP/2)
121 const unsigned short port = 8080;
122 std::cout << "Starting HTTP/2 server on port " << port << "..." << std::endl;
123
124 auto result = server->start(port);
125 if (result.is_err())
126 {
127 std::cerr << "Failed to start server: " << result.error().message << std::endl;
128 return 1;
129 }
130
131 std::cout << "Server started successfully!" << std::endl;
132 std::cout << std::endl;
133 std::cout << "Available endpoints:" << std::endl;
134 std::cout << " GET http://localhost:" << port << "/" << std::endl;
135 std::cout << " GET http://localhost:" << port << "/api/health" << std::endl;
136 std::cout << " GET http://localhost:" << port << "/api/echo" << std::endl;
137 std::cout << " POST http://localhost:" << port << "/api/data" << std::endl;
138 std::cout << std::endl;
139 std::cout << "Test with curl (requires h2c support):" << std::endl;
140 std::cout << " curl --http2-prior-knowledge http://localhost:" << port << "/" << std::endl;
141 std::cout << " curl --http2-prior-knowledge http://localhost:" << port << "/api/health" << std::endl;
142 std::cout << " curl --http2-prior-knowledge -X POST -d '{\"test\": 123}' http://localhost:"
143 << port << "/api/data" << std::endl;
144 std::cout << std::endl;
145 std::cout << "Press Ctrl+C to stop the server..." << std::endl;
146
147 // Wait for shutdown signal
148 while (g_running)
149 {
150 std::this_thread::sleep_for(std::chrono::milliseconds(100));
151 }
152
153 std::cout << "\nShutting down server..." << std::endl;
154 server->stop();
155 std::cout << "Server stopped." << std::endl;
156
157 return 0;
158}
Server-side HTTP/2 stream for sending responses.
auto send_headers(int status_code, const std::vector< http_header > &headers, bool end_stream=false) -> VoidResult
Send response headers.
auto send_data(const std::vector< uint8_t > &data, bool end_stream=false) -> VoidResult
Send response data.
int main()
void signal_handler(int)
std::atomic< bool > g_running
auto content_type() const -> std::optional< std::string >
Get Content-Type header value.
std::vector< uint8_t > body
Request body from DATA frames.
std::string path
Request path (:path pseudo-header)
std::string authority
Authority (:authority pseudo-header)
std::string method
HTTP method (:method pseudo-header)
uint32_t max_concurrent_streams
Max concurrent streams.