Skip to content

Commit 8431439

Browse files
committed
example
1 parent b070017 commit 8431439

1 file changed

Lines changed: 267 additions & 0 deletions

File tree

Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
/**
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0.
4+
*/
5+
6+
#include <aws/http/connection.h>
7+
#include <aws/http/request_response.h>
8+
#include <aws/io/channel_bootstrap.h>
9+
#include <aws/io/event_loop.h>
10+
#include <aws/io/host_resolver.h>
11+
#include <aws/io/socket.h>
12+
#include <aws/io/stream.h>
13+
#include <aws/io/tls_channel_handler.h>
14+
15+
#include <aws/common/condition_variable.h>
16+
#include <aws/common/mutex.h>
17+
#include <aws/common/string.h>
18+
19+
#include <inttypes.h>
20+
21+
struct app_ctx {
22+
struct aws_allocator *allocator;
23+
struct aws_mutex mutex;
24+
struct aws_condition_variable cv;
25+
struct aws_http_connection *connection;
26+
struct aws_http_stream *stream;
27+
bool connection_completed;
28+
bool stream_completed;
29+
int error_code;
30+
size_t bytes_to_send;
31+
size_t bytes_sent;
32+
};
33+
34+
static void s_on_write_complete(struct aws_http_stream *stream, int error_code, void *user_data) {
35+
(void)stream;
36+
struct app_ctx *ctx = user_data;
37+
38+
if (error_code) {
39+
fprintf(stderr, "Write failed with error: %s\n", aws_error_name(error_code));
40+
return;
41+
}
42+
43+
fprintf(stdout, "Write completed successfully\n");
44+
}
45+
46+
static void s_on_stream_complete(struct aws_http_stream *stream, int error_code, void *user_data) {
47+
(void)stream;
48+
struct app_ctx *ctx = user_data;
49+
50+
aws_mutex_lock(&ctx->mutex);
51+
ctx->stream_completed = true;
52+
ctx->error_code = error_code;
53+
aws_mutex_unlock(&ctx->mutex);
54+
aws_condition_variable_notify_one(&ctx->cv);
55+
56+
if (error_code) {
57+
fprintf(stderr, "Stream completed with error: %s\n", aws_error_name(error_code));
58+
} else {
59+
fprintf(stdout, "Stream completed successfully\n");
60+
}
61+
}
62+
63+
static void s_on_connection_setup(struct aws_http_connection *connection, int error_code, void *user_data) {
64+
struct app_ctx *ctx = user_data;
65+
66+
aws_mutex_lock(&ctx->mutex);
67+
if (error_code) {
68+
fprintf(stderr, "Connection failed: %s\n", aws_error_name(error_code));
69+
ctx->connection_completed = true;
70+
ctx->error_code = error_code;
71+
} else {
72+
fprintf(stdout, "Connection established\n");
73+
ctx->connection = connection;
74+
}
75+
aws_mutex_unlock(&ctx->mutex);
76+
aws_condition_variable_notify_one(&ctx->cv);
77+
}
78+
79+
static void s_on_connection_shutdown(struct aws_http_connection *connection, int error_code, void *user_data) {
80+
(void)connection;
81+
struct app_ctx *ctx = user_data;
82+
83+
aws_mutex_lock(&ctx->mutex);
84+
ctx->connection_completed = true;
85+
if (error_code) {
86+
fprintf(stderr, "Connection shutdown with error: %s\n", aws_error_name(error_code));
87+
}
88+
aws_mutex_unlock(&ctx->mutex);
89+
aws_condition_variable_notify_one(&ctx->cv);
90+
}
91+
92+
static bool s_connection_ready(void *user_data) {
93+
struct app_ctx *ctx = user_data;
94+
return ctx->connection != NULL;
95+
}
96+
97+
static bool s_stream_completed(void *user_data) {
98+
struct app_ctx *ctx = user_data;
99+
return ctx->stream_completed;
100+
}
101+
102+
static bool s_connection_completed(void *user_data) {
103+
struct app_ctx *ctx = user_data;
104+
return ctx->connection_completed;
105+
}
106+
107+
int main(int argc, char **argv) {
108+
(void)argc;
109+
(void)argv;
110+
111+
struct aws_allocator *allocator = aws_default_allocator();
112+
aws_http_library_init(allocator);
113+
114+
struct app_ctx ctx = {
115+
.allocator = allocator,
116+
.bytes_to_send = 1024,
117+
};
118+
aws_mutex_init(&ctx.mutex);
119+
aws_condition_variable_init(&ctx.cv);
120+
121+
/* Setup event loop */
122+
struct aws_event_loop_group *el_group = aws_event_loop_group_new_default(allocator, 1, NULL);
123+
struct aws_host_resolver_default_options resolver_options = {
124+
.el_group = el_group,
125+
.max_entries = 8,
126+
};
127+
struct aws_host_resolver *resolver = aws_host_resolver_new_default(allocator, &resolver_options);
128+
struct aws_client_bootstrap_options bootstrap_options = {
129+
.event_loop_group = el_group,
130+
.host_resolver = resolver,
131+
};
132+
struct aws_client_bootstrap *bootstrap = aws_client_bootstrap_new(allocator, &bootstrap_options);
133+
134+
/* Connect to httpbin.org */
135+
struct aws_socket_options socket_options = {
136+
.type = AWS_SOCKET_STREAM,
137+
.domain = AWS_SOCKET_IPV4,
138+
.connect_timeout_ms = 3000,
139+
};
140+
141+
struct aws_http_client_connection_options conn_options = {
142+
.self_size = sizeof(conn_options),
143+
.socket_options = &socket_options,
144+
.allocator = allocator,
145+
.host_name = aws_byte_cursor_from_c_str("httpbin.org"),
146+
.port = 80,
147+
.bootstrap = bootstrap,
148+
.on_setup = s_on_connection_setup,
149+
.on_shutdown = s_on_connection_shutdown,
150+
.user_data = &ctx,
151+
};
152+
153+
aws_http_client_connect(&conn_options);
154+
155+
/* Wait for connection */
156+
aws_mutex_lock(&ctx.mutex);
157+
aws_condition_variable_wait_pred(&ctx.cv, &ctx.mutex, s_connection_ready, &ctx);
158+
aws_mutex_unlock(&ctx.mutex);
159+
160+
if (!ctx.connection) {
161+
fprintf(stderr, "Failed to establish connection\n");
162+
goto cleanup;
163+
}
164+
165+
/* Create request with Content-Length */
166+
struct aws_http_message *request = aws_http_message_new_request(allocator);
167+
if (!request) {
168+
fprintf(stderr, "Failed to create request\n");
169+
goto cleanup;
170+
}
171+
172+
if (aws_http_message_set_request_method(request, aws_byte_cursor_from_c_str("POST"))) {
173+
fprintf(stderr, "Failed to set request method\n");
174+
aws_http_message_release(request);
175+
goto cleanup;
176+
}
177+
178+
if (aws_http_message_set_request_path(request, aws_byte_cursor_from_c_str("/post"))) {
179+
fprintf(stderr, "Failed to set request path\n");
180+
aws_http_message_release(request);
181+
goto cleanup;
182+
}
183+
184+
struct aws_http_header headers[] = {
185+
{.name = aws_byte_cursor_from_c_str("Host"), .value = aws_byte_cursor_from_c_str("httpbin.org")},
186+
{.name = aws_byte_cursor_from_c_str("Content-Length"), .value = aws_byte_cursor_from_c_str("1024")},
187+
{.name = aws_byte_cursor_from_c_str("Content-Type"), .value = aws_byte_cursor_from_c_str("text/plain")},
188+
};
189+
for (size_t i = 0; i < AWS_ARRAY_SIZE(headers); ++i) {
190+
aws_http_message_add_header(request, headers[i]);
191+
}
192+
193+
/* Make request with manual data writes */
194+
/* Note: This minimal example demonstrates sending data but does not read the response */
195+
struct aws_http_make_request_options options = {
196+
.self_size = sizeof(options),
197+
.request = request,
198+
.use_manual_data_writes = true,
199+
.on_complete = s_on_stream_complete,
200+
.user_data = &ctx,
201+
};
202+
203+
ctx.stream = aws_http_connection_make_request(ctx.connection, &options);
204+
if (!ctx.stream) {
205+
fprintf(stderr, "Failed to create stream\n");
206+
aws_http_message_release(request);
207+
goto cleanup;
208+
}
209+
210+
aws_http_stream_activate(ctx.stream);
211+
aws_http_message_release(request);
212+
213+
/* Write data in chunks */
214+
uint8_t data[256];
215+
memset(data, 'A', sizeof(data));
216+
217+
for (size_t i = 0; i < 4; ++i) {
218+
struct aws_byte_cursor chunk = aws_byte_cursor_from_array(data, sizeof(data));
219+
struct aws_input_stream *input_stream = aws_input_stream_new_from_cursor(allocator, &chunk);
220+
221+
struct aws_http_stream_write_data_options write_options = {
222+
.data = input_stream,
223+
.end_stream = (i == 3),
224+
.on_complete = s_on_write_complete,
225+
.user_data = &ctx,
226+
};
227+
228+
if (aws_http_stream_write_data(ctx.stream, &write_options)) {
229+
fprintf(stderr, "Failed to write data: %s\n", aws_error_name(aws_last_error()));
230+
aws_input_stream_release(input_stream);
231+
break;
232+
}
233+
234+
ctx.bytes_sent += sizeof(data);
235+
fprintf(stdout, "Queued write %zu/%zu bytes\n", ctx.bytes_sent, ctx.bytes_to_send);
236+
237+
aws_input_stream_release(input_stream);
238+
}
239+
240+
/* Wait for stream completion */
241+
aws_mutex_lock(&ctx.mutex);
242+
aws_condition_variable_wait_pred(&ctx.cv, &ctx.mutex, s_stream_completed, &ctx);
243+
aws_mutex_unlock(&ctx.mutex);
244+
245+
aws_http_stream_release(ctx.stream);
246+
247+
cleanup:
248+
if (ctx.connection) {
249+
aws_http_connection_release(ctx.connection);
250+
}
251+
252+
/* Wait for connection shutdown */
253+
aws_mutex_lock(&ctx.mutex);
254+
aws_condition_variable_wait_pred(&ctx.cv, &ctx.mutex, s_connection_completed, &ctx);
255+
aws_mutex_unlock(&ctx.mutex);
256+
257+
aws_client_bootstrap_release(bootstrap);
258+
aws_host_resolver_release(resolver);
259+
aws_event_loop_group_release(el_group);
260+
261+
aws_condition_variable_clean_up(&ctx.cv);
262+
aws_mutex_clean_up(&ctx.mutex);
263+
264+
aws_http_library_clean_up();
265+
266+
return ctx.error_code ? 1 : 0;
267+
}

0 commit comments

Comments
 (0)