Merge branch 'release/0.3.5'
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 708128f..589c7e6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,7 +4,7 @@
 
 set(PROJECT_MAJOR_VERSION 0)
 set(PROJECT_MINOR_VERSION 3)
-set(PROJECT_PATCH_VERSION 4)
+set(PROJECT_PATCH_VERSION 5)
 
 set (PROJECT_VERSION ${PROJECT_MAJOR_VERSION}.${PROJECT_MINOR_VERSION}.${PROJECT_PATCH_VERSION})
 set (CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeModules)
diff --git a/ChangeLog b/ChangeLog
index 077c9d3..58882d3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,35 @@
+v0.3.5
+ - Added evhtp_request_t accessors
+
+	evbuf_t          * evhtp_request_get_input(evhtp_request_t *);
+	evbuf_t          * evhtp_request_get_output(evhtp_request_t *);
+	evbase_t         * evhtp_request_get_evbase(evhtp_request_t *);
+	evserv_t         * evhtp_request_get_listener(evhtp_request_t *);
+	evhtp_method       evhtp_request_get_method(evhtp_request_t *);
+	evhtp_proto        evhtp_request_get_proto(evhtp_request_t *);
+	evhtp_conn_t     * evhtp_request_get_conn(evhtp_request_t *);
+	evhtp_hdrs_t     * evhtp_request_get_headers_in(evhtp_request_t *);
+	evhtp_hdrs_t     * evhtp_request_get_headers_out(evhtp_request_t *);
+	evhtp_callback_cb  evhtp_request_get_cb(evhtp_request_t *);
+	void             * evhtp_request_get_cbarg(evhtp_request_t *);
+	int                evhtp_request_get_sock(evhtp_request_t *);
+	const char       * evhtp_request_get_path(evhtp_request_t *);
+	const char       * evhtp_request_get_uri(evhtp_request_t *);
+	const char       * evhtp_request_method_str(evhtp_request_t *);
+	int                evhtp_request_get_matched_soff(evhtp_request_t *);
+	int                evhtp_request_get_matched_eoff(evhtp_request_t *);
+	int64_t            evhtp_request_get_content_length(evhtp_request_t *);
+
+ - Better callback return error and response handling.
+		* Callbacks which return an evhtp_res code now must use
+      EVHTP_RES_*, where each EVHTP_RES_* definition is a HTTP
+      status code. For example "return EVHTP_RES_400;" will
+      send a 404 error to the client, along with terminating
+      the parser.
+
+ - All static functions prefixed with _htp_* are now just static htp_
+ - Various small bugfixes.
+
 v0.3.4
  - Added optional OpenSSL support (with optional threading abstractions).
    * In order to properly enable SSL for your server two things must happen:
diff --git a/evhtp.c b/evhtp.c
index 5b43fee..9813133 100644
--- a/evhtp.c
+++ b/evhtp.c
@@ -11,6 +11,7 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <assert.h>
 
 #include "http_parser.h"
 #include "onigposix.h"
@@ -125,6 +126,7 @@
     evhtp_request_t * request;
     http_parser     * parser;
     int               sock;
+    evhtp_res         err;
     evhtp_cflags      flags;
     evbase_t        * evbase;
     evbev_t         * bev;
@@ -145,124 +147,127 @@
 #define _HTP_DEFSERVER  "libevht"
 #define _HTP_DEFCHUNKED "chunked"
 
-#ifdef DEBUG
-#define __QUOTE(x)                     # x
-#define  _QUOTE(x)                     __QUOTE(x)
+#ifdef HTP_DEBUG
+#define __QUOTE(x)                    # x
+#define  _QUOTE(x)                    __QUOTE(x)
 
-#define evhtp_log_debug(fmt, ...)      do {                    \
+#define evhtp_log_debug(fmt, ...)     do {                     \
         fprintf(stdout, __FILE__ "[" _QUOTE(__LINE__) "] %s: " \
-            fmt "\n", __func__, ## __VA_ARGS__);               \
+                fmt "\n", __func__, ## __VA_ARGS__);           \
         fflush(stdout);                                        \
 } while (0)
 #else
-#define evhtp_log_debug(fmt, ...)      do {} while (0)
+#define evhtp_log_debug(fmt, ...)     do {} while (0)
 #endif
 
-#define _htp_conn_hook(c)              (c)->hooks
-#define _htp_conn_has_hook(c, n)       (_htp_conn_hook(c) && _htp_conn_hook(c)->n)
-#define _htp_conn_hook_cbarg(c, n)     _htp_conn_hook(c)->n ## _cbargs
-#define _htp_conn_hook_call(c, n, ...) _htp_conn_hook(c)->n(c->request, __VA_ARGS__, _htp_conn_hook_cbarg(c, n))
-#define _htp_conn_hook_set(c, n, f, a) do { \
-        _htp_conn_hook(c)->n       = f;     \
-        _htp_conn_hook_cbarg(c, n) = a;     \
+#define htp_conn_hook(c)              (c)->hooks
+#define htp_conn_has_hook(c, n)       (htp_conn_hook(c) && htp_conn_hook(c)->n)
+#define htp_conn_hook_cbarg(c, n)     htp_conn_hook(c)->n ## _cbargs
+#define htp_conn_hook_call(c, n, ...) htp_conn_hook(c)->n(c->request, __VA_ARGS__, htp_conn_hook_cbarg(c, n))
+#define htp_conn_hook_set(c, n, f, a) do { \
+        htp_conn_hook(c)->n       = f;     \
+        htp_conn_hook_cbarg(c, n) = a;     \
 } while (0)
 
 #define CRLF "\r\n"
 
-static evhtp_proto        _htp_proto(char major, char minor);
-static evhtp_callback_t * _htp_callbacks_find_callback(evhtp_callbacks_t *, const char *);
-static evhtp_callback_t * _htp_callbacks_find_callback_woffsets(evhtp_callbacks_t *, const char *, int *, int *);
-static void               _htp_recv_cb(evbev_t * bev, void * arg);
-static void               _htp_err_cb(evbev_t * bev, short events, void * arg);
-static evhtp_request_t  * _htp_request_new(evhtp_conn_t * conn);
+static evhtp_proto        htp_proto(char major, char minor);
+static evhtp_callback_t * htp_callbacks_find_callback(evhtp_callbacks_t *, const char *);
+static evhtp_callback_t * htp_callbacks_find_callback_woffsets(evhtp_callbacks_t *, const char *, int *, int *);
+static void               htp_recv_cb(evbev_t * bev, void * arg);
+static void               htp_err_cb(evbev_t * bev, short events, void * arg);
+static evhtp_request_t  * htp_request_new(evhtp_conn_t * conn);
 
 static int                ssl_num_locks;
 static evhtp_mutex_t   ** ssl_locks;
 
