Merge branch 'release/1.2.12'
diff --git a/.github/issue_template.md b/.github/issue_template.md
new file mode 100644
index 0000000..d944465
--- /dev/null
+++ b/.github/issue_template.md
@@ -0,0 +1,3 @@
+# Details
+# Steps or code to reproduce the problem.
+# Version
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b24b08d..8a01f86 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,7 +3,7 @@
 
 set(PROJECT_MAJOR_VERSION 1)
 set(PROJECT_MINOR_VERSION 2)
-set(PROJECT_PATCH_VERSION 11)
+set(PROJECT_PATCH_VERSION 12)
 set(PROJECT_VERSION      ${PROJECT_MAJOR_VERSION}.${PROJECT_MINOR_VERSION}.${PROJECT_PATCH_VERSION})
 
 set(CMAKE_C_FLAGS         "${CMAKE_C_FLAGS} -DPROJECT_VERSION=${PROJECT_VERSION} -Wall")
@@ -237,7 +237,8 @@
 include_directories(
 	${CMAKE_CURRENT_BINARY_DIR}
 	${CMAKE_CURRENT_BINARY_DIR}/compat
-	${CMAKE_CURRENT_SOURCE_DIR}
+	${CMAKE_SOURCE_DIR}/include
+    ${CMAKE_CURRENT_BINARY_DIR}/include
 	${ONIG_INCLUDE_DIR}
 	${OPENSSL_INCLUDE_DIR}
 	${LIBEVENT_INCLUDE_DIR}
@@ -259,7 +260,10 @@
 	set (EVHTP_DISABLE_SSL ON)
 endif(NOT ${LIBEVENT_OPENSSL_FOUND})
 
-set(LIBEVHTP_SOURCES evhtp.c evhtp_numtoa.c htparse.c)
+set (LIBEVHTP_SOURCES
+    evhtp.c
+    numtoa.c
+    parser.c)
 
 if (EVHTP_USE_JEMALLOC)
 		set(LIBEVHTP_EXTERNAL_LIBS ${LIBEVHTP_EXTERNAL_LIBS} jemalloc)
@@ -272,24 +276,24 @@
 
 if (NOT EVHTP_DISABLE_EVTHR)
 	set (LIBEVHTP_EXTERNAL_LIBS ${LIBEVHTP_EXTERNAL_LIBS} pthread)
-	set (LIBEVHTP_SOURCES ${LIBEVHTP_SOURCES} evthr.c)
-endif(NOT EVHTP_DISABLE_EVTHR)
+	set (LIBEVHTP_SOURCES       ${LIBEVHTP_SOURCES}       thread.c)
+endif()
 
-IF (WIN32)
-	add_definitions(-DWIN32 -march=i486)
-	find_library (LIB_WS32 ws2_32)
-	set (SYS_LIBS ${SYS_LIBS} ${LIB_WS32})
-ELSE ()
+if (WIN32)
+	add_definitions (-DWIN32 -march=i486)
+	find_library    (LIB_WS32 ws2_32)
+	set             (SYS_LIBS ${SYS_LIBS} ${LIB_WS32})
+else ()
 	if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
 		find_library (LIB_DL dl)
-		set (SYS_LIBS ${LIB_DL})
+		set          (SYS_LIBS ${LIB_DL})
 	endif()
 
 	if (NOT APPLE)
 		find_library (LIB_RT rt)
-		set (SYS_LIBS ${SYS_LIBS} ${LIB_RT})
+		set          (SYS_LIBS ${SYS_LIBS} ${LIB_RT})
 	endif()
-ENDIF (WIN32)
+endif ()
 
 if (EVHTP_BUILD_SHARED)
 	set (EVHTP_LIBTYPE SHARED)
@@ -298,11 +302,15 @@
 endif()
 
 configure_file(
-	${CMAKE_CURRENT_SOURCE_DIR}/evhtp-config.h.in
-	${CMAKE_CURRENT_BINARY_DIR}/evhtp-config.h)
+	${CMAKE_CURRENT_SOURCE_DIR}/include/evhtp/config.h.in
+	${CMAKE_CURRENT_BINARY_DIR}/include/evhtp/config.h)
 
-add_library(evhtp ${EVHTP_LIBTYPE} ${LIBEVHTP_SOURCES} ${ONIG_SOURCES})
-target_link_libraries(evhtp ${LIBEVHTP_EXTERNAL_LIBS})
+add_library(evhtp ${EVHTP_LIBTYPE}
+    ${LIBEVHTP_SOURCES}
+    ${ONIG_SOURCES})
+
+target_link_libraries(evhtp
+    ${LIBEVHTP_EXTERNAL_LIBS})
 
 if (EVHTP_BUILD_SHARED)
 		set_target_properties(evhtp PROPERTIES SOVERSION "${PROJECT_VERSION}")
@@ -319,12 +327,33 @@
 endif()
 
 install (TARGETS evhtp DESTINATION ${LIB_INSTALL_DIR})
-install (FILES evhtp.h DESTINATION ${INCLUDE_INSTALL_DIR}/evhtp)
-install (FILES htparse.h DESTINATION ${INCLUDE_INSTALL_DIR}/evhtp)
-install (FILES ${CMAKE_CURRENT_BINARY_DIR}/evhtp-config.h DESTINATION ${INCLUDE_INSTALL_DIR}/evhtp)
+
+install (
+    FILES
+        ${PROJECT_SOURCE_DIR}/include/evhtp/evhtp.h
+        ${PROJECT_SOURCE_DIR}/include/evhtp/parser.h
+        ${PROJECT_SOURCE_DIR}/include/evhtp/thread.h
+    DESTINATION
+        ${INCLUDE_INSTALL_DIR}/evhtp)
+
+install (
+    FILES
+        ${PROJECT_SOURCE_DIR}/include/evhtp.h
+    DESTINATION
+        ${INCLUDE_INSTALL_DIR})
+
+install (
+    FILES
+        ${CMAKE_CURRENT_BINARY_DIR}/include/evhtp/config.h
+    DESTINATION
+        ${INCLUDE_INSTALL_DIR}/evhtp)
 
 if (NOT EVHTP_DISABLE_EVTHR)
-	install (FILES evthr.h DESTINATION ${INCLUDE_INSTALL_DIR}/evhtp)
+    install (
+        FILES
+            ${PROJECT_SOURCE_DIR}/include/evhtp/thread.h
+        DESTINATION
+            ${INCLUDE_INSTALL_DIR}/evhtp)
 endif()
 
 if (NOT EVHTP_DISABLE_REGEX)
@@ -421,7 +450,7 @@
     OUTPUT_STRIP_TRAILING_WHITESPACE
   )
   set(CPACK_PACKAGE_FILE_NAME
-"${CPACK_PACKAGE_NAME_LOWERCASE}_${PROJECT_VERSION}-${PROJECT_VERSION_REVISION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")  
+"${CPACK_PACKAGE_NAME_LOWERCASE}_${PROJECT_VERSION}-${PROJECT_VERSION_REVISION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
 
 else(DPKG_PROGRAM)
   set(CPACK_PACKAGE_FILE_NAME
diff --git a/ChangeLog b/ChangeLog
index 2484c21..4d4dc31 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,17 @@
-v1.3.12-pre3
+v1.2.12
+ o remove evhtp_heap, never used (d132721 Nathan French)
+ o remove evhtp_json, never used (aec4b3c Nathan French)
+ o [Issue#20] Include pathing (80a69cc Nathan French)
+ o Fix deprecated usage (f4c42c7 Roman Gershman)
+ o Create issue_template.md (8d1a95f Nathan French)
+ o [Issue#25] Return NULL if callbacks == NULL for get_cb (cfcdba4 Nathan French)
+ o adding more null checks. I wish __attr__(nonull) was portable (9b552b7 Nathan French)
+ o adding some struct accessor defines to make life easier (613c5bf Nathan French)
+ o I think I worked out most of the potential derefs (acb42cf Nathan French)
+ o Fix potential null deref in htp__strndup_ (60b85ca Nathan French)
+ o Fix dead assignments in parser.c (e0a48e1 Nathan French)
+ o Eat our own dogfood (use_thread_wexit()) (ea37928 Nathan French)
+ o No use for strlen() in a loop (6833080 Nathan French)
  o use PROJECT_BINARY_DIR for sys/ compat headers (012341c Nathan French)
  o return int for htp__path_new_ (bf59eb1 Nathan French)
  o more return normalization (91008a6 Nathan French)
@@ -8,15 +21,11 @@
  o for some reason, htparser_init was being called manually with type_request?? (a153e5f Nathan French)
  o Add htp__strndup_ memfn wrapper (763168c Nathan French)
  o add a callback member in evhtp_ssl_cfg_t for customized decrypt privfile. fixes #16 (b3a4d42 h00360646)
-
-v1.2.12-pre2
  o Internalize some structs / deprecate evhtp_set_hook() (50ab327 Nathan French)
  o remove cruft (1b1a037 Nathan French)
  o add include directory for compat/sys headers (948c547 Nathan French)
  o export flag functions (3467cbb Nathan French)
  o formatting (4ec8dd3 Nathan French)
-
-v1.2.12-pre1
  o (evhtp_send_reply): Grab reference to bufferevent during write. (a976a2f Marcus Sundberg)
  o add thread exit callback for cleaning (0c7d9c4 jgli)
  o fix memory leak (a6b00cc jgli)
@@ -214,7 +223,7 @@
 
 v1.2.8
  o There's no libdl on FreeBSD. (a683a1f Adrian Chadd)
- o FreeBSD handles the POSIX_C_SOURCE definition very strictly - strncmp() and a lot of other stuff isn't defined in the 2001 standards.  
+ o FreeBSD handles the POSIX_C_SOURCE definition very strictly - strncmp() and a lot of other stuff isn't defined in the 2001 standards.
    Thus, the functions aren't declared when you include the library headers. (0354a67 Adrian Chadd)
 
 v1.2.7
diff --git a/evhtp.c b/evhtp.c
index ece5ac8..7bd2700 100644
--- a/evhtp.c
+++ b/evhtp.c
@@ -22,9 +22,9 @@
 #include <limits.h>
 #include <event2/dns.h>
 
-#include "evhtp-internal.h"
-#include "evhtp_numtoa.h"
-#include "evhtp.h"
+#include "internal.h"
+#include "numtoa.h"
+#include "evhtp/evhtp.h"
 
 /**
  * @brief structure containing a single callback and configuration
@@ -137,6 +137,18 @@
          (var) = (tvar))
 #endif
 
+/* rc == request->conn. Just little things to make life easier */
+#define rc_scratch  conn->scratch_buf
+#define rc_parser   conn->parser
+
+/* ch_ == conn->hooks->on_... */
+#define ch_fini_arg hooks->on_connection_fini_arg
+#define ch_fini     hooks->on_connection_fini
+
+/* rh_ == request->hooks->on_ */
+#define rh_err      hooks->on_error
+#define rh_err_arg  hooks->on_error_arg
+
 #ifndef EVHTP_DISABLE_MEMFUNCTIONS
 
 static void * (*malloc_)(size_t sz) = malloc;
@@ -169,11 +181,13 @@
         size_t len = nmemb * size;
         void * p;
 
-        if ((p = malloc_(len)) != NULL)
+        if ((p = malloc_(len)) == NULL)
         {
-            memset(p, 0, len);
+            return NULL;
         }
 
+        memset(p, 0, len);
+
         return p;
     }
 
@@ -185,14 +199,18 @@
 {
     if (malloc_ != malloc)
     {
-        size_t len = strlen(str);
+        size_t len;
         void * p;
 
-        if ((p = malloc_(len + 1)) != NULL)
+        len = strlen(str);
+
+        if ((p = malloc_(len + 1)) == NULL)
         {
-            memcpy(p, str, len + 1);
+            return NULL;
         }
 
+        memcpy(p, str, len + 1);
+
         return p;
     }
 
@@ -209,6 +227,8 @@
         if ((p = malloc_(len + 1)) != NULL)
         {
             memcpy(p, str, len + 1);
+        } else {
+            return NULL;
         }
 
         p[len] = '\0';
@@ -387,7 +407,11 @@
         return htp__strdup_(s);
     }
 
-    ret    = htp__malloc_(n + 1);
+    if ((ret = htp__malloc_(n + 1)) == NULL)
+    {
+        return NULL;
+    }
+
     ret[n] = '\0';
 
     memcpy(ret, s, n);
@@ -595,10 +619,9 @@
         return 500;
     }
 
-    if (connection->hooks != NULL && connection->hooks->on_connection_fini != NULL)
+    if (connection->hooks != NULL && connection->ch_fini != NULL)
     {
-        return (connection->hooks->on_connection_fini)(connection,
-                                                       connection->hooks->on_connection_fini_arg);
+        return (connection->ch_fini)(connection, connection->ch_fini_arg);
     }
 
     return EVHTP_RES_OK;
@@ -613,10 +636,9 @@
 static inline void
 htp__hook_error_(evhtp_request_t * request, evhtp_error_flags errtype)
 {
-    if (request && request->hooks && request->hooks->on_error)
+    if (request && request->hooks && request->rh_err)
     {
-        (*request->hooks->on_error)(request, errtype,
-                                    request->hooks->on_error_arg);
+        (*request->rh_err)(request, errtype, request->rh_err_arg);
     }
 }
 
@@ -744,6 +766,7 @@
                     unsigned int      * start_offset,
                     unsigned int      * end_offset)
 {
+    size_t path_len;
 #ifndef EVHTP_DISABLE_REGEX
     regmatch_t pmatch[28];
 #endif
@@ -754,19 +777,16 @@
         return NULL;
     }
 
