16 #include <sys/types.h>
22 #include "libevent/include/event2/buffer.h"
23 #include "libevent/include/event2/bufferevent.h"
24 #include "libevent/include/event2/event.h"
25 #include "libevent/include/event2/http.h"
26 #include "libevent/include/event2/keyvalq_struct.h"
27 #include "libevent/include/event2/util.h"
31 struct event_base* ev_base;
32 struct evhttp_uri* http_uri;
33 struct evhttp_connection* evcon;
35 void response_cb(
struct evhttp_request* req,
void* ctx) {
40 int errcode = EVUTIL_SOCKET_ERROR();
41 fprintf(stderr,
"socket error = %s (%d)\n",
42 evutil_socket_error_to_string(errcode), errcode);
46 fprintf(stderr,
"Response line: %d %s\n",
47 evhttp_request_get_response_code(req),
48 evhttp_request_get_response_code_line(req));
50 struct evkeyvalq* headers = evhttp_request_get_input_headers(req);
51 struct evkeyval* header;
52 for (header = headers->tqh_first; header; header = header->next.tqe_next) {
53 fprintf(stderr,
"%s : %s\n", header->key, header->value);
56 while ((nread = evbuffer_remove(evhttp_request_get_input_buffer(req), buffer,
57 sizeof(buffer))) > 0) {
58 fwrite(buffer,
static_cast<size_t>(nread), 1, stderr);
62 void help() { fputs(
"Usage: ev_fetch-client uri [body]\n", stderr); }
64 void err(
const char* msg) { fputs(msg, stderr); }
67 if (evcon !=
nullptr) {
68 evhttp_connection_free(evcon);
70 if (http_uri !=
nullptr) {
71 evhttp_uri_free(http_uri);
74 event_base_free(ev_base);
79 int main(
int argc,
char** argv) {
80 fprintf(stdout,
"Start the http client ...\n");
82 if (argc < 2 || argc > 3) {
87 const char* url = argv[1];
89 const char* body =
nullptr;
95 http_uri = evhttp_uri_parse(url);
96 if (http_uri ==
nullptr) {
101 const char* scheme = evhttp_uri_get_scheme(http_uri);
102 if (scheme ==
nullptr || strcasecmp(scheme,
"http") != 0) {
103 err(
"url must be http");
107 const char* host = evhttp_uri_get_host(http_uri);
108 if (host ==
nullptr) {
109 err(
"url must have a host");
113 int port = evhttp_uri_get_port(http_uri);
115 port = (strcasecmp(scheme,
"http") == 0) ? 80 : 443;
118 const char* path = evhttp_uri_get_path(http_uri);
119 if (strlen(path) == 0) {
124 const char* query = evhttp_uri_get_query(http_uri);
125 if (query ==
nullptr) {
126 snprintf(uri,
sizeof(uri) - 1,
"%s", path);
128 snprintf(uri,
sizeof(uri) - 1,
"%s?%s", path, query);
130 uri[
sizeof(uri) - 1] =
'\0';
133 ev_base = event_base_new();
134 if (ev_base ==
nullptr) {
135 perror(
"event_base_new()");
148 evcon = evhttp_connection_base_bufferevent_new(
149 ev_base,
nullptr,
nullptr, host,
static_cast<uint16_t
>(port));
150 if (evcon ==
nullptr) {
151 fprintf(stderr,
"evhttp_connection_base_bufferevent_new() failed\n");
156 evhttp_connection_set_retries(evcon, retries);
158 int timeout_in_secs = 5;
159 evhttp_connection_set_timeout(evcon, timeout_in_secs);
161 struct evhttp_request* req = evhttp_request_new(response_cb, evcon);
162 if (req ==
nullptr) {
163 fprintf(stderr,
"evhttp_request_new() failed\n");
167 struct evkeyvalq* output_headers = evhttp_request_get_output_headers(req);
168 evhttp_add_header(output_headers,
"Host", host);
169 evhttp_add_header(output_headers,
"Connection",
"close");
172 struct evbuffer* output_buffer = evhttp_request_get_output_buffer(req);
173 size_t size = strlen(body);
175 evbuffer_add(output_buffer, body, size);
177 char length_header[8];
178 evutil_snprintf(length_header,
sizeof(length_header) - 1,
"%lu", size);
179 evhttp_add_header(output_headers,
"Content-Length", length_header);
182 int r = evhttp_make_request(evcon, req,
183 body ? EVHTTP_REQ_POST : EVHTTP_REQ_GET, uri);
185 fprintf(stderr,
"evhttp_make_request() failed\n");
189 event_base_dispatch(ev_base);