-static evhtp_status
-_htp_run_on_expect_hook(evhtp_conn_t * conn, const char * expt_val) {
-    evhtp_status status = EVHTP_CODE_CONTINUE;
+static evhtp_res
+htp_run_on_expect_hook(evhtp_conn_t * conn, const char * expt_val) {
+    evhtp_res status = EVHTP_RES_CONTINUE;
 
     evhtp_log_debug("enter");
 
-    if (_htp_conn_has_hook(conn, _on_expect)) {
-        status = _htp_conn_hook_call(conn, _on_expect, expt_val);
+    if (htp_conn_has_hook(conn, _on_expect)) {
+        status = htp_conn_hook_call(conn, _on_expect, expt_val);
     }
 
     return status;
 }
 
 static evhtp_res
-_htp_run_hdr_hook(evhtp_conn_t * conn, evhtp_hdr_t * hdr) {
+htp_run_hdr_hook(evhtp_conn_t * conn, evhtp_hdr_t * hdr) {
     evhtp_res res = EVHTP_RES_OK;
 
     evhtp_log_debug("enter");
-    if (_htp_conn_has_hook(conn, _hdr)) {
-        res = _htp_conn_hook_call(conn, _hdr, hdr);
+
+    if (htp_conn_has_hook(conn, _hdr)) {
+        res = htp_conn_hook_call(conn, _hdr, hdr);
     }
 
     return res;
 }
 
 static evhtp_res
-_htp_run_hdrs_hook(evhtp_conn_t * conn, evhtp_hdrs_t * hdrs) {
+htp_run_hdrs_hook(evhtp_conn_t * conn, evhtp_hdrs_t * hdrs) {
     evhtp_res res = EVHTP_RES_OK;
 
     evhtp_log_debug("enter");
-    if (_htp_conn_has_hook(conn, _hdrs)) {
-        res = _htp_conn_hook_call(conn, _hdrs, hdrs);
+    if (htp_conn_has_hook(conn, _hdrs)) {
+        res = htp_conn_hook_call(conn, _hdrs, hdrs);
     }
 
     return res;
 }
 
 static evhtp_res
-_htp_run_path_hook(evhtp_conn_t * conn, const char * path) {
+htp_run_path_hook(evhtp_conn_t * conn, const char * path) {
     evhtp_res res = EVHTP_RES_OK;
 
     evhtp_log_debug("enter");
-    if (_htp_conn_has_hook(conn, _path)) {
-        res = _htp_conn_hook_call(conn, _path, path);
+
+    if (htp_conn_has_hook(conn, _path)) {
+        res = htp_conn_hook_call(conn, _path, path);
     }
 
     return res;
 }
 
 static evhtp_res
-_htp_run_uri_hook(evhtp_conn_t * conn, const char * uri) {
+htp_run_uri_hook(evhtp_conn_t * conn, const char * uri) {
     evhtp_res res = EVHTP_RES_OK;
 
     evhtp_log_debug("enter");
-    if (_htp_conn_has_hook(conn, _uri)) {
-        res = _htp_conn_hook_call(conn, _uri, uri);
+    if (htp_conn_has_hook(conn, _uri)) {
+        res = htp_conn_hook_call(conn, _uri, uri);
     }
 
     return res;
 }
 
 static evhtp_res
-_htp_run_read_hook(evhtp_conn_t * conn, const char * data, size_t sz) {
+htp_run_read_hook(evhtp_conn_t * conn, const char * data, size_t sz) {
     evhtp_res res = EVHTP_RES_OK;
 
     evhtp_log_debug("enter");
-    if (_htp_conn_has_hook(conn, _read)) {
-        res = _htp_conn_hook_call(conn, _read, data, sz);
+    if (htp_conn_has_hook(conn, _read)) {
+        res = htp_conn_hook_call(conn, _read, data, sz);
     }
 
     return res;
 }
 
 static int
-_htp_start_cb(http_parser * p) {
+htp_start_cb(http_parser * p) {
     evhtp_conn_t * conn = p->data;
 
     evhtp_log_debug("enter");
-    conn->request = _htp_request_new(conn);
+
+    conn->request = htp_request_new(conn);
     return 0;
 }
 
 static int
-_htp_end_cb(http_parser * p) {
+htp_end_cb(http_parser * p) {
     evhtp_conn_t    * conn    = NULL;
     evhtp_request_t * request = NULL;
 
@@ -278,7 +283,7 @@
 }
 
 static int
-_htp_query_str_cb(http_parser * p, const char * buf, size_t len) {
+htp_query_str_cb(http_parser * p, const char * buf, size_t len) {
     /* evhtp_conn_t * conn = p->data; */
 
     evhtp_log_debug("len = %" PRIoMAX " buf = '%.*s'", len, (int)len, buf);
@@ -287,7 +292,7 @@
 }
 
 static int
-_htp_uri_cb(http_parser * p, const char * buf, size_t len) {
+htp_uri_cb(http_parser * p, const char * buf, size_t len) {
     evhtp_conn_t    * conn;
     evhtp_request_t * request;
 
@@ -300,7 +305,8 @@
 
     memcpy(request->uri, buf, len);
 
-    if (_htp_run_uri_hook(conn, request->uri) != EVHTP_RES_OK) {
+    if (htp_run_uri_hook(conn, request->uri) != EVHTP_RES_OK) {
+        conn->err = 1;
         return -1;
     }
 
@@ -308,7 +314,7 @@
 }
 
 static int
-_htp_fragment_cb(http_parser * p, const char * buf, size_t len) {
+htp_fragment_cb(http_parser * p, const char * buf, size_t len) {
     /* evhtp_conn_t * conn = p->data; */
 
     evhtp_log_debug("len = %" PRIoMAX " buf = '%.*s", len, (int)len, buf);
@@ -317,7 +323,7 @@
 }
 
 static int
-_htp_header_key_cb(http_parser * p, const char * buf, size_t len) {
+htp_header_key_cb(http_parser * p, const char * buf, size_t len) {
     evhtp_hdr_t  * hdr;
     evhtp_conn_t * conn;
 
@@ -336,7 +342,7 @@
 }
 
 static int
-_htp_header_val_cb(http_parser * p, const char * buf, size_t len) {
+htp_header_val_cb(http_parser * p, const char * buf, size_t len) {
     evhtp_hdr_t     * hdr  = NULL;
     evhtp_conn_t    * conn = NULL;
     evhtp_request_t * req  = NULL;
@@ -353,7 +359,8 @@
 
     memcpy(hdr->val, buf, len);
 
-    if (_htp_run_hdr_hook(conn, hdr) != EVHTP_RES_OK) {
+    if (htp_run_hdr_hook(conn, hdr) != EVHTP_RES_OK) {
+        conn->err = 1;
         return -1;
     }
 
@@ -361,7 +368,7 @@
 }
 
 static int
-_htp_headers_complete_cb(http_parser * p) {
+htp_headers_complete_cb(http_parser * p) {
     evhtp_conn_t * conn;
 
     evhtp_log_debug("enter");
@@ -370,22 +377,24 @@
     conn->request->method = p->method;
     conn->request->major  = p->http_major;
     conn->request->minor  = p->http_minor;
-    conn->request->proto  = _htp_proto(p->http_major, p->http_minor);
+    conn->request->proto  = htp_proto(p->http_major, p->http_minor);
 
-    if (_htp_run_hdrs_hook(conn, &conn->request->headers_in) != EVHTP_RES_OK) {
+    if (htp_run_hdrs_hook(conn, &conn->request->headers_in) != EVHTP_RES_OK) {
+        conn->err = 1;
         return -1;
     }
 
     if (evhtp_hdr_find(&conn->request->headers_in, _HTP_CONTLEN)) {
         const char * expt_val;
         evbuf_t    * buf;
-        evhtp_status status;
+        evhtp_res    status;
 
         if (!(expt_val = evhtp_hdr_find(&conn->request->headers_in, _HTP_EXPECT))) {
             return 0;
         }
 
-        if ((status = _htp_run_on_expect_hook(conn, expt_val)) != EVHTP_CODE_CONTINUE) {
+        if ((status = htp_run_on_expect_hook(conn, expt_val)) != EVHTP_RES_CONTINUE) {
+            conn->err = 1;
             evhtp_send_reply(conn->request, status, "no", NULL);
             return -1;
         }
@@ -400,29 +409,27 @@
 }
 
 static int
-_htp_path_cb(http_parser * p, const char * buf, size_t len) {
+htp_path_cb(http_parser * p, const char * buf, size_t len) {
     evhtp_conn_t     * conn    = NULL;
     evhtp_request_t  * request = NULL;
     evhtp_callback_t * cb      = NULL;
 
-    /* printf("on_path size: %llu\n", len); */
-
     evhtp_log_debug("enter");
+
     conn               = p->data;
     request            = conn->request;
-
     request->path      = malloc(len + 1);
     request->path[len] = '\0';
 
     memcpy(request->path, buf, len);
 
-    cb = _htp_callbacks_find_callback_woffsets(conn->htp->callbacks,
-        request->path,
-        &request->matched_soff,
-        &request->matched_eoff);
-
+    cb = htp_callbacks_find_callback_woffsets(conn->htp->callbacks,
+                                              request->path,
+                                              &request->matched_soff,
+                                              &request->matched_eoff);
     if (cb == NULL) {
         if (conn->htp->default_cb == NULL) {
+            evhtp_send_reply(request, EVHTP_RES_400, "NOT FOUND", NULL);
             return -1;
         }
 
@@ -433,7 +440,8 @@
         request->cbarg = cb->cbarg;
     }
 
-    if (_htp_run_path_hook(conn, conn->request->path) != EVHTP_RES_OK) {
+    if (htp_run_path_hook(conn, conn->request->path) != EVHTP_RES_OK) {
+        conn->err = 1;
         return -1;
     }
 
@@ -441,13 +449,15 @@
 }
 
 static int
-_htp_body_cb(http_parser * p, const char * buf, size_t len) {
+htp_body_cb(http_parser * p, const char * buf, size_t len) {
     evhtp_conn_t * conn = p->data;
 
     evhtp_log_debug("enter");
-    evbuffer_add(conn->request->buffer_in, buf, len);
 
-    if (_htp_run_read_hook(conn, buf, len) != EVHTP_RES_OK) {
+    evbuffer_add(evhtp_request_get_input(conn->request), buf, len);
+
+    if (htp_run_read_hook(conn, buf, len) != EVHTP_RES_OK) {
+        conn->err = 1;
         return -1;
     }
 
@@ -455,7 +465,7 @@
 }
 
 static inline unsigned int
-_htp_thash(const char * key) {
+htp_thash(const char * key) {
     unsigned int h = 0;
 
     for (; *key; key++) {
@@ -466,7 +476,7 @@
 }
 
 static evhtp_callback_t *
-_htp_callback_new(const void * uri, callback_type_t type, evhtp_callback_cb cb, void * cbarg) {
+htp_callback_new(const void * uri, callback_type_t type, evhtp_callback_cb cb, void * cbarg) {
     evhtp_callback_t * htp_cb;
 
     evhtp_log_debug("enter");
@@ -479,8 +489,8 @@
 
     switch (type) {
         case callback_type_uri:
-            htp_cb->hash      = _htp_thash(uri);
-            htp_cb->val.uri   = strdup((const char *)uri);
+            htp_cb->hash    = htp_thash(uri);
+            htp_cb->val.uri = strdup((const char *)uri);
             break;
         case callback_type_regex:
             htp_cb->val.regex = (regex_t *)malloc(sizeof(regex_t));
@@ -501,7 +511,7 @@
 }
 
 static evhtp_callbacks_t *
-_htp_callbacks_new(unsigned int buckets) {
+htp_callbacks_new(unsigned int buckets) {
     evhtp_callbacks_t * htp_cbs;
 
     evhtp_log_debug("enter");
@@ -522,19 +532,18 @@
 }
 
 static evhtp_callback_t *
-_htp_callbacks_find_callback_woffsets(evhtp_callbacks_t * cbs,
-                                      const char        * uri,
-                                      int               * start_offset,
-                                      int               * end_offset) {
+htp_callbacks_find_callback_woffsets(evhtp_callbacks_t * cbs,
+                                     const char        * uri,
+                                     int               * start_offset,
+                                     int               * end_offset) {
     evhtp_callback_t * cb;
     unsigned int       hash;
 
-    evhtp_log_debug("enter");
     if (cbs == NULL) {
         return NULL;
     }
 
-    hash = _htp_thash(uri);
+    hash = htp_thash(uri);
     cb   = cbs->callbacks[hash & (cbs->buckets - 1)];
 
     while (cb != NULL) {
@@ -566,7 +575,7 @@
 }
 
 static evhtp_callback_t *
-_htp_callbacks_find_callback(evhtp_callbacks_t * cbs, const char * uri) {
+htp_callbacks_find_callback(evhtp_callbacks_t * cbs, const char * uri) {
     evhtp_callback_t * cb;
     unsigned int       hash;
 
@@ -576,7 +585,7 @@
         return NULL;
     }
 
-    hash = _htp_thash(uri);
+    hash = htp_thash(uri);
     cb   = cbs->callbacks[hash & (cbs->buckets - 1)];
 
     while (cb != NULL) {
@@ -603,7 +612,7 @@
 }
 
 static int
-_htp_callbacks_add_callback(evhtp_callbacks_t * cbs, evhtp_callback_t * cb) {
+htp_callbacks_add_callback(evhtp_callbacks_t * cbs, evhtp_callback_t * cb) {
     unsigned int hkey;
 
     evhtp_log_debug("enter");
@@ -630,7 +639,7 @@
 }
 
 void
-_htp_conn_free(evhtp_conn_t * conn) {
+htp_conn_free(evhtp_conn_t * conn) {
     if (conn == NULL) {
         return;
     }
@@ -659,10 +668,10 @@
 
 
     free(conn);
-} /* _htp_conn_free */
+} /* htp_conn_free */
 
 static evhtp_conn_t *
-_htp_conn_new(evhtp_t * htp) {
+htp_conn_new(evhtp_t * htp) {
     evhtp_conn_t * conn;
 
     evhtp_log_debug("enter");
@@ -690,7 +699,7 @@
 }
 
 static void
-_htp_conn_reset(evhtp_conn_t * conn) {
+htp_conn_reset(evhtp_conn_t * conn) {
     http_parser_init(conn->parser, HTTP_REQUEST);
 
     evhtp_log_debug("enter");
@@ -702,11 +711,11 @@
     bufferevent_enable(conn->bev, EV_READ);
 
     bufferevent_setwatermark(conn->bev, EV_READ | EV_WRITE, 0, 0);
-    bufferevent_setcb(conn->bev, _htp_recv_cb, NULL, _htp_err_cb, conn);
+    bufferevent_setcb(conn->bev, htp_recv_cb, NULL, htp_err_cb, conn);
 }
 
 static int
-_htp_conn_get_sock(evhtp_conn_t * conn) {
+htp_conn_get_sock(evhtp_conn_t * conn) {
     if (conn == NULL) {
         return -1;
     }
@@ -716,7 +725,7 @@
 }
 
 static evserv_t *
-_htp_conn_get_listener(evhtp_conn_t * conn) {
+htp_conn_get_listener(evhtp_conn_t * conn) {
     if (conn == NULL) {
         return NULL;
     }
@@ -726,7 +735,7 @@
 }
 
 static evbase_t *
-_htp_conn_get_evbase(evhtp_conn_t * conn) {
+htp_conn_get_evbase(evhtp_conn_t * conn) {
     if (conn == NULL) {
         return NULL;
     }
@@ -736,7 +745,7 @@
 }
 
 static int
-_htp_resp_can_have_content(evhtp_status code) {
+htp_resp_can_have_content(evhtp_res code) {
     evhtp_log_debug("enter");
     if (code >= 100) {
         if (code < 300) {
@@ -748,10 +757,10 @@
 }
 
 static void
-_htp_recv_cb(evbev_t * bev, void * arg) {
+htp_recv_cb(evbev_t * bev, void * arg) {
     evbuf_t      * ibuf;
     evhtp_conn_t * conn;
-    char         * read_buf;
+    void         * read_buf;
     size_t         nread;
     size_t         avail;
 
@@ -759,9 +768,13 @@
     conn     = (evhtp_conn_t *)arg;
     ibuf     = bufferevent_get_input(bev);
     avail    = evbuffer_get_length(ibuf);
-    read_buf = (char *)evbuffer_pullup(ibuf, avail);
+    read_buf = evbuffer_pullup(ibuf, avail);
 
-    nread    = http_parser_execute(conn->parser, &conn->htp->psets, read_buf, avail);
+    nread    = http_parser_execute(conn->parser, &conn->htp->psets, (char *)read_buf, avail);
+
+    if (conn->err != 0) {
+        return htp_conn_free(conn);
+    }
 
     evhtp_log_debug("nread = %zu", nread);
 
@@ -773,7 +786,7 @@
 }
 
 static void
-_htp_err_cb(evbev_t * bev, short events, void * arg) {
+htp_err_cb(evbev_t * bev, short events, void * arg) {
     evhtp_conn_t * conn;
 
     evhtp_log_debug("events = %x", events);
@@ -781,12 +794,15 @@
     if (events & (BEV_EVENT_ERROR | BEV_EVENT_EOF)) {
         conn = (evhtp_conn_t *)arg;
 
-        return _htp_conn_free(conn);
+        evhtp_log_debug("leaving....");
+        return htp_conn_free(conn);
     }
+
+    evhtp_log_debug("leaving....");
 }
 
 static int
-_htp_hdr_output(evhtp_hdr_t * hdr, void * arg) {
+htp_hdr_output(evhtp_hdr_t * hdr, void * arg) {
     evbuf_t * buf = (evbuf_t *)arg;
 
 
@@ -799,7 +815,7 @@
 }
 
 static void
-_htp_exec_in_thr(evthr_t * thr, void * arg, void * shared) {
+htp_exec_in_thr(evthr_t * thr, void * arg, void * shared) {
     evhtp_t      * htp;
     evhtp_conn_t * conn;
 
@@ -816,14 +832,14 @@
 #ifndef DISABLE_SSL
         conn->ssl = SSL_new(htp->ssl_ctx);
         conn->bev = bufferevent_openssl_socket_new(conn->evbase,
-            conn->sock, conn->ssl, BUFFEREVENT_SSL_ACCEPTING,
-            BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
+                                                   conn->sock, conn->ssl, BUFFEREVENT_SSL_ACCEPTING,
+                                                   BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
 
         SSL_set_app_data(conn->ssl, conn);
 #endif
     }
 
-    bufferevent_setcb(conn->bev, _htp_recv_cb, NULL, _htp_err_cb, conn);
+    bufferevent_setcb(conn->bev, htp_recv_cb, NULL, htp_err_cb, conn);
     bufferevent_enable(conn->bev, EV_READ);
     bufferevent_disable(conn->bev, EV_WRITE);
 
@@ -835,14 +851,14 @@
 }
 
 static void
-_htp_accept_cb(evserv_t * serv, int fd, struct sockaddr * s, int sl, void * arg) {
+htp_accept_cb(evserv_t * serv, int fd, struct sockaddr * s, int sl, void * arg) {
     evhtp_t      * htp;
     evhtp_conn_t * conn;
 
     evhtp_log_debug("enter");
-    htp          = (evhtp_t *)arg;
 
-    conn         = _htp_conn_new(htp);
+    htp          = (evhtp_t *)arg;
+    conn         = htp_conn_new(htp);
     conn->evbase = htp->evbase;
     conn->sock   = fd;
 
@@ -851,7 +867,7 @@
     }
 
     if (htp->pool != NULL) {
-        evthr_pool_defer(htp->pool, _htp_exec_in_thr, conn);
+        evthr_pool_defer(htp->pool, htp_exec_in_thr, conn);
         return;
     }
 
@@ -861,8 +877,8 @@
 #ifndef DISABLE_SSL
         conn->ssl = SSL_new(htp->ssl_ctx);
         conn->bev = bufferevent_openssl_socket_new(conn->evbase,
-            conn->sock, conn->ssl, BUFFEREVENT_SSL_ACCEPTING,
-            BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
+                                                   conn->sock, conn->ssl, BUFFEREVENT_SSL_ACCEPTING,
+                                                   BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
 
         SSL_set_app_data(conn->ssl, conn);
 #else
@@ -872,20 +888,21 @@
 
     bufferevent_disable(conn->bev, EV_WRITE);
     bufferevent_enable(conn->bev, EV_READ);
-    bufferevent_setcb(conn->bev, _htp_recv_cb, NULL, _htp_err_cb, conn);
+    bufferevent_setcb(conn->bev, htp_recv_cb, NULL, htp_err_cb, conn);
 
     if (htp->post_accept_cb) {
         htp->post_accept_cb(conn, htp->post_accept_cbarg);
     }
-} /* _htp_accept_cb */
+} /* htp_accept_cb */
 
 static void
-_htp_set_kalive_hdr(evhtp_hdrs_t * hdrs, evhtp_proto proto, int kalive) {
+htp_set_kalive_hdr(evhtp_hdrs_t * hdrs, evhtp_proto proto, int kalive) {
+    evhtp_log_debug("enter");
+
     if (hdrs == NULL) {
         return;
     }
 
-    evhtp_log_debug("enter");
     if (kalive && proto == EVHTP_PROTO_1_0) {
         return evhtp_hdr_add(hdrs, evhtp_hdr_new(_HTP_CONN, _HTP_DEFKALIVE));
     }
@@ -896,7 +913,7 @@
 }
 
 static void
-_htp_reply_set_content_hdrs(evhtp_request_t * req, size_t len) {
+htp_reply_set_content_hdrs(evhtp_request_t * req, size_t len) {
     const char * content_len_hval;
     const char * content_type_hval;
 
@@ -931,60 +948,62 @@
     if (content_type_hval == NULL) {
         evhtp_hdr_add(&req->headers_out, evhtp_hdr_new(_HTP_CONTYPE, _HTP_DEFCONTYPE));
     }
-} /* _htp_reply_set_content_hdrs */
+} /* htp_reply_set_content_hdrs */
 
-static evhtp_status
-_htp_code_parent(evhtp_status code) {
+static evhtp_res
+htp_code_parent(evhtp_res code) {
     evhtp_log_debug("enter");
     if (code > 599 || code < 100) {
-        return EVHTP_CODE_SCREWEDUP;
+        return EVHTP_RES_SCREWEDUP;
     }
 
     if (code >= 100 && code < 200) {
-        return EVHTP_CODE_100;
+        return EVHTP_RES_100;
     }
 
     if (code >= 200 && code < 300) {
-        return EVHTP_CODE_200;
+        return EVHTP_RES_200;
     }
 
     if (code >= 300 && code < 400) {
-        return EVHTP_CODE_300;
+        return EVHTP_RES_300;
     }
 
     if (code >= 400 && code < 500) {
-        return EVHTP_CODE_400;
+        return EVHTP_RES_400;
     }
 
-    return EVHTP_CODE_500;
+    return EVHTP_RES_500;
 }
 
 static int
-_htp_should_close_based_on_cflags(evhtp_cflags flags, evhtp_status code) {
+htp_should_close_based_on_cflags(evhtp_cflags flags, evhtp_res code) {
     int res = 0;
 
     evhtp_log_debug("enter");
-    switch (_htp_code_parent(code)) {
-        case EVHTP_CODE_100:
+
+    switch (htp_code_parent(code)) {
+        case EVHTP_RES_100:
             res = (flags & EVHTP_CLOSE_ON_100);
             break;
-        case EVHTP_CODE_200:
+        case EVHTP_RES_200:
             res = (flags & EVHTP_CLOSE_ON_200);
             break;
-        case EVHTP_CODE_300:
+        case EVHTP_RES_300:
             res = (flags & EVHTP_CLOSE_ON_300);
             break;
-        case EVHTP_CODE_400:
-            if (code == EVHTP_CODE_EXPECTFAIL && flags & EVHTP_CLOSE_ON_EXPECT_ERR) {
+        case EVHTP_RES_400:
+            if (code == EVHTP_RES_EXPECTFAIL && flags & EVHTP_CLOSE_ON_EXPECT_ERR) {
                 res = 1;
             } else {
                 res = (flags & EVHTP_CLOSE_ON_400);
             }
             break;
-        case EVHTP_CODE_500:
+        case EVHTP_RES_500:
             res = (flags & EVHTP_CLOSE_ON_500);
             break;
-        case EVHTP_CODE_SCREWEDUP:
+        case EVHTP_RES_SCREWEDUP:
+        default:
             res = 1;
             break;
     } /* switch */
@@ -993,7 +1012,7 @@
 }
 
 static int
-_htp_should_keep_alive(evhtp_request_t * req, evhtp_status code) {
+htp_should_keep_alive(evhtp_request_t * req, evhtp_res code) {
     evhtp_conn_t * conn = req->conn;
 
     evhtp_log_debug("enter");
@@ -1002,7 +1021,7 @@
         return 0;
     }
 
-    if (_htp_should_close_based_on_cflags(conn->flags, code)) {
+    if (htp_should_close_based_on_cflags(conn->flags, code)) {
         /* one of the user-set flags has informed us to close, thus
          * do not keep alive */
         return 0;
@@ -1014,7 +1033,7 @@
 }
 
 static inline int
-_htp_is_http_1_1x(char major, char minor) {
+htp_is_http_1_1x(char major, char minor) {
     evhtp_log_debug("enter");
     if (major >= 1 && minor >= 1) {
         return 1;
@@ -1024,7 +1043,7 @@
 }
 
 static inline int
-_htp_is_http_1_0x(char major, char minor) {
+htp_is_http_1_0x(char major, char minor) {
     if (major >= 1 && minor <= 0) {
         return 1;
     }
@@ -1033,36 +1052,36 @@
 }
 
 static evhtp_proto
-_htp_proto(char major, char minor) {
-    if (_htp_is_http_1_0x(major, minor)) {
+htp_proto(char major, char minor) {
+    if (htp_is_http_1_0x(major, minor)) {
         return EVHTP_PROTO_1_0;
     }
 
-    if (_htp_is_http_1_1x(major, minor)) {
+    if (htp_is_http_1_1x(major, minor)) {
         return EVHTP_PROTO_1_1;
     }
 
     return EVHTP_PROTO_INVALID;
 }
 
-#define _htp_set_status_buf(buf, major, minor, code) do {                       \
+#define htp_set_status_buf(buf, major, minor, code) do {                        \
         evbuffer_add_printf(buf, "HTTP/%d.%d %d DERP\r\n", major, minor, code); \
 } while (0)
 
-#define _htp_set_header_buf(buf, hdrs)               do { \
-        evhtp_hdrs_for_each(hdrs, _htp_hdr_output, buf);  \
+#define htp_set_header_buf(buf, hdrs)               do { \
+        evhtp_hdrs_for_each(hdrs, htp_hdr_output, buf);  \
 } while (0)
 
-#define _htp_set_server_hdr(hdrs, name)              do {      \
+#define htp_set_server_hdr(hdrs, name)              do {       \
         evhtp_hdr_add(hdrs, evhtp_hdr_new(_HTP_SERVER, name)); \
 } while (0)
 
-#define _htp_set_crlf_buf(buf)                       do { \
+#define htp_set_crlf_buf(buf)                       do {  \
         evbuffer_add_reference(buf, CRLF, 2, NULL, NULL); \
 } while (0)
 
 void
-_htp_set_body_buf(evbuf_t * dst, evbuf_t * src) {
+htp_set_body_buf(evbuf_t * dst, evbuf_t * src) {
     if (dst == NULL) {
         return;
     }
@@ -1074,7 +1093,7 @@
 }
 
 static void
-_htp_resp_fini_cb(evbev_t * bev, void * arg) {
+htp_resp_fini_cb(evbev_t * bev, void * arg) {
     evhtp_request_t * req;
     evhtp_conn_t    * conn;
     int               keepalive;
@@ -1086,14 +1105,14 @@
     conn      = req->conn;
 
     if (keepalive) {
-        return _htp_conn_reset(conn);
+        return htp_conn_reset(conn);
     } else {
-        return _htp_conn_free(conn);
+        return htp_conn_free(conn);
     }
 }
 
 static void
-_htp_resp_err_cb(evbev_t * bev, short events, void * arg) {
+htp_resp_err_cb(evbev_t * bev, short events, void * arg) {
     evhtp_request_t * req;
     evhtp_conn_t    * conn;
 
@@ -1102,27 +1121,30 @@
     req  = (evhtp_request_t *)arg;
     conn = req->conn;
 
-    return _htp_conn_free(conn);
+    return htp_conn_free(conn);
 }
 
 static void
-_htp_stream_fini_cb(evbev_t * bev, void * arg) {
+htp_stream_fini_cb(evbev_t * bev, void * arg) {
     evhtp_request_t * req;
     evhtp_conn_t    * conn;
+    evbuf_t         * buf;
 
     evhtp_log_debug("enter");
+
     req  = (evhtp_request_t *)arg;
     conn = req->conn;
+    buf  = evhtp_request_get_output(req);
 
     switch (req->stream_cb(req, req->stream_cbarg)) {
         case EVHTP_RES_OK:
-            bufferevent_write_buffer(conn->bev, req->buffer_out);
+            bufferevent_write_buffer(conn->bev, buf);
             return;
         case EVHTP_RES_DONE:
             if (req->chunked) {
-                evbuffer_add_reference(req->buffer_out, "0\r\n\r\n", 5, NULL, NULL);
-                bufferevent_setcb(conn->bev, NULL, _htp_resp_fini_cb, _htp_resp_err_cb, req);
-                bufferevent_write_buffer(conn->bev, req->buffer_out);
+                evbuffer_add_reference(buf, "0\r\n\r\n", 5, NULL, NULL);
+                bufferevent_setcb(conn->bev, NULL, htp_resp_fini_cb, htp_resp_err_cb, req);
+                bufferevent_write_buffer(conn->bev, buf);
                 return;
             }
             break;
@@ -1131,58 +1153,60 @@
             break;
     }
 
-    return _htp_resp_fini_cb(conn->bev, arg);
+    return htp_resp_fini_cb(conn->bev, arg);
 }
 
 void
-evhtp_send_reply(evhtp_request_t * req, evhtp_status code, const char * r, evbuf_t * b) {
+evhtp_send_reply(evhtp_request_t * req, evhtp_res code, const char * r, evbuf_t * b) {
     evhtp_conn_t * conn;
+    evbuf_t      * obuf;
 
     evhtp_log_debug("enter");
+
     conn           = req->conn;
-    req->keepalive = _htp_should_keep_alive(req, code);
+    obuf           = evhtp_request_get_output(req);
+    req->keepalive = htp_should_keep_alive(req, code);
 
-    if (req->buffer_out == NULL) {
-        req->buffer_out = evbuffer_new();
-    }
+    assert(obuf != NULL);
 
-    if (_htp_resp_can_have_content(code)) {
-        _htp_reply_set_content_hdrs(req, b ? evbuffer_get_length(b) : 0);
+    if (htp_resp_can_have_content(code)) {
+        htp_reply_set_content_hdrs(req, b ? evbuffer_get_length(b) : 0);
     } else {
         if ((b != NULL) && evbuffer_get_length(b) > 0) {
             evbuffer_drain(b, -1);
         }
     }
 
-    _htp_set_kalive_hdr(&req->headers_out, req->proto, req->keepalive);
-    _htp_set_server_hdr(&req->headers_out, evhtp_get_server_name(conn->htp));
+    htp_set_kalive_hdr(&req->headers_out, req->proto, req->keepalive);
+    htp_set_server_hdr(&req->headers_out, evhtp_get_server_name(conn->htp));
 
-    _htp_set_status_buf(req->buffer_out, req->major, req->minor, code);
-    _htp_set_header_buf(req->buffer_out, &req->headers_out);
-    _htp_set_crlf_buf(req->buffer_out);
-    _htp_set_body_buf(req->buffer_out, b);
+    htp_set_status_buf(obuf, req->major, req->minor, code);
+    htp_set_header_buf(obuf, &req->headers_out);
+    htp_set_crlf_buf(obuf);
+    htp_set_body_buf(obuf, b);
 
 
     bufferevent_disable(conn->bev, EV_READ);
     bufferevent_enable(conn->bev, EV_WRITE);
     bufferevent_setwatermark(conn->bev, EV_WRITE, 1, 0);
-    bufferevent_setcb(conn->bev, NULL, _htp_resp_fini_cb, _htp_resp_err_cb, req);
-    bufferevent_write_buffer(conn->bev, req->buffer_out);
+    bufferevent_setcb(conn->bev, NULL, htp_resp_fini_cb, htp_resp_err_cb, req);
+    bufferevent_write_buffer(conn->bev, obuf);
 } /* evhtp_send_reply */
 
 void
-evhtp_send_reply_stream(evhtp_request_t * req, evhtp_status code, evhtp_stream_cb cb, void * arg) {
+evhtp_send_reply_stream(evhtp_request_t * req, evhtp_res code, evhtp_stream_cb cb, void * arg) {
     evhtp_conn_t * conn;
+    evbuf_t      * obuf;
 
     evhtp_log_debug("enter");
-    conn = req->conn;
 
-    if (req->buffer_out == NULL) {
-        req->buffer_out = evbuffer_new();
-    }
+    conn = req->conn;
+    obuf = evhtp_request_get_output(req);
+
+    assert(obuf != NULL);
 
     if (req->proto == EVHTP_PROTO_1_1) {
-        req->keepalive = _htp_should_keep_alive(req, code);
+        req->keepalive = htp_should_keep_alive(req, code);
 
         if (!evhtp_hdr_find(&req->headers_out, _HTP_TRANSENC)) {
             evhtp_hdr_add(&req->headers_out, evhtp_hdr_new(_HTP_TRANSENC, _HTP_DEFCHUNKED));
@@ -1197,12 +1221,12 @@
         evhtp_hdr_add(&req->headers_out, evhtp_hdr_new(_HTP_CONTYPE, _HTP_DEFCONTYPE));
     }
 
-    _htp_set_kalive_hdr(&req->headers_out, req->proto, req->keepalive);
-    _htp_set_server_hdr(&req->headers_out, evhtp_get_server_name(conn->htp));
+    htp_set_kalive_hdr(&req->headers_out, req->proto, req->keepalive);
+    htp_set_server_hdr(&req->headers_out, evhtp_get_server_name(conn->htp));
 
-    _htp_set_status_buf(req->buffer_out, req->major, req->minor, code);
-    _htp_set_header_buf(req->buffer_out, &req->headers_out);
-    _htp_set_crlf_buf(req->buffer_out);
+    htp_set_status_buf(obuf, req->major, req->minor, code);
+    htp_set_header_buf(obuf, &req->headers_out);
+    htp_set_crlf_buf(obuf);
 
     req->stream_cb    = cb;
     req->stream_cbarg = arg;
@@ -1211,16 +1235,19 @@
     bufferevent_disable(conn->bev, EV_READ);
     bufferevent_enable(conn->bev, EV_WRITE);
     bufferevent_setwatermark(conn->bev, EV_WRITE, 1, 0);
-    bufferevent_setcb(conn->bev, NULL, _htp_stream_fini_cb, _htp_resp_err_cb, req);
-    bufferevent_write_buffer(conn->bev, req->buffer_out);
+    bufferevent_setcb(conn->bev, NULL, htp_stream_fini_cb, htp_resp_err_cb, req);
+    bufferevent_write_buffer(conn->bev, obuf);
 } /* evhtp_send_reply_stream */
 
 void
 evhtp_request_make_chunk(evhtp_request_t * req, evbuf_t * buf) {
+    evbuf_t * obuf = evhtp_request_get_output(req);
+
     evhtp_log_debug("enter");
-    evbuffer_add_printf(req->buffer_out, "%" PRIxMAX "\r\n", evbuffer_get_length(buf));
-    evbuffer_add_buffer(req->buffer_out, buf);
-    evbuffer_add_reference(req->buffer_out, CRLF, 2, NULL, NULL);
+
+    evbuffer_add_printf(obuf, "%" PRIxMAX "\r\n", evbuffer_get_length(buf));
+    evbuffer_add_buffer(obuf, buf);
+    evbuffer_add_reference(obuf, CRLF, 2, NULL, NULL);
 }
 
 void
@@ -1231,11 +1258,11 @@
         case EVHTP_PROTO_1_1:
             return evhtp_request_make_chunk(req, buf);
         case EVHTP_PROTO_1_0:
-            evbuffer_add_buffer(req->buffer_out, buf);
+            evbuffer_add_buffer(evhtp_request_get_output(req), buf);
             req->keepalive = 0;
             break;
         default:
-            return _htp_conn_free(req->conn);
+            return htp_conn_free(req->conn);
     }
 }
 
@@ -1255,22 +1282,22 @@
 
     switch (type) {
         case EVHTP_HOOK_HDRS_READ:
-            _htp_conn_hook_set(conn, _hdrs, cb, cbarg);
+            htp_conn_hook_set(conn, _hdrs, cb, cbarg);
             break;
         case EVHTP_HOOK_HDR_READ:
-            _htp_conn_hook_set(conn, _hdr, cb, cbarg);
+            htp_conn_hook_set(conn, _hdr, cb, cbarg);
             break;
         case EVHTP_HOOK_PATH_READ:
-            _htp_conn_hook_set(conn, _read, cb, cbarg);
+            htp_conn_hook_set(conn, _read, cb, cbarg);
             break;
         case EVHTP_HOOK_URI_READ:
-            _htp_conn_hook_set(conn, _uri, cb, cbarg);
+            htp_conn_hook_set(conn, _uri, cb, cbarg);
             break;
         case EVHTP_HOOK_READ:
-            _htp_conn_hook_set(conn, _read, cb, cbarg);
+            htp_conn_hook_set(conn, _read, cb, cbarg);
             break;
         case EVHTP_HOOK_ON_EXPECT:
-            _htp_conn_hook_set(conn, _on_expect, cb, cbarg);
+            htp_conn_hook_set(conn, _on_expect, cb, cbarg);
             break;
         case EVHTP_HOOK_COMPLETE:
             break;
@@ -1288,18 +1315,18 @@
     evhtp_log_debug("enter");
 
     if (htp->callbacks == NULL) {
-        htp->callbacks = _htp_callbacks_new(1024);
+        htp->callbacks = htp_callbacks_new(1024);
     } else {
-        if (_htp_callbacks_find_callback(htp->callbacks, uri)) {
+        if (htp_callbacks_find_callback(htp->callbacks, uri)) {
             return -1;
         }
     }
 
-    if (!(htp_cb = _htp_callback_new(uri, callback_type_uri, cb, cbarg))) {
+    if (!(htp_cb = htp_callback_new(uri, callback_type_uri, cb, cbarg))) {
         return -1;
     }
 
-    if (!_htp_callbacks_add_callback(htp->callbacks, htp_cb)) {
+    if (!htp_callbacks_add_callback(htp->callbacks, htp_cb)) {
         return -1;
     }
 
@@ -1313,14 +1340,14 @@
     evhtp_log_debug("enter");
 
     if (htp->callbacks == NULL) {
-        htp->callbacks = _htp_callbacks_new(1024);
+        htp->callbacks = htp_callbacks_new(1024);
     }
 
-    if (!(htp_cb = _htp_callback_new(pat, callback_type_regex, cb, arg))) {
+    if (!(htp_cb = htp_callback_new(pat, callback_type_regex, cb, arg))) {
         return -1;
     }
 
-    if (!_htp_callbacks_add_callback(htp->callbacks, htp_cb)) {
+    if (!htp_callbacks_add_callback(htp->callbacks, htp_cb)) {
         return -1;
     }
 
@@ -1345,9 +1372,10 @@
 
     signal(SIGPIPE, SIG_IGN);
 
-    htp->listener       = evconnlistener_new_bind(htp->evbase,
-        _htp_accept_cb, htp, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, 1024,
-        (struct sockaddr *)&sin, sizeof(sin));
+    htp->listener = evconnlistener_new_bind(htp->evbase,
+                                            htp_accept_cb, htp,
+                                            LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, 1024,
+                                            (struct sockaddr *)&sin, sizeof(sin));
 }
 
 void
@@ -1489,6 +1517,51 @@
     return 0;
 }
 
+const char *
+evhtp_request_get_path(evhtp_request_t * request) {
+    return (const char *)request->path;
+}
+
+const char *
+evhtp_request_get_uri(evhtp_request_t * request) {
+    return (const char *)request->uri;
+}
+
+int
+evhtp_request_get_matched_soff(evhtp_request_t * request) {
+    return request->matched_soff;
+}
+
+int
+evhtp_request_get_matched_eoff(evhtp_request_t * request) {
+    return request->matched_eoff;
+}
+
+evhtp_method
+evhtp_request_get_method(evhtp_request_t * request) {
+    return request->method;
+}
+
+evhtp_proto
+evhtp_request_get_proto(evhtp_request_t * request) {
+    return request->proto;
+}
+
+evhtp_conn_t *
+evhtp_request_get_conn(evhtp_request_t * request) {
+    return request->conn;
+}
+
+evhtp_hdrs_t *
+evhtp_request_get_headers_in(evhtp_request_t * request) {
+    return &request->headers_in;
+}
+
+evhtp_hdrs_t *
+evhtp_request_get_headers_out(evhtp_request_t * request) {
+    return &request->headers_out;
+}
+
 evbuf_t *
 evhtp_request_get_input(evhtp_request_t * request) {
     return request->buffer_in;
@@ -1499,6 +1572,31 @@
     return request->buffer_out;
 }
 
+evhtp_callback_cb
+evhtp_request_get_cb(evhtp_request_t * request) {
+    return request->cb;
+}
+
+void *
+evhtp_request_get_cbarg(evhtp_request_t * request) {
+    return request->cbarg;
+}
+
+const char *
+evhtp_request_method_str(evhtp_request_t * request) {
+    return evhtp_method_str(request->method);
+}
+
+int64_t
+evhtp_request_content_length(evhtp_request_t * request) {
+    return request->conn->parser->content_length;
+}
+
+const char *
+evhtp_method_str(evhtp_method method) {
+    return http_method_str(method);
+}
+
 evbase_t *
 evhtp_request_get_evbase(evhtp_request_t * request) {
     evhtp_log_debug("enter");
@@ -1507,7 +1605,7 @@
         return NULL;
     }
 
-    return _htp_conn_get_evbase(request->conn);
+    return htp_conn_get_evbase(request->conn);
 }
 
 int
@@ -1517,7 +1615,7 @@
         return -1;
     }
 
-    return _htp_conn_get_sock(request->conn);
+    return htp_conn_get_sock(request->conn);
 }
 
 evserv_t *
@@ -1528,7 +1626,7 @@
         return NULL;
     }
 
-    return _htp_conn_get_listener(request->conn);
+    return htp_conn_get_listener(request->conn);
 }
 
 evhtp_hdr_t *
@@ -1547,7 +1645,7 @@
 }
 
 static evhtp_request_t *
-_htp_request_new(evhtp_conn_t * conn) {
+htp_request_new(evhtp_conn_t * conn) {
     evhtp_request_t * request;
 
     evhtp_log_debug("enter");
@@ -1616,7 +1714,7 @@
 }
 
 static void
-_htp_ssl_scache_builtin_expire(int fd, short what, void * arg) {
+htp_ssl_scache_builtin_expire(int fd, short what, void * arg) {
     htp_scache_ent_t * ent;
     htp_scache_t     * scache;
 
@@ -1672,8 +1770,8 @@
     tv.tv_sec  = scfg->scache_timeout;
     tv.tv_usec = 0;
 
-    cache_ent->timeout_ev = evtimer_new(_htp_conn_get_evbase(conn),
-        _htp_ssl_scache_builtin_expire, (void *)cache_ent);
+    cache_ent->timeout_ev = evtimer_new(htp_conn_get_evbase(conn),
+                                        htp_ssl_scache_builtin_expire, (void *)cache_ent);
 
     evtimer_add(cache_ent->timeout_ev, &tv);
 
@@ -1713,7 +1811,7 @@
 }
 
 static int
-_htp_ssl_add_scache_ent(evhtp_ssl_t * ssl, evhtp_ssl_sess_t * sess) {
+htp_ssl_add_scache_ent(evhtp_ssl_t * ssl, evhtp_ssl_sess_t * sess) {
     evhtp_conn_t  * conn;
     evhtp_ssl_cfg * scfg;
     int             slen;
@@ -1739,7 +1837,7 @@
 }
 
 static evhtp_ssl_sess_t *
-_htp_ssl_get_scache_ent(evhtp_ssl_t * ssl, unsigned char * sid, int sid_len, int * copy) {
+htp_ssl_get_scache_ent(evhtp_ssl_t * ssl, unsigned char * sid, int sid_len, int * copy) {
     evhtp_conn_t     * conn;
     evhtp_t          * htp;
     evhtp_ssl_cfg    * scfg;
@@ -1760,7 +1858,7 @@
 }
 
 static void
-_htp_ssl_del_scache_ent(evhtp_ssl_ctx_t * ctx, evhtp_ssl_sess_t * sess) {
+htp_ssl_del_scache_ent(evhtp_ssl_ctx_t * ctx, evhtp_ssl_sess_t * sess) {
     evhtp_t       * htp;
     evhtp_ssl_cfg * scfg;
     unsigned char * sid;
@@ -1813,11 +1911,11 @@
     SSL_CTX_use_PrivateKey_file(htp->ssl_ctx, cfg->privfile ? : cfg->pemfile, SSL_FILETYPE_PEM);
     SSL_CTX_set_session_cache_mode(htp->ssl_ctx, cache_mode);
     SSL_CTX_set_session_id_context(htp->ssl_ctx, (void*)&s_server_session_id_context,
-        sizeof s_server_session_id_context);
+                                   sizeof s_server_session_id_context);
 
-    SSL_CTX_sess_set_new_cb(htp->ssl_ctx, _htp_ssl_add_scache_ent);
-    SSL_CTX_sess_set_get_cb(htp->ssl_ctx, _htp_ssl_get_scache_ent);
-    SSL_CTX_sess_set_remove_cb(htp->ssl_ctx, _htp_ssl_del_scache_ent);
+    SSL_CTX_sess_set_new_cb(htp->ssl_ctx, htp_ssl_add_scache_ent);
+    SSL_CTX_sess_set_get_cb(htp->ssl_ctx, htp_ssl_get_scache_ent);
+    SSL_CTX_sess_set_remove_cb(htp->ssl_ctx, htp_ssl_del_scache_ent);
     SSL_CTX_set_app_data(htp->ssl_ctx, htp);
 
     if (cfg->scache_init) {
@@ -1830,12 +1928,12 @@
 #endif
 
 static unsigned long
-_htp_ssl_get_thr_id(void) {
+htp_ssl_get_thr_id(void) {
     return (unsigned long)pthread_self();
 }
 
 static void
-_htp_ssl_thr_lock(int mode, int type, const char * file, int line) {
+htp_ssl_thr_lock(int mode, int type, const char * file, int line) {
     if (type < ssl_num_locks) {
         if (mode & CRYPTO_LOCK) {
             pthread_mutex_lock(ssl_locks[type]);
@@ -1860,8 +1958,8 @@
             pthread_mutex_init(ssl_locks[i], NULL);
         }
 
-        CRYPTO_set_id_callback(_htp_ssl_get_thr_id);
-        CRYPTO_set_locking_callback(_htp_ssl_thr_lock);
+        CRYPTO_set_id_callback(htp_ssl_get_thr_id);
+        CRYPTO_set_locking_callback(htp_ssl_thr_lock);
     }
 
     if (!(htp->pool = evthr_pool_new(nthreads, htp))) {
@@ -1883,18 +1981,18 @@
     }
 
     htp->server_name               = _HTP_DEFSERVER;
-    htp->psets.on_message_begin    = _htp_start_cb;
-    htp->psets.on_path             = _htp_path_cb;
-    htp->psets.on_query_string     = _htp_query_str_cb;
-    htp->psets.on_url              = _htp_uri_cb;
-    htp->psets.on_fragment         = _htp_fragment_cb;
-    htp->psets.on_header_field     = _htp_header_key_cb;
-    htp->psets.on_header_value     = _htp_header_val_cb;
-    htp->psets.on_headers_complete = _htp_headers_complete_cb;
-    htp->psets.on_body             = _htp_body_cb;
-    htp->psets.on_message_complete = _htp_end_cb;
+    htp->psets.on_message_begin    = htp_start_cb;
+    htp->psets.on_path             = htp_path_cb;
+    htp->psets.on_query_string     = htp_query_str_cb;
+    htp->psets.on_url              = htp_uri_cb;
+    htp->psets.on_fragment         = htp_fragment_cb;
+    htp->psets.on_header_field     = htp_header_key_cb;
+    htp->psets.on_header_value     = htp_header_val_cb;
+    htp->psets.on_headers_complete = htp_headers_complete_cb;
+    htp->psets.on_body             = htp_body_cb;
+    htp->psets.on_message_complete = htp_end_cb;
 
-    htp->evbase = evbase;
+    htp->evbase = evbase ? : event_base_new();
 
     evhtp_log_debug("created new instance");
 
diff --git a/evhtp.h b/evhtp.h
index 05ac75b..9e625ab 100644
--- a/evhtp.h
+++ b/evhtp.h
@@ -17,7 +17,7 @@
 #include <openssl/rand.h>
 #endif
 
-#define EVHTP_VERSION "0.3.4"
+#define EVHTP_VERSION "0.3.5"
 
 struct evhtp;
 struct evhtp_hdrs;
@@ -26,7 +26,6 @@
 struct evhtp_conn;
 struct evhtp_request;
 
-typedef unsigned              evhtp_status;
 typedef unsigned char         evhtp_cflags;
 typedef struct evbuffer       evbuf_t;
 typedef struct event          event_t;
@@ -48,7 +47,7 @@
 typedef struct evhtp_hdr      evhtp_hdr_t;
 typedef struct evhtp_hdrs     evhtp_hdrs_t;
 
-typedef enum evhtp_res        evhtp_res;
+typedef uint16_t              evhtp_res;
 typedef enum evhtp_hook_type  evhtp_hook_type;
 typedef enum http_method      evhtp_method;
 typedef enum evhtp_proto      evhtp_proto;
@@ -63,16 +62,9 @@
 typedef evhtp_res (*evhtp_hook_path)(evhtp_request_t *, const char *, void *);
 typedef evhtp_res (*evhtp_hook_uri)(evhtp_request_t *, const char *, void *);
 typedef evhtp_res (*evhtp_hook_read)(evhtp_request_t *, const char *, size_t, void *);
-typedef evhtp_status (*evhtp_hook_on_expect)(evhtp_request_t *, const char *, void *);
+typedef evhtp_res (*evhtp_hook_on_expect)(evhtp_request_t *, const char *, void *);
 typedef evhtp_res (*evhtp_stream_cb)(evhtp_request_t *, void *);
 
-enum evhtp_res {
-    EVHTP_RES_OK = 0,
-    EVHTP_RES_ERROR,
-    EVHTP_RES_MORE,
-    EVHTP_RES_DONE
-};
-
 #define EVHTP_CLOSE_ON_EXPECT_ERR (1 << 1)
 #define EVHTP_CLOSE_ON_100        (1 << 2)
 #define EVHTP_CLOSE_ON_200        (1 << 3)
@@ -80,63 +72,64 @@
 #define EVHTP_CLOSE_ON_400        (1 << 5)
 #define EVHTP_CLOSE_ON_500        (1 << 6)
 
-#define EVHTP_CODE_SCREWEDUP      1
+#define EVHTP_RES_SCREWEDUP       1
+#define EVHTP_RES_DONE            2
 
-#define EVHTP_CODE_100            100
-#define EVHTP_CODE_CONTINUE       100
-#define EVHTP_CODE_SWITCH_PROTO   101
-#define EVHTP_CODE_PROCESSING     102
-#define EVHTP_CODE_URI_TOOLONG    122
+#define EVHTP_RES_100             100
+#define EVHTP_RES_CONTINUE        100
+#define EVHTP_RES_SWITCH_PROTO    101
+#define EVHTP_RES_PROCESSING      102
+#define EVHTP_RES_URI_TOOLONG     122
 
-#define EVHTP_CODE_200            200
-#define EVHTP_CODE_OK             200
-#define EVHTP_CODE_CREATED        201
-#define EVHTP_CODE_ACCEPTED       202
-#define EVHTP_CODE_NAUTHINFO      203
-#define EVHTP_CODE_NOCONTENT      204
-#define EVHTP_CODE_RSTCONTENT     205
-#define EVHTP_CODE_PARTIAL        206
-#define EVHTP_CODE_MSTATUS        207
-#define EVHTP_CODE_IMUSED         226
+#define EVHTP_RES_200             200
+#define EVHTP_RES_OK              200
+#define EVHTP_RES_CREATED         201
+#define EVHTP_RES_ACCEPTED        202
+#define EVHTP_RES_NAUTHINFO       203
+#define EVHTP_RES_NOCONTENT       204
+#define EVHTP_RES_RSTCONTENT      205
+#define EVHTP_RES_PARTIAL         206
+#define EVHTP_RES_MSTATUS         207
+#define EVHTP_RES_IMUSED          226
 
-#define EVHTP_CODE_300            300
-#define EVHTP_CODE_MCHOICE        300
-#define EVHTP_CODE_MOVEDPERM      301
-#define EVHTP_CODE_FOUND          302
-#define EVHTP_CODE_SEEOTHER       303
-#define EVHTP_CODE_NOTMOD         304
-#define EVHTP_CODE_USEPROXY       305
-#define EVHTP_CODE_SWITCHPROXY    306
-#define EVHTP_CODE_TMPREDIR       307
+#define EVHTP_RES_300             300
+#define EVHTP_RES_MCHOICE         300
+#define EVHTP_RES_MOVEDPERM       301
+#define EVHTP_RES_FOUND           302
+#define EVHTP_RES_SEEOTHER        303
+#define EVHTP_RES_NOTMOD          304
+#define EVHTP_RES_USEPROXY        305
+#define EVHTP_RES_SWITCHPROXY     306
+#define EVHTP_RES_TMPREDIR        307
 
-#define EVHTP_CODE_400            400
-#define EVHTP_CODE_BADREQ         400
-#define EVHTP_CODE_UNAUTH         401
-#define EVHTP_CODE_PAYREQ         402
-#define EVHTP_CODE_FORBIDDEN      403
-#define EVHTP_CODE_NOTFOUND       404
-#define EVHTP_CODE_METHNALLOWED   405
-#define EVHTP_CODE_NACCEPTABLE    406
-#define EVHTP_CODE_PROXYAUTHREQ   407
-#define EVHTP_CODE_TIMEOUT        408
-#define EVHTP_CODE_CONFLICT       409
-#define EVHTP_CODE_GONE           410
-#define EVHTP_CODE_LENREQ         411
-#define EVHTP_CODE_PRECONDFAIL    412
-#define EVHTP_CODE_ENTOOLARGE     413
-#define EVHTP_CODE_URITOOLARGE    414
-#define EVHTP_CODE_UNSUPPORTED    415
-#define EVHTP_CODE_RANGENOTSC     416
-#define EVHTP_CODE_EXPECTFAIL     417
+#define EVHTP_RES_400             400
+#define EVHTP_RES_BADREQ          400
+#define EVHTP_RES_UNAUTH          401
+#define EVHTP_RES_PAYREQ          402
+#define EVHTP_RES_FORBIDDEN       403
+#define EVHTP_RES_NOTFOUND        404
+#define EVHTP_RES_METHNALLOWED    405
+#define EVHTP_RES_NACCEPTABLE     406
+#define EVHTP_RES_PROXYAUTHREQ    407
+#define EVHTP_RES_TIMEOUT         408
+#define EVHTP_RES_CONFLICT        409
+#define EVHTP_RES_GONE            410
+#define EVHTP_RES_LENREQ          411
+#define EVHTP_RES_PRECONDFAIL     412
+#define EVHTP_RES_ENTOOLARGE      413
+#define EVHTP_RES_URITOOLARGE     414
+#define EVHTP_RES_UNSUPPORTED     415
+#define EVHTP_RES_RANGENOTSC      416
+#define EVHTP_RES_EXPECTFAIL      417
 
-#define EVHTP_CODE_500            500
-#define EVHTP_CODE_SERVERR        500
-#define EVHTP_CODE_NOTIMPL        501
-#define EVHTP_CODE_BADGATEWAY     502
-#define EVHTP_CODE_SERVUNAVAIL    503
-#define EVHTP_CODE_GWTIMEOUT      504
-#define EVHTP_CODE_VERNSUPPORT    505
-#define EVHTP_CODE_BWEXEED        509
+#define EVHTP_RES_500             500
+#define EVHTP_RES_SERVERR         500
+#define EVHTP_RES_NOTIMPL         501
+#define EVHTP_RES_BADGATEWAY      502
+#define EVHTP_RES_SERVUNAVAIL     503
+#define EVHTP_RES_GWTIMEOUT       504
+#define EVHTP_RES_VERNSUPPORT     505
+#define EVHTP_RES_BWEXEED         509
 
 #ifndef DISABLE_SSL
 typedef SSL_SESSION evhtp_ssl_sess_t;
@@ -158,6 +151,9 @@
     EVHTP_HOOK_COMPLETE
 };
 
+#define EVHTP_HOOK_PRE_BODY  EVHTP_HOOK_HDRS_READ
+#define EVHTP_HOOK_READ_BODY EVHTP_HOOK_READ
+
 enum evhtp_proto {
     EVHTP_PROTO_INVALID,
     EVHTP_PROTO_1_0,
@@ -211,7 +207,20 @@
 evbuf_t          * evhtp_request_get_output(evhtp_request_t *);
 evbase_t         * evhtp_request_get_evbase(evhtp_request_t *);
 evserv_t         * evhtp_request_get_listener(evhtp_request_t *);
+evhtp_method       evhtp_request_get_method(evhtp_request_t *);
+evhtp_proto        evhtp_request_get_proto(evhtp_request_t *);
+evhtp_conn_t     * evhtp_request_get_conn(evhtp_request_t *);
+evhtp_hdrs_t     * evhtp_request_get_headers_in(evhtp_request_t *);
+evhtp_hdrs_t     * evhtp_request_get_headers_out(evhtp_request_t *);
+evhtp_callback_cb  evhtp_request_get_cb(evhtp_request_t *);
+void             * evhtp_request_get_cbarg(evhtp_request_t *);
 int                evhtp_request_get_sock(evhtp_request_t *);
+const char       * evhtp_request_get_path(evhtp_request_t *);
+const char       * evhtp_request_get_uri(evhtp_request_t *);
+const char       * evhtp_request_method_str(evhtp_request_t *);
+int                evhtp_request_get_matched_soff(evhtp_request_t *);
+int                evhtp_request_get_matched_eoff(evhtp_request_t *);
+int64_t            evhtp_request_get_content_length(evhtp_request_t *);
 
 evbase_t         * evhtp_get_evbase(evhtp_t *);
 evserv_t         * evhtp_get_listener(evhtp_t *);
@@ -220,8 +229,8 @@
 int                evhtp_set_hook(evhtp_conn_t *, evhtp_hook_type, void * cb, void * arg);
 void               evhtp_set_pre_accept_cb(evhtp_t *, evhtp_pre_accept, void *);
 void               evhtp_set_post_accept_cb(evhtp_t *, evhtp_post_accept, void *);
-void               evhtp_send_reply(evhtp_request_t *, evhtp_status, const char *, evbuf_t *);
-void               evhtp_send_reply_stream(evhtp_request_t *, evhtp_status, evhtp_stream_cb, void *);
+void               evhtp_send_reply(evhtp_request_t *, evhtp_res, const char *, evbuf_t *);
+void               evhtp_send_reply_stream(evhtp_request_t *, evhtp_res, evhtp_stream_cb, void *);
 void               evhtp_send_stream(evhtp_request_t *, evbuf_t *);
 void               evhtp_request_make_chunk(evhtp_request_t *, evbuf_t *);
 
@@ -238,20 +247,14 @@
 void               evhtp_hdr_free(evhtp_hdr_t *);
 
 const char       * evhtp_version(void);
+const char       * evhtp_method_str(evhtp_method);
 
 int                evhtp_use_threads(evhtp_t *, int);
-
 int                evhtp_use_ssl(evhtp_t *, evhtp_ssl_cfg *);
+
 void             * evhtp_ssl_scache_builtin_init(evhtp_t *);
 int                evhtp_ssl_scache_builtin_add(evhtp_conn_t *, unsigned char *, int, evhtp_ssl_sess_t *);
 evhtp_ssl_sess_t * evhtp_ssl_scache_builtin_get(evhtp_conn_t *, unsigned char *, int);
 
-#ifndef DISABLE_SSL
-int                evhtp_use_ssl(evhtp_t *, evhtp_ssl_cfg *);
-void             * evhtp_ssl_scache_builtin_init(evhtp_t *);
-int                evhtp_ssl_scache_builtin_add(evhtp_conn_t *, unsigned char *, int, evhtp_ssl_sess_t *);
-evhtp_ssl_sess_t * evhtp_ssl_scache_builtin_get(evhtp_conn_t *, unsigned char *, int);
-#endif
-
 #endif /* __EVHTP_H__ */
 
diff --git a/perftest.sh b/perftest.sh
index 2afa28d..ab0be0b 100755
--- a/perftest.sh
+++ b/perftest.sh
@@ -14,5 +14,5 @@
 
 echo "Running ($conns connections | $calls requests each)"
 
-#httperf --ssl --server=$host --port=$port --uri=$uri --rate=1e+06 --send-buffer=4096 --recv-buffer=16384 --wsess=$conns,$calls,0 
+#httperf --ssl --server=$host --port=$port --uri=$uri --rate=1e+06 --send-buffer=4096 --recv-buffer=16384 --wsess=$conns,$calls,0
 httperf --server=$host --port=$port --uri=$uri --rate=1e+06 --send-buffer=4096 --recv-buffer=16384 --wsess=$conns,$calls,0
diff --git a/test.c b/test.c
index 04da5cd..44e8247 100644
--- a/test.c
+++ b/test.c
@@ -52,27 +52,27 @@
     carg->idx = 0;
     carg->buf = evbuffer_new();
 
-    evhtp_send_reply_stream(req, EVHTP_CODE_OK, _send_chunk, carg);
+    evhtp_send_reply_stream(req, EVHTP_RES_OK, _send_chunk, carg);
 }
 
 static void
 test_regex(evhtp_request_t * req, void * arg) {
-    evhtp_send_reply(req, EVHTP_CODE_OK, "REGEXOK", NULL);
+    evhtp_send_reply(req, EVHTP_RES_OK, "REGEXOK", NULL);
 }
 
 static void
 test_foo_cb(evhtp_request_t * req, void * arg) {
-    evhtp_send_reply(req, EVHTP_CODE_OK, "OK", NULL);
+    evhtp_send_reply(req, EVHTP_RES_OK, "OK", NULL);
 }
 
 static void
 test_500_cb(evhtp_request_t * req, void * arg) {
-    evhtp_send_reply(req, EVHTP_CODE_SERVERR, "no", NULL);
+    evhtp_send_reply(req, EVHTP_RES_SERVERR, "no", NULL);
 }
 
 static void
 test_bar_cb(evhtp_request_t * req, void * arg) {
-    evhtp_send_reply(req, EVHTP_CODE_OK, "OK", NULL);
+    evhtp_send_reply(req, EVHTP_RES_OK, "OK", NULL);
 }
 
 static void
@@ -80,7 +80,7 @@
     struct evbuffer * b = evbuffer_new();
 
     evbuffer_add_reference(b, "derp", 4, NULL, NULL);
-    evhtp_send_reply(req, EVHTP_CODE_OK, "Everything is fine", b);
+    evhtp_send_reply(req, EVHTP_RES_OK, "Everything is fine", b);
     evbuffer_free(b);
 }
 
@@ -120,14 +120,14 @@
     return EVHTP_RES_OK;
 }
 
-static evhtp_status
+static evhtp_res
 inspect_expect(evhtp_request_t * req, const char * expct_str, void * arg) {
     if (strcmp(expct_str, "100-continue")) {
         printf("Inspecting expect failed!\n");
-        return EVHTP_CODE_EXPECTFAIL;
+        return EVHTP_RES_EXPECTFAIL;
     }
 
-    return EVHTP_CODE_CONTINUE;
+    return EVHTP_RES_CONTINUE;
 }
 
 static evhtp_res