-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhttp2_client.cpp
More file actions
154 lines (133 loc) · 5.16 KB
/
http2_client.cpp
File metadata and controls
154 lines (133 loc) · 5.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/// @file http2_client.cpp
/// @brief HTTP/2 Client Example
///
/// This example demonstrates how to make HTTP/2 requests using Elio's
/// HTTP/2 client with multiplexed streams over TLS.
///
/// Usage: ./http2_client [url]
/// Default: Fetches https://nghttp2.org/
///
/// Note: HTTP/2 requires HTTPS (TLS with ALPN h2 negotiation).
/// The target server must support HTTP/2.
#include <elio/elio.hpp>
#include <elio/http/http2.hpp>
#include <iostream>
using namespace elio;
using namespace elio::http;
/// Perform HTTP/2 requests demonstrating various features
coro::task<void> run_demo(const std::string& base_url) {
// Create HTTP/2 client with custom config
h2_client_config config;
config.user_agent = "elio-http2-client-example/1.0";
config.max_concurrent_streams = 100;
h2_client client(config);
ELIO_LOG_INFO("=== HTTP/2 Client Example ===");
ELIO_LOG_INFO("Base URL: {}", base_url);
// 1. Simple GET request
ELIO_LOG_INFO("\n--- HTTP/2 GET Request ---");
{
auto result = co_await client.get(base_url);
if (result) {
auto& resp = *result;
ELIO_LOG_INFO("Status: {}", static_cast<int>(resp.get_status()));
ELIO_LOG_INFO("Content-Type: {}", resp.content_type());
ELIO_LOG_INFO("Body length: {} bytes", resp.body().size());
// Print first 200 chars of body
auto body = resp.body();
if (body.size() > 200) {
ELIO_LOG_INFO("Body (truncated): {}", body.substr(0, 200));
} else {
ELIO_LOG_INFO("Body: {}", body);
}
} else {
ELIO_LOG_ERROR("HTTP/2 GET request failed: {}", strerror(errno));
}
}
// 2. Multiple requests using same connection (HTTP/2 multiplexing)
ELIO_LOG_INFO("\n--- HTTP/2 Connection Multiplexing ---");
{
ELIO_LOG_INFO("Making multiple requests over single HTTP/2 connection...");
for (int i = 1; i <= 3; ++i) {
ELIO_LOG_INFO("Request {}/3...", i);
auto result = co_await client.get(base_url);
if (result) {
ELIO_LOG_INFO(" Status: {} (body: {} bytes)",
static_cast<int>(result->get_status()),
result->body().size());
} else {
ELIO_LOG_ERROR(" Request {} failed", i);
}
}
ELIO_LOG_INFO("All requests used HTTP/2 multiplexed streams on single connection");
}
ELIO_LOG_INFO("\n=== HTTP/2 Client Example Complete ===");
co_return;
}
/// Simple one-off HTTP/2 request demonstration
coro::task<void> simple_fetch(const std::string& url) {
ELIO_LOG_INFO("Fetching via HTTP/2: {}", url);
// Use convenience function for one-off requests
auto result = co_await h2_get(url);
if (result) {
auto& resp = *result;
ELIO_LOG_INFO("Status: {}", static_cast<int>(resp.get_status()));
ELIO_LOG_INFO("Content-Type: {}", resp.content_type());
ELIO_LOG_INFO("Content-Length: {}", resp.body().size());
// Print response headers
ELIO_LOG_INFO("Response Headers:");
for (const auto& [name, value] : resp.get_headers()) {
ELIO_LOG_INFO(" {}: {}", name, value);
}
// Print response body (truncated if too long)
auto body = resp.body();
if (body.size() > 500) {
ELIO_LOG_INFO("Body (first 500 chars):\n{}", body.substr(0, 500));
} else {
ELIO_LOG_INFO("Body:\n{}", body);
}
} else {
ELIO_LOG_ERROR("HTTP/2 request failed: {}", strerror(errno));
ELIO_LOG_INFO("Note: HTTP/2 requires HTTPS and server support for h2 ALPN.");
}
co_return;
}
/// Async main - uses ELIO_ASYNC_MAIN for automatic scheduler management
coro::task<int> async_main(int argc, char* argv[]) {
std::string url;
bool full_demo = false;
ELIO_LOG_INFO("HTTP/2 Client Example");
ELIO_LOG_INFO("Using nghttp2 library for HTTP/2 protocol support");
// Parse arguments
if (argc > 1) {
std::string arg = argv[1];
if (arg == "--demo" || arg == "-d") {
full_demo = true;
url = "https://nghttp2.org/"; // nghttp2.org always supports HTTP/2
} else if (arg == "--help" || arg == "-h") {
std::cout << "Usage: " << argv[0] << " [options] [url]\n"
<< "\n"
<< "Options:\n"
<< " --demo, -d Run full feature demonstration\n"
<< " --help, -h Show this help\n"
<< "\n"
<< "Default: Fetches https://nghttp2.org/\n"
<< "Note: HTTP/2 requires HTTPS and server support for h2 ALPN.\n";
co_return 0;
} else {
url = arg;
}
} else {
// Default: run simple demo
full_demo = false;
url = "https://nghttp2.org/";
}
// Run appropriate mode
if (full_demo) {
co_await run_demo(url);
} else {
co_await simple_fetch(url);
}
co_return 0;
}
// Use ELIO_ASYNC_MAIN - handles scheduler creation, execution, and shutdown automatically
ELIO_ASYNC_MAIN(async_main)