17 #include <sys/socket.h>
18 #include <sys/types.h>
24 #include "absl/strings/numbers.h"
26 #include "libevent/include/event2/buffer.h"
27 #include "libevent/include/event2/event.h"
28 #include "libevent/include/event2/http.h"
29 #include "libevent/include/event2/keyvalq_struct.h"
30 #include "libevent/include/event2/util.h"
36 void request_cb(
struct evhttp_request *req,
void *arg) {
39 switch (evhttp_request_get_command(req)) {
52 case EVHTTP_REQ_DELETE:
55 case EVHTTP_REQ_OPTIONS:
58 case EVHTTP_REQ_TRACE:
61 case EVHTTP_REQ_CONNECT:
64 case EVHTTP_REQ_PATCH:
72 struct evbuffer *response_body = evbuffer_new();
73 if (response_body ==
nullptr) {
74 evhttp_send_error(req, HTTP_SERVUNAVAIL,
nullptr);
78 evbuffer_add_printf(response_body,
81 " <meta charset='utf-8'>\n"
82 " <title>Mini libevent httpserver</title>\n"
85 " <h1>Print the HTTP request detail</h1>\n"
88 evbuffer_add_printf(response_body,
"HTTP Method: %s <br>\n", method);
90 const char *uri = evhttp_request_get_uri(req);
91 evbuffer_add_printf(response_body,
"Request Uri: %s <br>\n", uri);
93 struct evhttp_uri *decoded_url = evhttp_uri_parse(uri);
94 if (decoded_url ==
nullptr) {
95 evhttp_send_error(req, HTTP_BADREQUEST,
nullptr);
99 evbuffer_add_printf(response_body,
"Decoded Uri:<br>\n");
101 evbuffer_add_printf(response_body,
" scheme : %s <br>\n",
102 evhttp_uri_get_scheme(decoded_url));
103 evbuffer_add_printf(response_body,
" host : %s <br>\n",
104 evhttp_uri_get_host(decoded_url));
105 evbuffer_add_printf(response_body,
" port : %d <br>\n",
106 evhttp_uri_get_port(decoded_url));
107 evbuffer_add_printf(response_body,
" path : %s <br>\n",
108 evhttp_uri_get_path(decoded_url));
109 evbuffer_add_printf(response_body,
" query : %s <br>\n",
110 evhttp_uri_get_query(decoded_url));
112 const char *path = evhttp_uri_get_path(decoded_url);
113 if (path ==
nullptr) {
117 evbuffer_add_printf(response_body,
"Uri path: %s <br>\n", path);
119 char *decoded_path = evhttp_uridecode(path, 1,
nullptr);
120 if (decoded_path ==
nullptr) {
121 evhttp_send_error(req, HTTP_BADREQUEST,
nullptr);
125 evbuffer_add_printf(response_body,
"Decoded path: %s <br>\n", decoded_path);
127 evbuffer_add_printf(response_body,
"<br><br>====<br><br>\n");
129 struct evkeyvalq *headers = evhttp_request_get_input_headers(req);
131 struct evkeyval *header;
132 for (header = headers->tqh_first; header; header = header->next.tqe_next) {
133 evbuffer_add_printf(response_body,
"%s : %s<br>\n", header->key,
137 struct evbuffer *request_body = evhttp_request_get_input_buffer(req);
138 if (request_body !=
nullptr) {
139 evbuffer_add_printf(response_body,
"<br><br>====<br><br>\n");
140 int result = evbuffer_add_buffer_reference(response_body, request_body);
142 evbuffer_add_printf(response_body,
">>> Failed to print the body<br>\n");
146 evhttp_add_header(evhttp_request_get_output_headers(req),
"Content-Type",
149 evhttp_send_reply(req, 200,
"OK", response_body);
151 evhttp_uri_free(decoded_url);
153 evbuffer_free(response_body);
156 void help() { fprintf(stdout,
"Usage: ev_print_req_server <port:8080>\n"); }
160 int main(
int argc,
char **argv) {
161 fprintf(stdout,
"Start the http server ...\n");
163 struct event_base *base;
165 struct evhttp_bound_socket *handle;
167 ev_uint32_t port = 8080;
174 bool port_parsed = absl::SimpleAtoi(argv[1], &port);
176 fprintf(stderr,
"Invalid port: %s\n", argv[1]);
179 base = event_base_new();
181 fprintf(stderr,
"Couldn't create an event_base: exiting\n");
185 http = evhttp_new(base);
187 fprintf(stderr,
"couldn't create evhttp. Exiting.\n");
192 evhttp_set_gencb(http, request_cb, NULL);
196 handle = evhttp_bind_socket_with_handle(http,
"::0", (ev_uint16_t)port);
198 fprintf(stderr,
"couldn't bind to port %d. Exiting.\n", (
int)port);
204 struct sockaddr_storage ss = {};
206 ev_socklen_t socklen =
sizeof(ss);
211 fd = evhttp_bound_socket_get_fd(handle);
212 memset(&ss, 0,
sizeof(ss));
213 if (getsockname(fd, (
struct sockaddr *)&ss, &socklen)) {
214 perror(
"getsockname() failed");
217 if (ss.ss_family == AF_INET) {
218 got_port = ntohs(((
struct sockaddr_in *)&ss)->sin_port);
219 inaddr = &((
struct sockaddr_in *)&ss)->sin_addr;
220 }
else if (ss.ss_family == AF_INET6) {
221 got_port = ntohs(((
struct sockaddr_in6 *)&ss)->sin6_port);
222 inaddr = &((
struct sockaddr_in6 *)&ss)->sin6_addr;
224 fprintf(stderr,
"Weird address family %d\n", ss.ss_family);
227 addr = evutil_inet_ntop(ss.ss_family, inaddr, addrbuf,
sizeof(addrbuf));
229 printf(
"Listening on %s:%d\n", addr, got_port);
230 evutil_snprintf(uri_root,
sizeof(uri_root),
"http://%s:%d", addr,
233 fprintf(stderr,
"evutil_inet_ntop failed\n");
238 event_base_dispatch(base);