#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <event2/event.h>
#include <event2/buffer.h>
#include <event2/http.h>
#include <event2/http_struct.h>
struct download_context
{
struct evhttp_uri *uri;
struct event_base *base;
struct evhttp_connection *cn;
struct evhttp_request *req;
struct evbuffer *buffer;
int ok;
};
static void download_callback(struct evhttp_request *req, void *arg);
static int download_renew_request(struct download_context *ctx);
static void download_callback(struct evhttp_request *req, void *arg)
{
struct download_context *ctx = (struct download_context *)arg;
struct evhttp_uri *new_uri = NULL;
const char *new_location = NULL;
/* response is ready */
switch(req->response_code)
{
case HTTP_OK:
/*
* * Response is received. No futher handling is required.
* * Finish
* */
event_base_loopexit(ctx->base, 0);
break;
case HTTP_MOVEPERM:
case HTTP_MOVETEMP:
new_location = evhttp_find_header(req->input_headers, "Location");
if (!new_location)
return;
new_uri = evhttp_uri_parse(new_location);
if (!new_uri)
return;
evhttp_uri_free(ctx->uri);
ctx->uri = new_uri;
download_renew_request(ctx);
return;
default:
/* FAILURE */
event_base_loopexit(ctx->base, 0);
return;
}
evbuffer_add_buffer(ctx->buffer, req->input_buffer);
/* SUCCESS */
ctx->ok = 1;
}
struct download_context *context_new(const char *url)
{
struct download_context *ctx = 0;
ctx = new (struct download_context);//(struct download_context*)calloc(0, sizeof(*ctx));
if (!ctx)
return 0;
ctx->uri = evhttp_uri_parse(url);
if (!ctx->uri)
return 0;
ctx->base = event_base_new();
if (!ctx->base)
return 0;
ctx->buffer = evbuffer_new();
download_renew_request(ctx);
return ctx;
}
void context_free(struct download_context *ctx)
{
evhttp_connection_free(ctx->cn);
event_base_free(ctx->base);
if (ctx->buffer)
evbuffer_free(ctx->buffer);
evhttp_uri_free(ctx->uri);
free(ctx);
}
static int download_renew_request(struct download_context *ctx)
{
/* free connections & request */
if (ctx->cn)
evhttp_connection_free(ctx->cn);
ctx->cn = evhttp_connection_base_new(ctx->base, NULL, "127.0.0.1", 56777);
ctx->req = evhttp_request_new(download_callback, ctx);
evhttp_make_request(ctx->cn, ctx->req, EVHTTP_REQ_GET, "/Hello");
evhttp_add_header(ctx->req->output_headers, "Host", "127.0.0.1");
return 0;
}
struct evbuffer *download_url(const char *url)
{
/* setup request, connection etc */
struct download_context *ctx = context_new(url);
if (!ctx)
return 0;
/* do all of the job */
event_base_dispatch(ctx->base);
struct evbuffer *retval = 0;
if (ctx->ok)
{
retval = ctx->buffer;
ctx->buffer = 0;
}
context_free(ctx);
return retval;
}
int main(int argc, char *argv[])
{
if (argc < 2)
{
printf("usage: %s example.com/\n", argv[0]);
return 1;
}
struct evbuffer *data = download_url(argv[1]);
printf("got %d bytes\n", data ? evbuffer_get_length(data) : -1);
if (data)
{
const unsigned char *joined = evbuffer_pullup(data, -1);
printf("data itself:\n====================\n");
::write(1, joined, evbuffer_get_length(data));
printf("\n====================\n");
evbuffer_free(data);
}
return 0;
}