+    path_len = strlen(path);
+
     TAILQ_FOREACH(callback, cbs, next)
     {
         switch (callback->type) {
             case evhtp_callback_type_hash:
-                if (callback->val.path[1] != path[1])
-                {
-                    continue;
-                }
-
-                if (strcmp(callback->val.path, path) == 0)
+                if (strncmp(callback->val.path, path, path_len) == 0)
                 {
                     *start_offset = 0;
-                    *end_offset   = (unsigned int)strlen(path);
+                    *end_offset   = path_len;
 
                     return callback;
                 }
@@ -788,7 +808,6 @@
 #endif
             case evhtp_callback_type_glob:
             {
-                size_t path_len = strlen(path);
                 size_t glob_len = strlen(callback->val.glob);
 
                 if (htp__glob_match_(callback->val.glob,
@@ -797,7 +816,7 @@
                                      path_len) == 1)
                 {
                     *start_offset = 0;
-                    *end_offset   = (unsigned int)path_len;
+                    *end_offset   = path_len;
 
                     return callback;
                 }
@@ -969,6 +988,11 @@
 {
     evhtp_authority_t * authority;
 
+    if (evhtp_unlikely(out == NULL))
+    {
+        return -1;
+    }
+
     *out = htp__calloc_(1, sizeof(*authority));
 
     return (*out != NULL) ? 0 : -1;
@@ -1098,7 +1122,7 @@
     evhtp_request_t * req;
     uint8_t           error;
 
-    if (evhtp_unlikely(!(req = htp__calloc_(sizeof(evhtp_request_t), 1))))
+    if (evhtp_unlikely(!(req = htp__calloc_(sizeof(*req), 1))))
     {
         return NULL;
     }
@@ -1525,27 +1549,44 @@
 static int
 htp__require_uri_(evhtp_connection_t * c)
 {
-    if (c != NULL && c->request != NULL && c->request->uri == NULL)
+    if (c != NULL && c->request != NULL)
     {
-        evhtp_assert(htp__uri_new_(&c->request->uri) == 0);
+        if (c->request->uri == NULL)
+        {
+            return htp__uri_new_(&c->request->uri);
+        }
+
+        return 0;
     }
 
-    return 0;
+    return -1;
 }
 
 static int
 htp__request_parse_host_(htparser * p, const char * data, size_t len)
 {
-    evhtp_connection_t * c = htparser_get_userdata(p);
+    evhtp_connection_t * c;
     evhtp_authority_t  * authority;
 
+    if (evhtp_unlikely(p == NULL))
+    {
+        return -1;
+    }
+
+    c = htparser_get_userdata(p);
+
+    /* all null checks are done in require_uri_,
+     * no need to check twice
+     */
     if (htp__require_uri_(c) == -1)
     {
         return -1;
     }
 
+
     authority           = c->request->uri->authority;
     authority->hostname = htp__malloc_(len + 1);
+    evhtp_alloc_assert(authority->hostname);
 
     if (authority->hostname == NULL)
     {
@@ -1594,6 +1635,11 @@
     evhtp_connection_t * c = htparser_get_userdata(p);
     evhtp_path_t       * path;
 
+    if (evhtp_unlikely(p == NULL || c == NULL))
+    {
+        return -1;
+    }
+
     if (htp__require_uri_(c) == -1)
     {
         return -1;
@@ -1811,6 +1857,8 @@
 
     /* check to see if we should use the body of the request as the query
      * arguments.
+     *
+     * htp__should_parse_query_body_ does all the proper null checks.
      */
     if (htp__should_parse_query_body_(c->request) == 1)
     {
@@ -1879,18 +1927,24 @@
     unsigned char     minor;
     char              out_buf[64];
 
+    evhtp_assert(request
+                 && request->headers_out
+                 && request->buffer_out
+                 && request->conn
+                 && request->rc_parser);
 
     content_type = evhtp_header_find(request->headers_out, "Content-Type");
     out_len      = evbuffer_get_length(request->buffer_out);
 
-    if ((buf = request->conn->scratch_buf) == NULL)
+    if ((buf = request->rc_scratch) == NULL)
     {
-        return NULL;
+        request->rc_scratch = evbuffer_new();
+        evhtp_alloc_assert(request->rc_scratch);
     }
 
     evbuffer_drain(buf, -1);
 
-    if (htparser_get_multipart(request->conn->parser) == 1)
+    if (htparser_get_multipart(request->rc_parser) == 1)
     {
         goto check_proto;
     }
@@ -1939,8 +1993,8 @@
         default:
             /* this sometimes happens when a response is made but paused before
              * the method has been parsed */
-            htparser_set_major(request->conn->parser, 1);
-            htparser_set_minor(request->conn->parser, 0);
+            htparser_set_major(request->rc_parser, 1);
+            htparser_set_minor(request->rc_parser, 0);
             break;
     } /* switch */
 
@@ -1957,8 +2011,8 @@
      * we fallback to using evbuffer_add_printf().
      */
 
-    major = evhtp_modp_uchartoa(htparser_get_major(request->conn->parser));
-    minor = evhtp_modp_uchartoa(htparser_get_minor(request->conn->parser));
+    major = evhtp_modp_uchartoa(htparser_get_major(request->rc_parser));
+    minor = evhtp_modp_uchartoa(htparser_get_minor(request->rc_parser));
 
     evhtp_modp_u32toa((uint32_t)code, out_buf);
 
@@ -2022,12 +2076,13 @@
     size_t               nread;
     size_t               avail;
 
-    htp_log_debug("enter sock = %d", c->sock);
+    if (evhtp_unlikely(bev == NULL))
+    {
+        return;
+    }
 
     avail = evbuffer_get_length(bufferevent_get_input(bev));
 
-    htp_log_debug("available bytes %zu", avail);
-
     if (evhtp_unlikely(avail == 0))
     {
         return;
@@ -2045,7 +2100,8 @@
 
     buf   = evbuffer_pullup(bufferevent_get_input(bev), avail);
 
-    htp_log_debug("buffer is\n----\n%.*s\n-----", (int)avail, (const char *)buf);
+    evhtp_assert(buf != NULL);
+    evhtp_assert(c->parser != NULL);
 
     nread = htparser_run(c->parser, &request_psets, (const char *)buf, avail);
 
@@ -2094,14 +2150,11 @@
 static void
 htp__connection_writecb_(struct bufferevent * bev, void * arg)
 {
-    evhtp_connection_t * c = arg;
+    evhtp_connection_t * c;
 
-    htp_log_debug("c->request = %p", c->request);
+    c = arg;
 
-    if (evhtp_unlikely(c->request == NULL))
-    {
-        return;
-    }
+    evhtp_assert(c && c->htp && c->request && c->parser && bev);
 
     htp__hook_connection_write_(c);
 
@@ -2501,7 +2554,11 @@
     evhtp_t            * htp = arg;
     evhtp_connection_t * connection;
 
-    if (evhtp_unlikely(!(connection = htp__connection_new_(htp, fd, evhtp_type_server))))
+    evhtp_assert(htp && serv && serv && s);
+
+    connection = htp__connection_new_(htp, fd, evhtp_type_server);
+
+    if (evhtp_unlikely(connection == NULL))
     {
         return;
     }
@@ -2530,17 +2587,15 @@
 #endif
     connection->evbase = htp->evbase;
 
-    if (htp__connection_accept_(htp->evbase, connection) < 0)
+    if (htp__connection_accept_(htp->evbase, connection) == -1)
     {
         evhtp_connection_free(connection);
-
         return;
     }
 
-    if (htp__run_post_accept_(htp, connection) < 0)
+    if (htp__run_post_accept_(htp, connection) == -1)
     {
         evhtp_connection_free(connection);
-
         return;
     }
 }     /* htp__accept_cb_ */
@@ -2647,6 +2702,11 @@
     evhtp_t            * evhtp;
     evhtp_t            * evhtp_vhost;
 
+    if (evhtp_unlikely(ssl == NULL))
+    {
+        return SSL_TLSEXT_ERR_NOACK;
+    }
+
     if (!(sname = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name)))
     {
         return SSL_TLSEXT_ERR_NOACK;
@@ -2766,11 +2826,11 @@
 }
 
 evhtp_header_t *
-evhtp_header_key_add(evhtp_headers_t * headers, const char * key, char kalloc)
+evhtp_header_key_add(evhtp_headers_t * headers, const char * key, char key_alloc)
 {
     evhtp_header_t * header;
 
-    if (!(header = evhtp_header_new(key, NULL, kalloc, 0)))
+    if (!(header = evhtp_header_new(key, NULL, key_alloc, 0)))
     {
         return NULL;
     }
@@ -2781,7 +2841,7 @@
 }
 
 evhtp_header_t *
-evhtp_header_val_add(evhtp_headers_t * headers, const char * val, char valloc)
+evhtp_header_val_add(evhtp_headers_t * headers, const char * val, char val_alloc)
 {
     evhtp_header_t * header;
 
@@ -2802,16 +2862,18 @@
 
     header->vlen = strlen(val);
 
-    if (valloc == 1)
+    if (val_alloc == 1)
     {
         header->val = htp__malloc_(header->vlen + 1);
+        evhtp_alloc_assert(header->val);
+
         header->val[header->vlen] = '\0';
         memcpy(header->val, val, header->vlen);
     } else {
         header->val = (char *)val;
     }
 
-    header->v_heaped = valloc;
+    header->v_heaped = val_alloc;
 
     return header;
 }
@@ -2830,15 +2892,16 @@
 }
 
 evhtp_kv_t *
-evhtp_kv_new(const char * key, const char * val, char kalloc, char valloc)
+evhtp_kv_new(const char * key, const char * val,
+             char key_alloc, char val_alloc)
 {
     evhtp_kv_t * kv;
 
     kv           = htp__malloc_(sizeof(evhtp_kv_t));
     evhtp_alloc_assert(kv);
 
-    kv->k_heaped = kalloc;
-    kv->v_heaped = valloc;
+    kv->k_heaped = key_alloc;
+    kv->v_heaped = val_alloc;
     kv->klen     = 0;
     kv->vlen     = 0;
     kv->key      = NULL;
@@ -2848,7 +2911,7 @@
     {
         kv->klen = strlen(key);
 
-        if (kalloc == 1)
+        if (key_alloc == 1)
         {
             char * s;
 
@@ -2872,7 +2935,7 @@
     {
         kv->vlen = strlen(val);
 
-        if (valloc == 1)
+        if (val_alloc == 0)
         {
             char * s = htp__malloc_(kv->vlen + 1);
 
@@ -3883,10 +3946,12 @@
     switch (type) {
         case evhtp_callback_type_hash:
             hcb->val.path  = htp__strdup_(path);
+            evhtp_alloc_assert(hcb->val.path);
             break;
 #ifndef EVHTP_DISABLE_REGEX
         case evhtp_callback_type_regex:
             hcb->val.regex = htp__malloc_(sizeof(regex_t));
+            evhtp_alloc_assert(hcb->val.regex);
 
             if (regcomp(hcb->val.regex, (char *)path, REG_EXTENDED) != 0)
             {
@@ -3899,6 +3964,7 @@
 #endif
         case evhtp_callback_type_glob:
             hcb->val.glob = htp__strdup_(path);
+            evhtp_alloc_assert(hcb->val.glob);
             break;
         default:
             evhtp_safe_free(hcb, htp__free_);
@@ -3907,7 +3973,7 @@
     }     /* switch */
 
     return hcb;
-}
+} /* evhtp_callback_new */
 
 void
 evhtp_callback_free(evhtp_callback_t * callback)
@@ -4214,6 +4280,13 @@
 {
     evhtp_callback_t * callback;
 
+    evhtp_assert(htp != NULL);
+
+    if (evhtp_unlikely(htp->callbacks == NULL))
+    {
+        return NULL;
+    }
+
     TAILQ_FOREACH(callback, htp->callbacks, next)
     {
         if (strcmp(callback->val.path, path) == 0)
diff --git a/evhtp_heap.c b/evhtp_heap.c
deleted file mode 100644
index 884b743..0000000
--- a/evhtp_heap.c
+++ /dev/null
@@ -1,110 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <errno.h>
-#include <assert.h>
-#include <stddef.h>
-#include <sys/queue.h>
-
-#include "evhtp-internal.h"
-#include "evhtp_heap.h"
-
-struct evhtp_heap_page_s;
-typedef struct evhtp_heap_page_s evhtp_heap_page;
-
-struct evhtp_heap_page_s {
-    SLIST_ENTRY(evhtp_heap_page_s) next;
-    char data[];
-};
-
-struct evhtp_heap_s {
-    size_t page_size;             /* page size */
-
-    SLIST_HEAD(, evhtp_heap_page_s) page_list_free;
-    SLIST_HEAD(, evhtp_heap_page_s) page_list_used;
-};
-
-
-static evhtp_heap_page *
-heap_page_new_(evhtp_heap * heap) {
-    evhtp_heap_page * page;
-
-    page = malloc(heap->page_size + sizeof(evhtp_heap_page));
-
-    SLIST_INSERT_HEAD(&heap->page_list_free, page, next);
-
-    return page;
-};
-
-
-static evhtp_heap *
-heap_new_(size_t elts, size_t size) {
-    evhtp_heap * heap;
-
-    if (!(heap = malloc(sizeof(evhtp_heap)))) {
-        return NULL;
-    }
-
-    heap->page_size = size;
-
-    SLIST_INIT(&heap->page_list_free);
-    SLIST_INIT(&heap->page_list_used);
-
-    while (elts-- > 0) {
-        heap_page_new_(heap);
-    }
-
-    return heap;
-}
-
-static void
-heap_free_(evhtp_heap * heap, void * d) {
-    evhtp_heap_page * page;
-
-    if (evhtp_unlikely(heap == NULL)) {
-        return;
-    }
-
-    evhtp_assert(d != NULL);
-
-    page = (evhtp_heap_page *)((char *)(d - offsetof(evhtp_heap_page, data)));
-    evhtp_assert(page != NULL);
-    evhtp_assert(page->data == d);
-
-    SLIST_REMOVE(&heap->page_list_used, page, evhtp_heap_page_s, next);
-    SLIST_INSERT_HEAD(&heap->page_list_free, page, next);
-}
-
-void
-evhtp_heap_free(evhtp_heap * heap, void * data) {
-    return heap_free_(heap, data);
-}
-
-static void *
-heap_alloc_(evhtp_heap * heap) {
-    evhtp_heap_page * page;
-
-    if (SLIST_EMPTY(&heap->page_list_free)) {
-        heap_page_new_(heap);
-    }
-
-    page = SLIST_FIRST(&heap->page_list_free);
-    evhtp_assert(page != NULL);
-
-    SLIST_REMOVE(&heap->page_list_free, page, evhtp_heap_page_s, next);
-    SLIST_INSERT_HEAD(&heap->page_list_used, page, next);
-
-    return page->data;
-}
-
-void *
-evhtp_heap_alloc(evhtp_heap * heap) {
-    return heap_alloc_(heap);
-}
-
-evhtp_heap *
-evhtp_heap_new(size_t size, size_t elts) {
-    return heap_new_(elts, size);
-}
-
diff --git a/evhtp_heap.h b/evhtp_heap.h
deleted file mode 100644
index 7bbb2bb..0000000
--- a/evhtp_heap.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef __EVHTP_HEAP_H__
-#define __EVHTP_HEAP_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct evhtp_heap_s;
-
-typedef struct evhtp_heap_s evhtp_heap;
-
-/**
- * @brief creates a new heap context
- *
- * @param size the size of the data to be allocated
- * @param nelem the number of elements allocated with the size
- *
- * @return NULL on error
- */
-EVHTP_EXPORT evhtp_heap * evhtp_heap_new(size_t size, size_t elts);
-
-/**
- * @brief returns a single pre-allocated segment of memory from the heap list,
- *        if there happens to be no entries left, one will be allocated, added to the
- *        heap and returned.
- *
- * @param heap
- *
- * @return a block of data
- */
-EVHTP_EXPORT void * evhtp_heap_alloc(evhtp_heap * heap);
-
-/**
- * @brief removes the data entry, and places it back into a unused queue.
- *
- * @param heap
- * @param d data that was returned from evhtp_heap_alloc()
- */
-EVHTP_EXPORT void evhtp_heap_free(evhtp_heap * heap, void * data);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
diff --git a/evhtp_json.c b/evhtp_json.c
deleted file mode 100644
index 3a65f29..0000000
--- a/evhtp_json.c
+++ /dev/null
@@ -1,1677 +0,0 @@
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <errno.h>
-#include <stdbool.h>
-#include <assert.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <unistd.h>
-
-
-#include "evhtp_heap.h"
-#include "evhtp_json.h"
-
-enum evhtp_j_state {
-    evhtp_j_s_start = 0,
-    evhtp_j_s_end
-};
-
-enum evhtp_j_arr_state {
-    evhtp_j_arr_s_val = 0,
-    evhtp_j_arr_s_comma,
-    evhtp_j_arr_s_end
-};
-
-enum evhtp_j_obj_state {
-    evhtp_j_obj_s_key = 0,
-    evhtp_j_obj_s_delim,
-    evhtp_j_obj_s_val,
-    evhtp_j_obj_s_comma,
-    evhtp_j_obj_s_end
-};
-
-typedef enum evhtp_j_state     evhtp_j_state;
-typedef enum evhtp_j_arr_state evhtp_j_arr_state;
-typedef enum evhtp_j_obj_state evhtp_j_obj_state;
-
-static __thread void * __js_heap = NULL;
-
-struct evhtp_json_s {
-    evhtp_json_vtype type;
-    union {
-        evhtp_kvmap * object;
-        evhtp_tailq * array;
-        char        * string;
-        unsigned int  number;
-        bool          boolean;
-    };
-
-    size_t slen;
-    void   (* freefn)(void *);
-};
-
-#define j_type_(j) (evhtp_likely(j) ? j->type : -1)
-
-evhtp_json_vtype
-evhtp_json_get_type(evhtp_json * js) {
-    if (evhtp_unlikely(js == NULL)) {
-        return -1;
-    } else {
-        return js->type;
-    }
-}
-
-ssize_t
-evhtp_json_get_size(evhtp_json * js) {
-    if (evhtp_unlikely(js == NULL)) {
-        return -1;
-    }
-
-    if (js == NULL) {
-        return -1;
-    }
-
-    switch (j_type_(js)) {
-        case evhtp_json_vtype_string:
-            return (ssize_t)js->slen;
-        case evhtp_json_vtype_array:
-            return evhtp_tailq_size(js->array);
-        case evhtp_json_vtype_object:
-            return evhtp_kvmap_get_size(js->object);
-        default:
-            return 0;
-    }
-
-    return 0;
-}
-
-evhtp_kvmap *
-evhtp_json_get_object(evhtp_json * js) {
-    if (evhtp_unlikely(js == NULL)) {
-        return NULL;
-    }
-
-    if (evhtp_unlikely(j_type_(js) != evhtp_json_vtype_object)) {
-        return NULL;
-    } else {
-        return js->object;
-    }
-}
-
-evhtp_tailq *
-evhtp_json_get_array(evhtp_json * js) {
-    if (js == NULL) {
-        return NULL;
-    }
-
-    if (evhtp_unlikely(j_type_(js) != evhtp_json_vtype_array)) {
-        return NULL;
-    }
-
-    return js->array;
-}
-
-unsigned int
-evhtp_json_get_number(evhtp_json * js) {
-    if (js == NULL) {
-        return 0;
-    }
-
-    if (evhtp_unlikely(j_type_(js) != evhtp_json_vtype_number)) {
-        return 0;
-    } else {
-        return js->number;
-    }
-}
-
-const char *
-evhtp_json_get_string(evhtp_json * js) {
-    if (evhtp_unlikely(js == NULL)) {
-        return NULL;
-    }
-
-    if (evhtp_likely(j_type_(js) == evhtp_json_vtype_string)) {
-        return js->string;
-    } else {
-        return NULL;
-    }
-}
-
-bool
-evhtp_json_get_boolean(evhtp_json * js) {
-    if (js == NULL) {
-        return false;
-    }
-
-    if (evhtp_unlikely(j_type_(js) != evhtp_json_vtype_bool)) {
-        return false;
-    } else {
-        return js->boolean;
-    }
-}
-
-char
-evhtp_json_get_null(evhtp_json * js) {
-    if (js == NULL) {
-        return -1;
-    }
-
-    if (evhtp_unlikely(j_type_(js) != evhtp_json_vtype_null)) {
-        return -1;
-    } else {
-        return 1;
-    }
-}
-
-static evhtp_json *
-j_new_(evhtp_json_vtype type) {
-    evhtp_json * evhtp_j;
-
-    if (evhtp_unlikely(__js_heap == NULL)) {
-        __js_heap = evhtp_heap_new(sizeof(evhtp_json), 1024);
-    }
-
-    evhtp_j         = evhtp_heap_alloc(__js_heap);
-    evhtp_alloc_assert(evhtp_j);
-
-    evhtp_j->type   = type;
-    evhtp_j->freefn = NULL;
-    return evhtp_j;
-}
-
-static evhtp_json *
-j_object_new_(void) {
-    evhtp_json * js;
-
-    if (!(js = j_new_(evhtp_json_vtype_object))) {
-        return NULL;
-    }
-
-    js->object = evhtp_kvmap_new(10);
-    js->freefn = (void (*))evhtp_kvmap_free;
-
-    return js;
-}
-
-static inline evhtp_json *
-j_array_new_(void) {
-    evhtp_json * js;
-
-    if (!(js = j_new_(evhtp_json_vtype_array))) {
-        return NULL;
-    }
-
-    js->array  = evhtp_tailq_new();
-    js->freefn = (void (*))evhtp_tailq_free;
-
-    return js;
-}
-
-static evhtp_json *
-j_string_new_(const char * str, size_t slen) {
-    evhtp_json * js;
-
-    js = j_new_(evhtp_json_vtype_string);
-    evhtp_alloc_assert(js);
-
-    if (evhtp_unlikely(str == NULL || slen == 0)) {
-        slen = 0;
-    }
-
-    js->string       = malloc(slen + 1);
-    evhtp_alloc_assert(js->string);
-
-    js->string[slen] = '\0';
-
-    memcpy(js->string, str, slen);
-
-    js->slen         = slen;
-    js->freefn       = free;
-
-    return js;
-}
-
-static evhtp_json *
-j_number_new_(unsigned int num) {
-    evhtp_json * js;
-
-    js         = j_new_(evhtp_json_vtype_number);
-    js->number = num;
-
-    return js;
-}
-
-static evhtp_json *
-j_boolean_new_(bool boolean) {
-    evhtp_json * js;
-
-    js          = j_new_(evhtp_json_vtype_bool);
-    js->boolean = boolean;
-
-    return js;
-}
-
-static evhtp_json *
-j_null_new_(void) {
-    return j_new_(evhtp_json_vtype_null);
-}
-
-static int
-j_object_add_(evhtp_json * dst, const char * key, evhtp_json * val) {
-    if (evhtp_unlikely(j_type_(dst) != evhtp_json_vtype_object)) {
-        return -1;
-    }
-
-    if (!evhtp_kvmap_add(dst->object, key, val, (void (*))evhtp_json_free)) {
-        return -1;
-    }
-
-    return 0;
-}
-
-static int
-j_object_add_klen_(evhtp_json * dst, const char * key, size_t klen, evhtp_json * val) {
-    if (evhtp_unlikely(j_type_(dst) != evhtp_json_vtype_object)) {
-        return -1;
-    }
-
-    if (!evhtp_kvmap_add_wklen(dst->object,
-                               key, klen, val, (void (*))evhtp_json_free)) {
-        return -1;
-    }
-
-    return 0;
-}
-
-static int
-j_array_add_(evhtp_json * dst, evhtp_json * src) {
-    if (evhtp_unlikely(j_type_(dst) != evhtp_json_vtype_array)) {
-        return -1;
-    }
-
-    if (!evhtp_tailq_append(dst->array, src, 1, (void (*))evhtp_json_free)) {
-        return -1;
-    }
-
-    return 0;
-}
-
-evhtp_json *
-evhtp_json_parse_string(const char * data, size_t len, size_t * n_read) {
-    unsigned char ch;
-    size_t        i;
-    size_t        buflen;
-    char          buf[len + 128];
-    int           buf_idx;
-    int           escaped;
-    bool          error;
-    evhtp_json  * js;
-
-    if (!data || !len || *data != '"') {
-        /* *n_read = 0; */
-        return NULL;
-    }
-
-    escaped = 0;
-    buf_idx = 0;
-    error   = false;
-    js      = NULL;
-    buflen  = len + 128;
-
-    len--;
-    data++;
-
-    for (i = 0; i < len; i++) {
-        if (buf_idx >= buflen) {
-            error = true;
-            errno = ENOBUFS;
-            goto end;
-        }
-
-        ch = data[i];
-
-        if (!evhtp_isascii(ch)) {
-            error = true;
-            goto end;
-        }
-
-        if (escaped) {
-            switch (ch) {
-                case '"':
-                case '/':
-                case 'b':
-                case 'f':
-                case 'n':
-                case 'r':
-                case 't':
-                case '\\':
-                    escaped        = 0;
-                    buf[buf_idx++] = ch;
-                    break;
-                default:
-                    error          = true;
-                    goto end;
-            }
-            continue;
-        }
-
-        if (ch == '\\') {
-            escaped = 1;
-            continue;
-        }
-
-        if (ch == '"') {
-            js = j_string_new(buf, buf_idx);
-            i += 1;
-            break;
-        }
-
-        buf[buf_idx++] = ch;
-    }
-
-end:
-    *n_read += i;
-
-    if (error == true) {
-        evhtp_safe_free(js, evhtp_json_free);
-        return NULL;
-    }
-
-    return js;
-} /* evhtp_json_parse_string */
-
-inline evhtp_json *
-evhtp_json_parse_key(const char * data, size_t len, size_t * n_read) {
-    return evhtp_json_parse_string(data, len, n_read);
-}
-
-evhtp_json *
-evhtp_json_parse_number(const char * data, size_t len, size_t * n_read) {
-    unsigned char ch;
-    char          buf[len];
-    int           buf_idx;
-    size_t        i;
-    evhtp_json  * js;
-
-    if (!data || !len) {
-        return NULL;
-    }
-
-    js      = NULL;
-    buf_idx = 0;
-
-    memset(buf, 0, sizeof(buf));
-
-    for (i = 0; i < len; i++) {
-        ch = data[i];
-
-        if (!isdigit(ch) || (len == 1 && isdigit(ch))) {
-            js = j_number_new((unsigned int)evhtp_atoi(buf, buf_idx));
-            break;
-        }
-
-        buf[buf_idx++] = ch;
-    }
-
-    *n_read += (len == 1) ? 1 : i - 1;
-
-    return js;
-}
-
-#define J_TRUE_CMP   0x657572
-#define J_FALSE_CMP  0x65736c61
-#define J_TRUE_MASK  0xFFFFFF
-#define J_FALSE_MASK 0xFFFFFFFF
-
-inline evhtp_json *
-evhtp_json_parse_boolean(const char * data, size_t len, size_t * n_read) {
-    evhtp_json * js;
-
-    if (evhtp_unlikely(len < 4)) {
-        /* need at LEAST 'true' */
-        return NULL;
-    }
-
-    js = NULL;
-
-    /* here we cast our data string to an integer, mask it by the
-     * number of words we want to see, then match the integer version
-     * of the string.
-     */
-    switch (*data) {
-        case 't':
-            if ((*((uint32_t *)(data + 1)) & J_TRUE_MASK) == J_TRUE_CMP) {
-                *n_read += 3;
-                js       = j_boolean_new(true);
-            }
-
-            break;
-        case 'f':
-            if (len < 5) {
-                return NULL;
-            }
-
-            if ((*((uint32_t *)(data + 1)) & J_FALSE_MASK) == J_FALSE_CMP) {
-                *n_read += 4;
-                js       = j_boolean_new(false);
-            }
-
-            break;
-        default:
-            return NULL;
-    } /* switch */
-
-    return js;
-}     /* evhtp_json_parse_boolean */
-
-evhtp_json *
-evhtp_json_parse_null(const char * data, size_t len, size_t * n_read) {
-    if (len < 4) {
-        return NULL;
-    }
-
-    if (!evhtp_str30_cmp(data, 'n', 'u', 'l', 'l')) {
-        return NULL;
-    }
-
-    *n_read += 4;
-
-    return j_null_new();
-}
-
-evhtp_json *
-evhtp_json_parse_value(const char * data, size_t len, size_t * n_read) {
-    if (data == NULL || len == 0) {
-        /* *n_read = 0; */
-        return NULL;
-    }
-
-    switch (data[0]) {
-        case '"':
-            return evhtp_json_parse_string(data, len, n_read);
-        case '{':
-            return evhtp_json_parse_object(data, len, n_read);
-        case '[':
-            return evhtp_json_parse_array(data, len, n_read);
-        default:
-            if (isdigit(data[0])) {
-                return evhtp_json_parse_number(data, len, n_read);
-            }
-
-            switch (*data) {
-                case 't':
-                case 'f':
-                    return evhtp_json_parse_boolean(data, len, n_read);
-                case 'n':
-                    return evhtp_json_parse_null(data, len, n_read);
-            }
-    } /* switch */
-
-    /* *n_read = 0; */
-    return NULL;
-}
-
-evhtp_json *
-evhtp_json_parse_array(const char * data, size_t len, size_t * n_read) {
-    unsigned char     ch;
-    unsigned char     end_ch;
-    size_t            i;
-    bool              error;
-    size_t            b_read;
-    evhtp_j_arr_state state;
-    evhtp_json      * js;
-
-
-    if (!data || !len || *data != '[') {
-        /* *n_read = 0; */
-        return NULL;
-    }
-
-    data++;
-    len--;
-
-    js     = j_array_new_();
-    state  = evhtp_j_arr_s_val;
-    error  = false;
-    b_read = 0;
-    end_ch = 0;
-
-    for (i = 0; i < len; i++) {
-        evhtp_json * val;
-
-        ch = data[i];
-
-        if (isspace(ch)) {
-            continue;
-        }
-
-        switch (state) {
-            case evhtp_j_arr_s_val:
-                if (ch == ']') {
-                    end_ch = ch;
-                    state  = evhtp_j_arr_s_end;
-                    break;
-                }
-
-                if (!(val = evhtp_json_parse_value(&data[i], (len - i), &b_read))) {
-                    error = true;
-                    goto end;
-                }
-
-                i     += b_read;
-                b_read = 0;
-
-                j_array_add(js, val);
-
-                state  = evhtp_j_arr_s_comma;
-
-                if ((i + 1) == len) {
-                    end_ch = data[i];
-                }
-
-                break;
-            case evhtp_j_arr_s_comma:
-                switch (ch) {
-                    case ',':
-                        state  = evhtp_j_arr_s_val;
-                        break;
-                    case ']':
-                        end_ch = ch;
-                        state  = evhtp_j_arr_s_end;
-                        break;
-                    default:
-                        error  = true;
-                        goto end;
-                }
-                break;
-            case evhtp_j_arr_s_end:
-                goto end;
-        } /* switch */
-    }
-end:
-    *n_read += i;
-
-    if ((end_ch != ']' || error == true)) {
-        evhtp_safe_free(js, evhtp_json_free);
-        return NULL;
-    }
-
-    return js;
-} /* evhtp_json_parse_array */
-
-evhtp_json *
-evhtp_json_parse_object(const char * data, size_t len, size_t * n_read) {
-    unsigned char     ch;
-    unsigned char     end_ch;
-    size_t            i;
-    evhtp_json      * js;
-    evhtp_json      * key;
-    evhtp_json      * val;
-    evhtp_j_obj_state state;
-    bool              error;
-    size_t            b_read;
-
-    if (*data != '{') {
-        /* *n_read = 0; */
-        return NULL;
-    }
-
-    state  = evhtp_j_obj_s_key;
-    js     = j_object_new_();
-    key    = NULL;
-    val    = NULL;
-    error  = false;
-    b_read = 0;
-    end_ch = 0;
-
-    data++;
-    len--;
-
-    for (i = 0; i < len; i++) {
-        ch = data[i];
-
-        if (isspace(ch)) {
-            continue;
-        }
-
-        switch (state) {
-            case evhtp_j_obj_s_key:
-                if (ch == '}') {
-                    end_ch = ch;
-                    state  = evhtp_j_obj_s_end;
-                    break;
-                }
-
-                if (!(key = evhtp_json_parse_key(&data[i], (len - i), &b_read))) {
-                    error = true;
-                    i    += b_read;
-                    goto end;
-                }
-
-                i     += b_read;
-                b_read = 0;
-                state  = evhtp_j_obj_s_delim;
-                break;
-            case evhtp_j_obj_s_delim:
-                if (ch != ':') {
-                    error = true;
-                    goto end;
-                }
-
-                state = evhtp_j_obj_s_val;
-                break;
-
-            case evhtp_j_obj_s_val:
-                if (!(val = evhtp_json_parse_value(&data[i], (len - i), &b_read))) {
-                    error = true;
-                    i    += b_read;
-                    goto end;
-                }
-
-                i     += b_read;
-                b_read = 0;
-
-                j_object_add_(js, key->string, val);
-
-                evhtp_safe_free(key, evhtp_json_free);
-
-                key   = NULL;
-                state = evhtp_j_obj_s_comma;
-
-                break;
-
-            case evhtp_j_obj_s_comma:
-                switch (ch) {
-                    case ',':
-                        state  = evhtp_j_obj_s_key;
-                        break;
-                    case '}':
-                        end_ch = ch;
-                        state  = evhtp_j_obj_s_end;
-                        break;
-                    default:
-                        error  = true;
-                        goto end;
-                }
-                break;
-            case evhtp_j_obj_s_end:
-                goto end;
-        } /* switch */
-    }
-
-end:
-    *n_read += i;
-
-    evhtp_safe_free(key, evhtp_json_free);
-
-    if ((end_ch != '}' || error == true)) {
-        evhtp_safe_free(js, evhtp_json_free);
-        return NULL;
-    }
-
-    return js;
-} /* evhtp_json_parse_object */
-
-evhtp_json *
-evhtp_json_parse_buf(const char * data, size_t len, size_t * n_read) {
-    unsigned char ch;
-    size_t        b_read;
-    size_t        i;
-    evhtp_json  * js;
-    evhtp_j_state state;
-
-    js     = NULL;
-    b_read = 0;
-    state  = evhtp_j_s_start;
-
-    for (i = 0; i < len; i++) {
-        ch = data[i];
-
-        if (isspace(ch)) {
-            continue;
-        }
-
-        switch (state) {
-            case evhtp_j_s_start:
-                switch (ch) {
-                    case '{':
-                        if (!(js = evhtp_json_parse_object(&data[i], (len - i), &b_read))) {
-                            *n_read += b_read;
-                            return NULL;
-                        }
-
-                        i     += b_read;
-                        b_read = 0;
-                        break;
-                    case '[':
-                        if (!(js = evhtp_json_parse_array(&data[i], (len - i), &b_read))) {
-                            *n_read += b_read;
-                            return NULL;
-                        }
-
-                        i       += b_read;
-                        b_read   = 0;
-                        break;
-                    default:
-                        *n_read += i;
-                        return NULL;
-                } /* switch */
-
-                state = evhtp_j_s_end;
-                break;
-            case evhtp_j_s_end:
-                break;
-        }         /* switch */
-    }
-
-    *n_read += i;
-
-    return js;
-}         /* evhtp_json_parse_buf */
-
-evhtp_json *
-evhtp_json_parse_file(const char * filename, size_t * bytes_read) {
-    evhtp_json * json   = NULL;
-    FILE       * fp     = NULL;
-    char       * buf    = NULL;
-    size_t       n_read = 0;
-    long         file_size;
-
-    if (filename == NULL) {
-        return NULL;
-    }
-
-    do {
-        if (!(fp = fopen(filename, "re"))) {
-            break;
-        }
-
-        if (fseek(fp, 0L, SEEK_END) == -1) {
-            break;
-        }
-
-        if ((file_size = ftell(fp)) == -1) {
-            break;
-        }
-
-        if (fseek(fp, 0L, SEEK_SET) == -1) {
-            break;
-        }
-
-        /* allocate 1 more than the size, just incase there is not an EOL
-         * terminator in the file.
-         */
-        if (!(buf = calloc(file_size + 1, 1))) {
-            break;
-        }
-
-        if (fread(buf, 1, file_size, fp) != file_size) {
-            break;
-        }
-
-        if (buf[file_size] == 0) {
-            /* just make sure we have SOME type of EOL terminator by placing a
-             * \n in it. */
-            buf[file_size] = '\n';
-            file_size     += 1;
-        }
-
-        if (!(json = evhtp_json_parse_buf(buf, file_size, &n_read))) {
-            break;
-        }
-    } while (0);
-
-    if (fp != NULL) {
-        fclose(fp);
-    }
-
-    *bytes_read = n_read;
-
-    evhtp_safe_free(buf, free);
-    return json;
-} /* evhtp_json_parse_file */
-
-void
-evhtp_json_free(evhtp_json * js) {
-    if (js == NULL) {
-        return;
-    }
-
-    switch (j_type_(js)) {
-        case evhtp_json_vtype_string:
-            evhtp_safe_free(js->string, free);
-            break;
-        case evhtp_json_vtype_object:
-            evhtp_safe_free(js->object, evhtp_kvmap_free);
-            break;
-        case evhtp_json_vtype_array:
-            evhtp_safe_free(js->array, evhtp_tailq_free);
-            break;
-        default:
-            break;
-    }
-
-    evhtp_heap_free(__js_heap, js);
-}
-
-static evhtp_json *
-j_array_index_(evhtp_json * array, int offset) {
-    evhtp_tailq * list;
-
-    if (!(list = evhtp_json_get_array(array))) {
-        return NULL;
-    }
-
-    return (evhtp_json *)evhtp_tailq_get_at_index(list, offset);
-}
-
-enum path_state {
-    path_state_reading_key,
-    path_state_reading_array,
-    path_state_reading_array_end
-};
-
-
-evhtp_json *
-evhtp_json_get_array_index(evhtp_json * array, int offset) {
-    if (evhtp_unlikely(array == NULL || offset < 0)) {
-        return NULL;
-    }
-
-    return j_array_index_(array, offset);
-}
-
-evhtp_json *
-evhtp_json_path_get(evhtp_json * js, const char * path) {
-    char            buf[strlen(path) + 1];
-    int             buf_idx;
-    evhtp_kvmap   * object;
-    evhtp_json    * prev;
-    unsigned char   ch;
-    size_t          i;
-    enum path_state state;
-
-
-    if (evhtp_unlikely(js == NULL || path == NULL)) {
-        return NULL;
-    }
-
-    prev    = js;
-    object  = NULL;
-    buf_idx = 0;
-    buf[0]  = '\0';
-    state   = path_state_reading_key;
-
-    for (i = 0; i < strlen(path) + 1; i++) {
-        ch = path[i];
-
-        switch (state) {
-            case path_state_reading_key:
-                switch (ch) {
-                    case '[':
-                        state = path_state_reading_array;
-                        break;
-                    case '\0':
-                    case '.':
-                        if (!(object = evhtp_json_get_object(prev))) {
-                            return NULL;
-                        }
-
-                        if (!(prev = evhtp_kvmap_find(object, buf))) {
-                            return NULL;
-                        }
-
-                        buf[0]         = '\0';
-                        buf_idx        = 0;
-                        break;
-                    default:
-                        buf[buf_idx++] = ch;
-                        buf[buf_idx]   = '\0';
-                        break;
-                } /* switch */
-                break;
-            case path_state_reading_array:
-                switch (ch) {
-                    case ']':
-                        if (!(prev = j_array_index_(prev, evhtp_atoi(buf, buf_idx)))) {
-                            return NULL;
-                        }
-
-                        buf[0]         = '\0';
-                        buf_idx        = 0;
-
-                        state          = path_state_reading_array_end;
-                        break;
-                    default:
-                        buf[buf_idx++] = ch;
-                        buf[buf_idx]   = '\0';
-                        break;
-                }
-                break;
-            case path_state_reading_array_end:
-                state = path_state_reading_key;
-                break;
-        } /* switch */
-
-        if (ch == '\0') {
-            break;
-        }
-    }
-
-    return (prev != js) ? prev : NULL;
-} /* evhtp_json_path_get */
-
-evhtp_json *
-evhtp_json_new_object(void) {
-    return j_object_new_();
-}
-
-evhtp_json *
-evhtp_json_new_array(void) {
-    return j_array_new_();
-}
-
-evhtp_json *
-evhtp_json_string_new(const char * str) {
-    return j_string_new_(str, str ? strlen(str) : 0);
-}
-
-evhtp_json *
-evhtp_json_string_new_len(const char * str, size_t size) {
-    return j_string_new_(str, size);
-}
-
-evhtp_json *
-evhtp_json_number_new(unsigned int num) {
-    return j_number_new_(num);
-}
-
-evhtp_json *
-evhtp_json_boolean_new(bool boolean) {
-    return j_boolean_new_(boolean);
-}
-
-evhtp_json *
-evhtp_json_null_new(void) {
-    return j_null_new_();
-}
-
-int
-evhtp_json_object_add(evhtp_json * obj, const char * key, evhtp_json * val) {
-    if (!obj || !key || !val) {
-        return -1;
-    }
-
-    return j_object_add_(obj, key, val);
-}
-
-inline int
-evhtp_json_object_add_klen(evhtp_json * obj, const char * k, size_t klen, evhtp_json * v) {
-    if (evhtp_unlikely(obj == NULL)) {
-        return -1;
-    }
-
-    return j_object_add_klen(obj, k, klen, v);
-}
-
-int
-evhtp_json_array_add(evhtp_json * array, evhtp_json * val) {
-    return j_array_add(array, val);
-}
-
-int
-evhtp_json_add(evhtp_json * obj, const char * key, evhtp_json * val) {
-    if (!obj) {
-        return -1;
-    }
-
-    if (key == NULL) {
-        if (j_type_(obj) != evhtp_json_vtype_array) {
-            return -1;
-        }
-
-        return evhtp_json_array_add(obj, val);
-    }
-
-    return evhtp_json_object_add(obj, key, val);
-}
-
-struct __jbuf {
-    char  * buf;
-    size_t  buf_idx;
-    size_t  buf_len;
-    ssize_t written;
-    int     dynamic;
-    bool    escape;
-};
-
-static int
-j_addbuf_(struct __jbuf * jbuf, const char * buf, size_t len) {
-    evhtp_assert(jbuf != NULL);
-
-    if (len == 0 || buf == NULL) {
-        return 0;
-    }
-
-    if ((jbuf->buf_idx + len) > jbuf->buf_len) {
-        if (evhtp_unlikely(jbuf->dynamic == 1)) {
-            char * n_buf;
-
-            jbuf->buf      = realloc(jbuf->buf, (size_t)(jbuf->buf_len + len + 32));
-            evhtp_alloc_assert(jbuf->buf);
-
-            jbuf->buf_len += len + 32;
-        } else {
-            return -1;
-        }
-    }
-
-    memcpy(&jbuf->buf[jbuf->buf_idx], buf, len);
-
-    jbuf->buf_idx += len;
-    jbuf->written += len;
-
-    return 0;
-}
-
-static int
-j_addbuf_vprintf_(struct __jbuf * jbuf, const char * fmt, va_list ap) {
-    char tmpbuf[jbuf->buf_len - jbuf->buf_idx];
-    int  sres;
-
-    evhtp_assert(jbuf != NULL);
-
-    sres = vsnprintf(tmpbuf, sizeof(tmpbuf), fmt, ap);
-
-    if (sres >= sizeof(tmpbuf) || sres < 0) {
-        return -1;
-    }
-
-    return j_addbuf_(jbuf, tmpbuf, (size_t)sres);
-}
-
-static int
-j_addbuf_printf_(struct __jbuf * jbuf, const char * fmt, ...) {
-    va_list ap;
-    int     sres;
-
-    evhtp_assert(jbuf != NULL);
-
-    va_start(ap, fmt);
-    {
-        sres = j_addbuf_vprintf_j(jbuf, fmt, ap);
-    }
-    va_end(ap);
-
-    return sres;
-}
-
-static const char digits[] =
-    "0001020304050607080910111213141516171819"
-    "2021222324252627282930313233343536373839"
-    "4041424344454647484950515253545556575859"
-    "6061626364656667686970717273747576777879"
-    "8081828384858687888990919293949596979899";
-
-static int
-j_addbuf_number_(struct __jbuf * jbuf, unsigned int num) {
-    char     buf[32]; /* 18446744073709551615 64b, 20 characters */
-    char   * buffer          = (char *)buf;
-    char   * buffer_end      = buffer + 32;
-    char   * buffer_end_save = buffer + 32;
-    unsigned index;
-
-    evhtp_assert(jbuf != NULL);
-
-    *--buffer_end = '\0';
-
-    while (num >= 100) {
-        index         = (num % 100) * 2;
-
-        num          /= 100;
-
-        *--buffer_end = digits[index + 1];
-        *--buffer_end = digits[index];
-    }
-
-    if (num < 10) {
-        *--buffer_end = (char)('0' + num);
-    } else {
-        index         = (unsigned)(num * 2);
-
-        *--buffer_end = digits[index + 1];
-        *--buffer_end = digits[index];
-    }
-
-    return j_addbuf_(jbuf, buffer_end, (size_t)(buffer_end_save - buffer_end - 1));
-}
-
-static int j_array_to_buffer__(evhtp_json * json, struct __jbuf * jbuf);
-static int j_number_to_buffer__(evhtp_json * json, struct __jbuf * jbuf);
-static int j_object_to_buffer__(evhtp_json * json, struct __jbuf * jbuf);
-
-static int
-j_number_to_buffer_(evhtp_json * json, struct __jbuf * jbuf) {
-    if (evhtp_likely(j_type_(json) != evhtp_json_vtype_number)) {
-        return -1;
-    } else {
-        return addbuf__number(jbuf, json->number);
-    }
-}
-
-static int
-j_escape_string_(const char * str, size_t len, struct __jbuf * jbuf) {
-    unsigned char ch;
-    size_t        i;
-
-    evhtp_assert(jbuf != NULL);
-
-    if (evhtp_unlikely(str == NULL)) {
-        return -1;
-    }
-
-    for (i = 0; i < len; i++) {
-        ch = str[i];
-
-        switch (ch) {
-            default:
-                if (evhtp_unlikely(addbuf_(jbuf, (const char *)&ch, 1) == -1)) {
-                    return -1;
-                }
-                break;
-            case '\n':
-                if (evhtp_unlikely(addbuf_(jbuf, "\\n", 2) == -1)) {
-                    return -1;
-                }
-                break;
-            case '"':
-                if (evhtp_unlikely(addbuf_(jbuf, "\\\"", 2) == -1)) {
-                    return -1;
-                }
-                break;
-            case '\t':
-                if (evhtp_unlikely(addbuf_(jbuf, "\\t", 2) == -1)) {
-                    return -1;
-                }
-                break;
-            case '\r':
-                if (evhtp_unlikely(addbuf_(jbuf, "\\r", 2) == -1)) {
-                    return -1;
-                }
-                break;
-            case '\\':
-                if (evhtp_unlikely(addbuf_(jbuf, "\\\\", 2) == -1)) {
-                    return -1;
-                }
-                break;
-        } /* switch */
-    }
-
-    return 0;
-}         /* j_escape_string */
-
-static int
-j_string_to_buffer_(evhtp_json * json, struct __jbuf * jbuf) {
-    const char * str;
-
-    if (j_type_(json) != evhtp_json_vtype_string) {
-        return -1;
-    }
-
-    str = json->string;
-
-    if (evhtp_unlikely(str == NULL)) {
-        return -1;
-    }
-
-    if (evhtp_unlikely(j_addbuf_(jbuf, "\"", 1) == -1)) {
-        return -1;
-    }
-
-    if (jbuf->escape == true) {
-        if (evhtp_unlikely(j_escape_string_(str, json->slen, jbuf) == -1)) {
-            return -1;
-        }
-    }
-
-    return j_addbuf_(jbuf, "\"", 1);
-}
-
-static int
-j_boolean_to_buffer_(evhtp_json * json, struct __jbuf * jbuf) {
-    if (j_type_(json) != evhtp_json_vtype_bool) {
-        return -1;
-    }
-
-    return j_addbuf_printf_(jbuf, "%s",
-                            evhtp_json_get_boolean(json) == true ? "true" : "false");
-}
-
-static int
-j_null_to_buffer_(evhtp_json * json, struct __jbuf * jbuf) {
-    if (j_type_(json) != evhtp_json_vtype_null) {
-        return -1;
-    }
-
-    return addbuf__printf(jbuf, "null");
-}
-
-static int
-j_to_buffer(evhtp_json * json, struct __jbuf * jbuf) {
-    switch (j_type_(json)) {
-        case evhtp_json_vtype_number:
-            return j_number_to_buffer_(json, jbuf);
-        case evhtp_json_vtype_array:
-            return j_array_to_buffer_(json, jbuf);
-        case evhtp_json_vtype_object:
-            return j_object_to_buffer_(json, jbuf);
-        case evhtp_json_vtype_string:
-            return j_string_to_buffer_(json, jbuf);
-        case evhtp_json_vtype_bool:
-            return j_boolean_to_buffer_(json, jbuf);
-        case evhtp_json_vtype_null:
-            return j_null_to_buffer_(json, jbuf);
-        default:
-            return -1;
-    }
-
-    return 0;
-}
-
-static int
-j_array_to_buffer_(evhtp_json * json, struct __jbuf * jbuf) {
-    evhtp_tailq      * array;
-    evhtp_tailq_elem * elem;
-    evhtp_tailq_elem * temp;
-
-    if (j_type_(json) != evhtp_json_vtype_array) {
-        return -1;
-    }
-
-    array = json->array;
-
-    if (evhtp_unlikely(addbuf_(jbuf, "[", 1) == -1)) {
-        return -1;
-    }
-
-    for (elem = evhtp_tailq_first(array); elem; elem = temp) {
-        evhtp_json * val;
-
-        val = (evhtp_json *)evhtp_tailq_elem_data(elem);
-        evhtp_assert(val != NULL);
-
-        if (evhtp_unlikely(j_to_buffer(val, jbuf) == -1)) {
-            return -1;
-        }
-
-        if ((temp = evhtp_tailq_next(elem))) {
-            if (evhtp_unlikely(addbuf_(jbuf, ",", 1) == -1)) {
-                return -1;
-            }
-        }
-    }
-
-    if (evhtp_unlikely(addbuf_(jbuf, "]", 1) == -1)) {
-        return -1;
-    }
-
-    return 0;
-}
-
-static int
-j_object_to_buffer_(evhtp_json * json, struct __jbuf * jbuf) {
-    evhtp_kvmap     * object;
-    evhtp_kvmap_ent * ent;
-    evhtp_kvmap_ent * temp;
-
-    if (j_type_(json) != evhtp_json_vtype_object) {
-        return -1;
-    }
-
-    object = json->object;
-
-    if (evhtp_unlikely(addbuf_(jbuf, "{", 1) == -1)) {
-        return -1;
-    }
-
-    for (ent = evhtp_kvmap_first(object); ent; ent = temp) {
-        const char * key;
-        evhtp_json * val;
-
-        key = evhtp_kvmap_ent_key(ent);
-        evhtp_assert(key != NULL);
-
-        val = (evhtp_json *)evhtp_kvmap_ent_val(ent);
-        evhtp_assert(val != NULL);
-
-        if (evhtp_unlikely(addbuf_(jbuf, "\"", 1) == -1)) {
-            return -1;
-        }
-
-        if (evhtp_unlikely(addbuf_(jbuf, key, evhtp_kvmap_ent_get_klen(ent)) == -1)) {
-            return -1;
-        }
-
-        if (evhtp_unlikely(addbuf_(jbuf, "\":", 2) == -1)) {
-            return -1;
-        }
-
-        if (evhtp_unlikely(j_to_buffer(val, jbuf) == -1)) {
-            return -1;
-        }
-
-        if ((temp = evhtp_kvmap_next(ent))) {
-            if (evhtp_unlikely(addbuf_(jbuf, ",", 1) == -1)) {
-                return -1;
-            }
-        }
-    }
-
-    if (evhtp_unlikely(addbuf_(jbuf, "}", 1) == -1)) {
-        return -1;
-    }
-
-    return 0;
-} /* j_object_to_buffer_ */
-
-ssize_t
-_evhtp_json_to_buffer(evhtp_json * json, char * buf, size_t buf_len, struct __jbuf * jbuf) {
-    if (evhtp_unlikely(!json || !buf)) {
-        return -1;
-    }
-
-    if (evhtp_unlikely(j_to_buffer(json, jbuf) == -1)) {
-        return -1;
-    }
-
-    return jbuf->written;
-}
-
-ssize_t
-evhtp_json_to_buffer(evhtp_json * json, char * buf, size_t buf_len) {
-    struct __jbuf jbuf = {
-        .buf     = buf,
-        .buf_idx = 0,
-        .written = 0,
-        .buf_len = buf_len,
-        .dynamic = 0,
-        .escape  = true
-    };
-
-    if (evhtp_unlikely(j_to_buffer(json, &jbuf) == -1)) {
-        return -1;
-    }
-
-    return jbuf.written;
-}
-
-ssize_t
-evhtp_json_to_buffer_nescp(evhtp_json * json, char * buf, size_t buf_len) {
-    struct __jbuf jbuf = {
-        .buf     = buf,
-        .buf_idx = 0,
-        .written = 0,
-        .buf_len = buf_len,
-        .dynamic = 0,
-        .escape  = false
-    };
-
-    if (evhtp_unlikely(j_to_buffer(json, &jbuf) == -1)) {
-        return -1;
-    }
-
-    return jbuf.written;
-}
-
-char *
-evhtp_json_to_buffer_alloc(evhtp_json * json, size_t * len) {
-    struct __jbuf jbuf = {
-        .buf     = NULL,
-        .buf_idx = 0,
-        .written = 0,
-        .buf_len = 0,
-        .dynamic = 1,
-        .escape  = true
-    };
-
-    if (!json || !len) {
-        return NULL;
-    }
-
-    if (j_to_buffer(json, &jbuf) == -1) {
-        evhtp_safe_free(jbuf.buf, free);
-        return NULL;
-    }
-
-    *len = jbuf.written;
-
-    return jbuf.buf;
-}
-
-static inline int j_compare_(evhtp_json * j1, evhtp_json * j2, evhtp_json_key_filtercb cb);
-
-static inline int
-j_number_compare_(evhtp_json * j1, evhtp_json * j2, evhtp_json_key_filtercb cb) {
-    if (j1 == NULL || j2 == NULL) {
-        return -1;
-    }
-
-    if (j_type_(j1) != evhtp_json_vtype_number) {
-        return -1;
-    }
-
-    if (j_type_(j2) != evhtp_json_vtype_number) {
-        return -1;
-    }
-
-    if (evhtp_json_get_number(j1) != evhtp_json_get_number(j2)) {
-        return -1;
-    }
-
-    return 0;
-}
-
-static inline int
-j_array_compare_(evhtp_json * j1, evhtp_json * j2, evhtp_json_key_filtercb cb) {
-    evhtp_tailq      * j1_array;
-    evhtp_tailq      * j2_array;
-    evhtp_tailq_elem * elem;
-    evhtp_tailq_elem * temp;
-    int                idx;
-
-    if (j1 == NULL || j2 == NULL) {
-        return -1;
-    }
-
-    if (!(j1_array = evhtp_json_get_array(j1))) {
-        return -1;
-    }
-
-    if (!(j2_array = evhtp_json_get_array(j2))) {
-        return -1;
-    }
-
-    idx = 0;
-
-    for (elem = evhtp_tailq_first(j1_array); elem; elem = temp) {
-        evhtp_json * j1_val;
-        evhtp_json * j2_val;
-
-        j1_val = (evhtp_json *)evhtp_tailq_elem_data(elem);
-        j2_val = (evhtp_json *)evhtp_tailq_get_at_index(j2_array, idx);
-
-        if (j1_val && !j2_val) {
-            return -1;
-        }
-
-        if (j2_val && !j1_val) {
-            return -1;
-        }
-
-        if (j_compare_(j1_val, j2_val, cb) == -1) {
-            return -1;
-        }
-
-        idx += 1;
-
-        temp = evhtp_tailq_next(elem);
-    }
-
-    return 0;
-} /* j_array_compare_ */
-
-static int
-j_object_compare_(evhtp_json * j1, evhtp_json * j2, evhtp_json_key_filtercb cb) {
-    evhtp_kvmap     * j1_map;
-    evhtp_kvmap     * j2_map;
-    evhtp_kvmap_ent * ent;
-    evhtp_kvmap_ent * temp;
-
-    if (j1 == NULL || j2 == NULL) {
-        return -1;
-    }
-
-    if (!(j1_map = evhtp_json_get_object(j1))) {
-        return -1;
-    }
-
-    if (!(j2_map = evhtp_json_get_object(j2))) {
-        return -1;
-    }
-
-    for (ent = evhtp_kvmap_first(j1_map); ent; ent = temp) {
-        const char * key;
-        evhtp_json * j1_val;
-        evhtp_json * j2_val;
-
-        if (!(key = evhtp_kvmap_ent_key(ent))) {
-            return -1;
-        }
-
-        if (!(j1_val = (evhtp_json *)evhtp_kvmap_ent_val(ent))) {
-            return -1;
-        }
-
-        if (cb && (cb)(key, j1_val) == 1) {
-            /* the key filter callback returned 1, which means we can ignore the
-             * comparison of this field.
-             */
-            temp = evhtp_kvmap_next(ent);
-            continue;
-        }
-
-        if (!(j2_val = (evhtp_json *)evhtp_kvmap_find(j2_map, key))) {
-            return -1;
-        }
-
-        if (j_compare_(j1_val, j2_val, cb) == -1) {
-            return -1;
-        }
-
-        temp = evhtp_kvmap_next(ent);
-    }
-
-    return 0;
-} /* j_object_compare_ */
-
-static int
-j_string_compare_(evhtp_json * j1, evhtp_json * j2, evhtp_json_key_filtercb cb) {
-    const char * j1_str;
-    const char * j2_str;
-
-    if (!(j1_str = evhtp_json_get_string(j1))) {
-        return -1;
-    }
-
-    if (!(j2_str = evhtp_json_get_string(j2))) {
-        return -1;
-    }
-
-    if (strcmp(j1_str, j2_str)) {
-        return -1;
-    }
-
-    return 0;
-}
-
-static int
-j_boolean_compare_(evhtp_json * j1, evhtp_json * j2, evhtp_json_key_filtercb cb) {
-    if (!j1 || !j2) {
-        return -1;
-    }
-
-    if (j_type_(j1) != evhtp_json_vtype_bool) {
-        return -1;
-    }
-
-    if (j_type_(j2) != evhtp_json_vtype_bool) {
-        return -1;
-    }
-
-    if (evhtp_json_get_boolean(j1) != evhtp_json_get_boolean(j2)) {
-        return -1;
-    }
-
-    return 0;
-}
-
-static int
-j_null_compare_(evhtp_json            * j1,
-                evhtp_json            * j2,
-                evhtp_json_key_filtercb cb) {
-    if (j1 == NULL || j2 == NULL) {
-        return -1;
-    }
-
-    if (j_type_(j1) != evhtp_json_vtype_null
-        || j_type_(j2) != evhtp_json_vtype_null) {
-        return -1;
-    }
-
-    return 0;
-}
-
-static int
-j_compare_(evhtp_json * j1, evhtp_json * j2, evhtp_json_key_filtercb cb) {
-    if (j1 == NULL || j2 == NULL) {
-        return -1;
-    }
-
-    if (j_type_(j1) != j_type_(j2)) {
-        return -1;
-    }
-
-    if (evhtp_json_get_size(j1) != evhtp_json_get_size(j2)) {
-        return -1;
-    }
-
-    switch (j_type_(j1)) {
-        case evhtp_json_vtype_number:
-            return j_number_compare_(j1, j2, cb);
-        case evhtp_json_vtype_array:
-            return j_array_compare_(j1, j2, cb);
-        case evhtp_json_vtype_object:
-            return j_object_compare_(j1, j2, cb);
-        case evhtp_json_vtype_string:
-            return j_string_compare_(j1, j2, cb);
-        case evhtp_json_vtype_bool:
-            return j_boolean_compare_(j1, j2, cb);
-        case evhtp_json_vtype_null:
-            return j_null_compare_(j2, j2, cb);
-        default:
-            return -1;
-    }
-
-    return 0;
-}
-
-int
-evhtp_json_compare(evhtp_json            * j1,
-                   evhtp_json            * j2,
-                   evhtp_json_key_filtercb cb) {
-    return j_compare_(j1, j2, cb);
-}
-
diff --git a/evhtp_json.h b/evhtp_json.h
deleted file mode 100644
index f1143c4..0000000
--- a/evhtp_json.h
+++ /dev/null
@@ -1,345 +0,0 @@
-#ifndef __EVHTP_JSON_H__
-#define __EVHTP_JSON_H__
-
-enum evhtp_json_vtype_e {
-    evhtp_json_vtype_string = 0,
-    evhtp_json_vtype_number,
-    evhtp_json_vtype_object,
-    evhtp_json_vtype_array,
-    evhtp_json_vtype_bool,
-    evhtp_json_vtype_null
-};
-
-struct evhtp_json_s;
-
-typedef enum evhtp_json_vtype_e evhtp_json_vtype;
-typedef struct evhtp_json_s     evhtp_json;
-
-typedef int (* evhtp_json_key_filtercb)(const char * key, evhtp_json * val);
-
-
-/**
- * @brief creates a new unordered-keyval context
- *
- * @return evhtp_json context with a vtype of 'evhtp_json_vtype_object'
- */
-EVHTP_EXPORT evhtp_json * evhtp_json_new_object(void);
-
-
-/**
- * @brief creates a new ordered array of evhtp_json context values
- *
- * @return evhtp_json context with a vtype of 'evhtp_json_vtype_array'
- */
-EVHTP_EXPORT evhtp_json * evhtp_json_new_array(void);
-
-
-/**
- * @brief frees data associated with a evhtp_json context. Objects and arrays
- *        will free all the resources contained within in a recursive manner.
- *
- * @param js
- */
-EVHTP_EXPORT void evhtp_json_free(evhtp_json * js);
-
-/**
- * @brief creates a evhtp_json context for a null terminated string
- *        and copies the original string
- *
- * @param str
- *
- * @return evhtp_json context with vtype of 'evhtp_json_vtype_string'
- */
-EVHTP_EXPORT evhtp_json * evhtp_json_string_new(const char * str);
-
-
-/**
- * @brief a variant of evhtp_json_string_new which can be faster if you
- *          already know the length.
- *
- * @param str
- * @param len length of the string
- *
- * @return
- */
-EVHTP_EXPORT evhtp_json * evhtp_json_string_new_len(const char * str, size_t len);
-
-
-/**
- * @brief creates a evhtp_json context for a number. Note: this only supports
- *        unsigned int right now (casted for signed).
- *
- * @param num
- *
- * @return evhtp_json context with vtype of 'evhtp_json_vtype_number'
- */
-EVHTP_EXPORT evhtp_json * evhtp_json_number_new(unsigned int num);
-
-
-/**
- * @brief creates a evhtp_json context for a boolean value.
- *
- * @param boolean either true or false
- *
- * @return evhtp_json context with vtype of 'evhtp_json_vtype_bool'
- */
-EVHTP_EXPORT evhtp_json * evhtp_json_boolean_new(bool boolean);
-
-
-/**
- * @brief creates a evhtp_json context for a null value
- *
- * @return evhtp_json context with vtype of 'evhtp_json_vtype_null'
- */
-EVHTP_EXPORT evhtp_json * evhtp_json_null_new(void);
-
-/**
- * @brief parse a buffer containing raw json and convert it to the
- *        internal evhtp_json.
- *
- * @param data the buffer to parse
- * @param len the length of the data in the buffer
- * @param n_read the number of bytes which were parsed will be stored
- *        here.
- *
- * @return evhtp_json context if valid json, NULL on error (also see n_read above)
- */
-EVHTP_EXPORT evhtp_json * evhtp_json_parse_buf(const char * data, size_t len, size_t * n_read);
-
-/**
- * @brief wrapper around evhtp_json_parse_buf but opens, reads, parses, and closes
- *        a file with JSON data.
- *
- * @param filename
- * @param n_read number of bytes parsed
- *
- * @return see evhtp_json_parse_buf
- */
-EVHTP_EXPORT evhtp_json * evhtp_json_parse_file(const char * filename, size_t * n_read);
-
-/* these next set of parser functions are self explainatory, and will probably be
- * made private in the future.
- */
-EVHTP_EXPORT evhtp_json * evhtp_json_parse_object(const char * data, size_t len, size_t * n_read);
-EVHTP_EXPORT evhtp_json * evhtp_json_parse_array(const char * data, size_t len, size_t * n_read);
-EVHTP_EXPORT evhtp_json * evhtp_json_parse_value(const char * data, size_t len, size_t * n_read);
-EVHTP_EXPORT evhtp_json * evhtp_json_parse_string(const char * data, size_t len, size_t * n_read);
-EVHTP_EXPORT evhtp_json * evhtp_json_parse_number(const char * data, size_t len, size_t * n_read);
-EVHTP_EXPORT evhtp_json * evhtp_json_parse_key(const char * data, size_t len, size_t * n_read);
-EVHTP_EXPORT evhtp_json * evhtp_json_parse_null(const char * data, size_t len, size_t * n_read);
-EVHTP_EXPORT evhtp_json * evhtp_json_parse_boolean(const char * data, size_t len, size_t * n_read);
-
-/**
- * @brief returns the underlying type of the evhtp_json context
- *
- * @param js
- *
- * @return
- */
-EVHTP_EXPORT evhtp_json_vtype evhtp_json_get_type(evhtp_json * js);
-
-
-/**
- * @brief returns the underlying evhtp_kvmap ADT for an object
- *
- * @param js
- *
- * @return evhtp_kvmap on success, NULL if the underlying data
- *         is not an object.
- */
-EVHTP_EXPORT evhtp_kvmap * evhtp_json_get_object(evhtp_json * js);
-
-/**
- * @brief returns the underlying evhtp_tailq ADT for an array
- *
- * @param js
- *
- * @return evhtp_tailq on success, NULL if the underlying data is
- *         not an array.
- */
-EVHTP_EXPORT evhtp_tailq * evhtp_json_get_array(evhtp_json * js);
-
-
-/**
- * @brief fetches the evhtp_json value in an array at a specific index
- *
- * @param js
- * @param index
- *
- * @return the evhtp_json value, NULL if not found
- */
-EVHTP_EXPORT evhtp_json * evhtp_json_get_array_index(evhtp_json * js, int index);
-
-
-/**
- * @brief return the underlying number
- *
- * @param js
- *
- * @return
- */
-EVHTP_EXPORT unsigned int evhtp_json_get_number(evhtp_json * js);
-
-
-/**
- * @brief fetches the underlying string of the evhtp_json context
- *
- * @param js
- *
- * @return the string on success, NULL if underlying data is not a string
- */
-EVHTP_EXPORT const char * evhtp_json_get_string(evhtp_json * js);
-
-
-/**
- * @brief boolean fetch
- *
- * @param js
- *
- * @return true or false
- */
-EVHTP_EXPORT bool evhtp_json_get_boolean(evhtp_json * js);
-
-
-/**
- * @brief null fetch
- *
- * @param js
- *
- * @return 1 if null, -1 if underlying data is not a null
- */
-EVHTP_EXPORT char evhtp_json_get_null(evhtp_json * js);
-
-
-/**
- * @brief size fetch of underlying evhtp_json data:
- *          evhtp_json_vtype_string : length of the string
- *          evhtp_json_vtype_array  : the number of entries in the array
- *          evhtp_json_vtype_object : number of entries in the object
- *
- * @param js
- *
- * @return 0 if the underlying type doesn't have a size, otherwise see above
- */
-EVHTP_EXPORT ssize_t evhtp_json_get_size(evhtp_json * js);
-
-
-/**
- * @brieffetch evhtp_json data using a special syntax
- *
- *        if the json is { "a" : 1, "b" : [1, 2, 3, { "foo": "bar" }], "c" : {"hi" : null} }
- *
- *        and you would like to get the second element of the key "b" the syntax would be:
- *           "b.[2]"
- *
- *        or to get the value of "foo" in this example:
- *           "b.[4].foo"
- *
- * @param js
- * @param path
- *
- * @return
- */
-EVHTP_EXPORT evhtp_json * evhtp_json_path_get(evhtp_json * js, const char * path);
-
-
-/**
- * @brief add a string : evhtp_json context to an existing evhtp_json object
- *
- * @param obj
- * @param key
- * @param val
- *
- * @return
- */
-EVHTP_EXPORT int evhtp_json_object_add(evhtp_json * obj, const char * key, evhtp_json * val);
-
-
-/**
- * @brief same as evhtp_json_object_add, except if the length of the key is known,
- *        you can reduce overhead
- *
- * @param o
- * @param k
- * @param kl
- * @param v
- *
- * @return
- */
-EVHTP_EXPORT int evhtp_json_object_add_klen(evhtp_json * o, const char * k, size_t kl, evhtp_json * v);
-
-
-/**
- * @brief add a evhtp_json context to a evhtp_json array context
- *
- * @param array
- * @param val
- *
- * @return
- */
-EVHTP_EXPORT int evhtp_json_array_add(evhtp_json * array, evhtp_json * val);
-
-
-/**
- * @brief can be used on either evhtp_json arrays or objects. For arrays, just omit the key
- *
- * @param obj
- * @param k
- * @param val
- *
- * @return
- */
-EVHTP_EXPORT int evhtp_json_add(evhtp_json * obj, const char * k, evhtp_json * val);
-
-
-/**
- * @brief converts the evhtp_json ctx to a valid JSON string
- *
- * @param json
- * @param buf user supplied buffer
- * @param buf_len the length of the buffer
- *
- * @return number of bytes copied into the buffer
- */
-EVHTP_EXPORT ssize_t evhtp_json_to_buffer(evhtp_json * json, char * buf, size_t buf_len);
-
-
-/**
- * @brief same as evhtp_json_to_buffer but does not escape strings
- *
- * @param json
- * @param buf
- * @param buf_len
- *
- * @return
- */
-EVHTP_EXPORT ssize_t evhtp_json_to_buffer_nescp(evhtp_json * json, char * buf, size_t buf_len);
-
-
-/**
- * @brief converts to a malloc'd JSON string
- *
- * @param json
- * @param len
- *
- * @return
- */
-EVHTP_EXPORT char * evhtp_json_to_buffer_alloc(evhtp_json * json, size_t * len);
-
-
-/**
- * @brief compares two evhtp_json contexts to determine if they match, if the filtercb
- *        argument is not NULL, and the type being compared currently is an array or object,
- *        each ts_json context is passed to the callback. If the callback returns -1, that
- *        value will not be compared to the other.
- *
- * @param j1
- * @param j2
- * @param cb
- *
- * @return
- */
-EVHTP_EXPORT int evhtp_json_compare(evhtp_json * j1, evhtp_json * j2, evhtp_json_key_filtercb cb);
-
-#endif
-
diff --git a/examples/test.c b/examples/test.c
index 9eacad7..544898e 100644
--- a/examples/test.c
+++ b/examples/test.c
@@ -8,8 +8,8 @@
 #include <inttypes.h>
 #include <event2/event.h>
 
-#include "../evhtp-internal.h"
-#include "../evhtp.h"
+#include "internal.h"
+#include "evhtp/evhtp.h"
 
 
 #ifndef EVHTP_DISABLE_EVTHR
@@ -597,7 +597,7 @@
     evhtp_callback_set_hook(cb_6, evhtp_hook_on_headers, test_regex_hdrs_cb, NULL);
 #endif
 
-    evhtp_callback_set_hook(cb_10, evhtp_hook_on_headers, set_max_body, NULL); 
+    evhtp_callback_set_hook(cb_10, evhtp_hook_on_headers, set_max_body, NULL);
 
     /* set a default request handler */
     evhtp_set_gencb(htp, test_default_cb, "foobarbaz");
@@ -648,7 +648,7 @@
 
 #ifndef EVHTP_DISABLE_EVTHR
     if (use_threads) {
-        evhtp_use_threads(htp, NULL, num_threads, NULL);
+        evhtp_use_threads_wexit(htp, NULL, NULL, num_threads, NULL);
     }
 #endif
 
diff --git a/examples/test_basic.c b/examples/test_basic.c
index 96d02d5..63209a9 100644
--- a/examples/test_basic.c
+++ b/examples/test_basic.c
@@ -44,7 +44,7 @@
     evhtp_set_cb(htp, "/1/ping.json", testcb, "two");
     evhtp_set_cb(htp, "/issue161", issue161cb, NULL);
 #ifndef EVHTP_DISABLE_EVTHR
-    evhtp_use_threads(htp, NULL, 8, NULL);
+    evhtp_use_threads_wexit(htp, NULL, NULL, 8, NULL);
 #endif
     evhtp_bind_socket(htp, "0.0.0.0", 8081, 2048);
 
diff --git a/examples/test_client.c b/examples/test_client.c
index bf05058..c65ea29 100644
--- a/examples/test_client.c
+++ b/examples/test_client.c
@@ -7,40 +7,46 @@
 #include <evhtp.h>
 
 static void
-request_cb(evhtp_request_t * req, void * arg) {
+request_cb(evhtp_request_t * req, void * arg)
+{
     printf("hi %zu\n", evbuffer_get_length(req->buffer_in));
 }
 
 static evhtp_res
-print_data(evhtp_request_t * req, evbuf_t * buf, void * arg) {
+print_data(evhtp_request_t * req, evbuf_t * buf, void * arg)
+{
     printf("Got %zu bytes\n", evbuffer_get_length(buf));
 
     return EVHTP_RES_OK;
 }
 
 static evhtp_res
-print_new_chunk_len(evhtp_request_t * req, uint64_t len, void * arg) {
+print_new_chunk_len(evhtp_request_t * req, uint64_t len, void * arg)
+{
     printf("started new chunk, %" PRIu64 "  bytes\n", len);
 
     return EVHTP_RES_OK;
 }
 
 static evhtp_res
-print_chunk_complete(evhtp_request_t * req, void * arg) {
+print_chunk_complete(evhtp_request_t * req, void * arg)
+{
     printf("ended a single chunk\n");
 
     return EVHTP_RES_OK;
 }
 
 static evhtp_res
-print_chunks_complete(evhtp_request_t * req, void * arg) {
+print_chunks_complete(evhtp_request_t * req, void * arg)
+{
     printf("all chunks read\n");
 
     return EVHTP_RES_OK;
 }
 
 int
-main(int argc, char ** argv) {
+main(int argc, char ** argv)
+{
     evbase_t           * evbase;
     evhtp_connection_t * conn;
     evhtp_request_t    * request;
@@ -49,10 +55,10 @@
     conn    = evhtp_connection_new(evbase, "75.126.169.52", 80);
     request = evhtp_request_new(request_cb, evbase);
 
-    evhtp_set_hook(&request->hooks, evhtp_hook_on_read, print_data, evbase);
-    evhtp_set_hook(&request->hooks, evhtp_hook_on_new_chunk, print_new_chunk_len, NULL);
-    evhtp_set_hook(&request->hooks, evhtp_hook_on_chunk_complete, print_chunk_complete, NULL);
-    evhtp_set_hook(&request->hooks, evhtp_hook_on_chunks_complete, print_chunks_complete, NULL);
+    evhtp_request_set_hook(request, evhtp_hook_on_read, print_data, evbase);
+    evhtp_request_set_hook(request, evhtp_hook_on_new_chunk, print_new_chunk_len, NULL);
+    evhtp_request_set_hook(request, evhtp_hook_on_chunk_complete, print_chunk_complete, NULL);
+    evhtp_request_set_hook(request, evhtp_hook_on_chunks_complete, print_chunks_complete, NULL);
 
     evhtp_headers_add_header(request->headers_out,
                              evhtp_header_new("Host", "ieatfood.net", 0, 0));
@@ -68,4 +74,3 @@
 
     return 0;
 }
-
diff --git a/examples/test_perf.c b/examples/test_perf.c
index ea3d570..0abfd4c 100644
--- a/examples/test_perf.c
+++ b/examples/test_perf.c
@@ -7,8 +7,8 @@
 #include <signal.h>
 #include <inttypes.h>
 
-#include "../evhtp-internal.h"
-#include "../evhtp.h"
+#include "internal.h"
+#include "evhtp/evhtp.h"
 
 static int      num_threads  = 0;
 static char   * baddr        = "127.0.0.1";
@@ -112,7 +112,7 @@
 #ifndef EVHTP_DISABLE_EVTHR
         if (num_threads > 0)
         {
-            evhtp_assert(evhtp_use_threads(htp, NULL, num_threads, NULL) != -1);
+            evhtp_assert(evhtp_use_threads_wexit(htp, NULL, NULL, num_threads, NULL) != -1);
         }
 #endif
 
diff --git a/examples/test_proxy.c b/examples/test_proxy.c
index 6a0451c..daba6e5 100644
--- a/examples/test_proxy.c
+++ b/examples/test_proxy.c
@@ -115,7 +115,7 @@
 #endif
 #endif
 
-    evhtp_use_threads(evhtp, init_thread_cb, 8, NULL);
+    evhtp_use_threads_wexit(evhtp, init_thread_cb, NULL, 8, NULL);
 #ifndef WIN32
     ev_sigterm = evsignal_new(evbase, SIGTERM, sigterm_cb, evbase);
     evsignal_add(ev_sigterm, NULL);
diff --git a/include/evhtp.h b/include/evhtp.h
new file mode 100644
index 0000000..e457281
--- /dev/null
+++ b/include/evhtp.h
@@ -0,0 +1,7 @@
+#ifndef __EVHTP_BASE_H__
+#define __EVHTP_BASE_H__
+
+#include <evhtp/evhtp.h>
+
+#endif
+
diff --git a/evhtp-config.h.in b/include/evhtp/config.h.in
similarity index 100%
rename from evhtp-config.h.in
rename to include/evhtp/config.h.in
diff --git a/evhtp.h b/include/evhtp/evhtp.h
similarity index 99%
rename from evhtp.h
rename to include/evhtp/evhtp.h
index 835164b..44882fb 100644
--- a/evhtp.h
+++ b/include/evhtp/evhtp.h
@@ -1,14 +1,14 @@
-#include <evhtp-config.h>
+#include <evhtp/config.h>
 
 #ifndef __EVHTP__H__
 #define __EVHTP__H__
 
 /** @file */
 #ifndef EVHTP_DISABLE_EVTHR
-#include <evthr.h>
+#include <evhtp/thread.h>
 #endif
 
-#include <htparse.h>
+#include <evhtp/parser.h>
 
 #ifndef EVHTP_DISABLE_REGEX
 #include <onigposix.h>
@@ -202,7 +202,7 @@
 typedef void * (* evhtp_ssl_scache_init)(evhtp_t *);
 #endif
 
-#define EVHTP_VERSION           "1.2.12-pre3"
+#define EVHTP_VERSION           "1.2.12"
 #define EVHTP_VERSION_MAJOR     1
 #define EVHTP_VERSION_MINOR     2
 #define EVHTP_VERSION_PATCH     12
@@ -622,7 +622,7 @@
  *
  * @param htp
  */
-EVHTP_EXPORT void evhtp_disable_100_continue(evhtp_t * htp);
+EVHTP_EXPORT void evhtp_disable_100_continue(evhtp_t * htp)
 DEPRECATED("evhtp_disable_100 will soon be deprecated, use htp->flags instead");
 
 /**
@@ -781,7 +781,7 @@
  *
  * @return 0 on success, -1 on error (if hooks is NULL, it is allocated)
  */
-EVHTP_EXPORT int evhtp_set_hook(evhtp_hooks_t ** hooks, evhtp_hook_type type, evhtp_hook cb, void * arg);
+EVHTP_EXPORT int evhtp_set_hook(evhtp_hooks_t ** hooks, evhtp_hook_type type, evhtp_hook cb, void * arg)
 DEPRECATED("use evhtp_[connection|request|callback]_set_hook() instead of set_hook directly");
 
 EVHTP_EXPORT int evhtp_connection_set_hook(evhtp_connection_t * c, evhtp_hook_type type, evhtp_hook cb, void * arg);
diff --git a/htparse.h b/include/evhtp/parser.h
similarity index 98%
rename from htparse.h
rename to include/evhtp/parser.h
index da2fd53..0dc47d0 100644
--- a/htparse.h
+++ b/include/evhtp/parser.h
@@ -1,7 +1,7 @@
 #ifndef __HTPARSE_H__
 #define __HTPARSE_H__
 
-#include "evhtp-config.h"
+#include <evhtp/config.h>
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/evthr.h b/include/evhtp/thread.h
similarity index 97%
rename from evthr.h
rename to include/evhtp/thread.h
index f848d31..268e345 100644
--- a/evthr.h
+++ b/include/evhtp/thread.h
@@ -3,7 +3,7 @@
 
 #include <pthread.h>
 #include <event2/event.h>
-#include <evhtp-config.h>
+#include <evhtp/config.h>
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/evhtp-internal.h b/include/internal.h
similarity index 100%
rename from evhtp-internal.h
rename to include/internal.h
diff --git a/evhtp_numtoa.h b/include/numtoa.h
similarity index 96%
rename from evhtp_numtoa.h
rename to include/numtoa.h
index 21ace95..f5d7428 100644
--- a/evhtp_numtoa.h
+++ b/include/numtoa.h
@@ -5,7 +5,7 @@
 extern "C" {
 #endif
 
-#include "evhtp-config.h"
+#include "evhtp/config.h"
 
 /**
  * @brief based on the system architecture, convert a size_t
diff --git a/evhtp_numtoa.c b/numtoa.c
similarity index 95%
rename from evhtp_numtoa.c
rename to numtoa.c
index 05dd466..00544e5 100644
--- a/evhtp_numtoa.c
+++ b/numtoa.c
@@ -13,8 +13,8 @@
 #include <string.h>
 #include <stdint.h>
 
-#include "evhtp-internal.h"
-#include "evhtp_numtoa.h"
+#include "internal.h"
+#include "numtoa.h"
 
 static inline void
 strreverse(char * begin, char * end) {
diff --git a/htparse.c b/parser.c
similarity index 99%
rename from htparse.c
rename to parser.c
index 04ba01a..1974151 100644
--- a/htparse.c
+++ b/parser.c
@@ -8,8 +8,8 @@
 #include <ctype.h>
 #include <unistd.h>
 
-#include "htparse.h"
-#include "evhtp-internal.h"
+#include "evhtp/parser.h"
+#include "internal.h"
 
 #ifdef PARSER_DEBUG
 #define __QUOTE(x)                  # x
@@ -970,8 +970,6 @@
                 }
                 break;
             case s_port:
-                res = 0;
-
                 if (ch >= '0' && ch <= '9') {
                     p->buf[p->buf_idx++] = ch;
                     p->buf[p->buf_idx]   = '\0';
@@ -1607,7 +1605,6 @@
                 break;
             case s_hdrline_hdr_val:
                 err = 0;
-                res = 0;
 
                 do {
                     htparse_log_debug("[%p] s_hdrline_hdr_val", p);
@@ -1812,11 +1809,8 @@
             case s_hdrline_almost_done:
                 htparse_log_debug("[%p] s_hdrline_almost_done", p);
 
-                res = 0;
-
                 switch (ch) {
                     case LF:
-                        res = 0;
                         res = hook_on_hdrs_complete_run(p, hooks);
 
                         if (res != 0) {
@@ -1825,7 +1819,6 @@
                         }
 
                         p->buf_idx = 0;
-                        htparse_log_debug("[%p] HERE", p);
 
                         if (p->flags & parser_flag_trailing) {
                             res      = hook_on_msg_complete_run(p, hooks);
@@ -1866,7 +1859,6 @@
                 if (p->flags & parser_flag_trailing) {
                     res      = hook_on_msg_complete_run(p, hooks);
                     p->state = s_start;
-                    break;
                 } else if (p->flags & parser_flag_chunked) {
                     p->state = s_chunk_size_start;
                     i--;
@@ -1877,6 +1869,7 @@
                     res      = hook_on_msg_complete_run(p, hooks);
                     p->state = s_start;
                 }
+
                 if (res) {
                     p->error = htparse_error_user;
                     return i + 1;
@@ -1912,8 +1905,6 @@
                 break;
 
             case s_chunk_size_almost_done:
-                res = 0;
-
                 if (ch != LF) {
                     p->error = htparse_error_inval_chunk_sz;
                     return i + 1;
diff --git a/evthr.c b/thread.c
similarity index 99%
rename from evthr.c
rename to thread.c
index 64201a3..7873f73 100644
--- a/evthr.c
+++ b/thread.c
@@ -19,8 +19,8 @@
 #include <event2/event.h>
 #include <event2/thread.h>
 
-#include "evhtp-internal.h"
-#include "evthr.h"
+#include "internal.h"
+#include "evhtp/thread.h"
 
 typedef struct evthr_cmd        evthr_cmd_t;
 typedef struct evthr_pool_slist evthr_pool_slist_t;