Skip to content

Instantly share code, notes, and snippets.

@gkres
Last active December 15, 2015 00:09
Show Gist options
  • Save gkres/5170799 to your computer and use it in GitHub Desktop.
Save gkres/5170799 to your computer and use it in GitHub Desktop.
Libevent http server that acts like a middle man between a client and http server. (A quick example, just to try and clear a few libevent related things up. Pretty sure it could have been done better.)
#include <iostream>
#include <event.h>
#include <evhttp.h>
#include <event2/event.h>
#include <event2/http.h>
#include <event2/buffer.h>
#include <sys/queue.h>
#include <cstdlib>
#include <string.h>
using namespace std;
static void final_reply_cb(struct evhttp_request *req, void *arg) {
string body;
struct evhttp_request* r = (evhttp_request*)arg;
// Prepare things for an outgoing response
struct evbuffer *output_buffer;
output_buffer = evbuffer_new();
struct evkeyvalq *output_headers = evhttp_request_get_output_headers(r);
evhttp_add_header(output_headers, "Content-Type", "text/plain");
string response = "";
// Parse the incoming response body
int len = evbuffer_get_length(req->input_buffer);
void *buf = malloc(len);
evbuffer_copyout(req->input_buffer, buf, len);
body = string(static_cast<char*>(buf), len);
// Send the outgoing response
evbuffer_add_printf(output_buffer, "%s", body.c_str());
evhttp_send_reply(r, HTTP_OK, "OK", output_buffer);
evbuffer_free(output_buffer);
}
void request_to_endpoint_cb(struct evhttp_request *r, void *arg) {
// Parse the URI parameters
struct evkeyvalq* args = new evkeyvalq;
const char *uri = evhttp_request_get_uri(r);
const char *query_part;
struct evhttp_uri* parsed_uri = NULL;
parsed_uri = evhttp_uri_parse(uri);
if (parsed_uri != NULL) query_part = evhttp_uri_get_query(parsed_uri);
else query_part = uri;
string type = "";
evhttp_parse_query_str(query_part,args);
struct evkeyval *param;
TAILQ_FOREACH(param, args,next) {
if (strcmp(param->key,"type") == 0) {
type = param->value;
break;
}
}
string url = "";
string host = "";
string host_ip = "";
if (type == "1") {
url = "http://www.google.com/robots.txt";
host = "google.com";
host_ip = "173.194.70.113";
} else {
url = "http://localhost/sleep10"; // nginx set to wait 10 sec before replying
host = "localhost";
host_ip = "192.168.2.15";
}
// Create new connection to server
const char *addr = host_ip.c_str();
unsigned int port = 80;
struct evhttp_connection *connection = evhttp_connection_new(addr, port);
evhttp_connection_set_timeout(connection, 15);
// Create the http request
struct evhttp_request *request = evhttp_request_new(final_reply_cb, r);
evhttp_add_header(request->output_headers, "Host", host.c_str());
evhttp_add_header(request->output_headers, "Content-Length", "0");
cout << "(proxy) Making a request to endpoint (" << url << ")." << endl;
evhttp_make_request(connection, request, EVHTTP_REQ_GET, url.c_str());
cout << "(proxy) Request to endpoint made (" << url << "), waiting for a reply." << endl;
}
int main(int argc, char* argv[]) {
cout << "Starting test http server" << endl;
// Setup evhttp server
struct event_base *libeventbase = event_init();
struct evhttp *metrics_server;
metrics_server = evhttp_new(libeventbase);
evhttp_bind_socket(metrics_server, "0.0.0.0", 8080);
evhttp_set_cb(metrics_server, "/test", request_to_endpoint_cb, libeventbase);
event_dispatch();
event_base_free(libeventbase);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment