Skip to content

Instantly share code, notes, and snippets.

@mythosil
Created August 18, 2011 17:11
Show Gist options
  • Save mythosil/1154552 to your computer and use it in GitHub Desktop.
Save mythosil/1154552 to your computer and use it in GitHub Desktop.
evhttp returns static files
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <event.h>
#include <evhttp.h>
#define HTTPD_ADDR "0.0.0.0"
#define HTTPD_PORT 8080
#define DOCUMENT_ROOT "./"
static const char *get_mime_type(const char *filetype)
{
if (filetype == NULL ||
strcasecmp(filetype, "html") == 0 ||
strcasecmp(filetype, "htm") == 0)
return "text/html";
else if (strcasecmp(filetype, "js") == 0)
return "text/javascript";
else if (strcasecmp(filetype, "css") == 0)
return "text/css";
else if (strcasecmp(filetype, "txt") == 0)
return "text/plain";
else if (strcasecmp(filetype, "ico") == 0)
return "image/x-icon";
else if (strcasecmp(filetype, "png") == 0)
return "image/png";
else if (strcasecmp(filetype, "gif") == 0)
return "image/gif";
else if (strcasecmp(filetype, "jpeg") == 0 ||
strcasecmp(filetype, "jpg") == 0)
return "image/jpeg";
return "application/ocet-stream";
}
static char *get_file_content(const char *req_path, int *content_length)
{
struct stat sb;
static char filepath[1024];
char *content;
FILE *fp;
int rsize;
sprintf(filepath, "%s%s", DOCUMENT_ROOT, req_path);
if (stat(filepath, &sb) < 0) /* not found */
return NULL;
if (S_ISDIR(sb.st_mode)) {
sprintf(filepath, "%s%s/index.html", DOCUMENT_ROOT, req_path);
if (stat(filepath, &sb) < 0) /* not found */
return NULL;
}
*content_length = (int)sb.st_size;
fp = fopen(filepath, "rb");
content = NULL;
if (fp) {
content = (char *)malloc(*content_length);
rsize = fread(content, 1, *content_length, fp);
fclose(fp);
if (rsize != *content_length) {
free(content);
content = NULL;
}
}
return content;
}
void req_handler(struct evhttp_request *r, void *arg)
{
struct evbuffer *evbuf;
const char *req_path, *filetype, *mime_type;
char *content;
int content_length;
char content_length_str[12];
if (r->type != EVHTTP_REQ_GET) {
evhttp_send_error(r, HTTP_BADREQUEST, "available GET only");
return;
}
req_path = evhttp_request_uri(r);
content = get_file_content(req_path, &content_length);
if (content == NULL) {
evhttp_send_error(r, HTTP_NOTFOUND, "Not Found");
return;
}
filetype = strrchr(req_path, '.');
if (filetype == NULL)
mime_type = get_mime_type(NULL);
else
mime_type = get_mime_type(filetype + 1);
sprintf(content_length_str, "%d", content_length);
evhttp_add_header(r->output_headers, "Content-Type", mime_type);
evhttp_add_header(r->output_headers, "Content-Length", content_length_str);
evbuf = evbuffer_new();
if (evbuf == NULL) {
evhttp_send_error(r, HTTP_SERVUNAVAIL, "failed to create buffer");
free(content);
return;
}
evbuffer_add(evbuf, content, content_length);
evhttp_send_reply(r, HTTP_OK, "", evbuf);
evbuffer_free(evbuf);
free(content);
}
int main(int argc, const char* argv[])
{
struct event_base *ev_base;
struct evhttp *httpd;
ev_base = event_base_new();
httpd = evhttp_new(ev_base);
if (evhttp_bind_socket(httpd, HTTPD_ADDR, HTTPD_PORT) < 0) {
perror("evhttp_bind_socket()");
exit(EXIT_FAILURE);
}
evhttp_set_gencb(httpd, req_handler, NULL);
event_base_dispatch(ev_base);
evhttp_free(httpd);
event_base_free(ev_base);
return 0;
}
@mythosil
Copy link
Author

oops, there're terrible bugs.
should not return text/html for filetype == NULL (in get_mime_type).
also, not considering security.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment