Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
A more flexible replacement for libevent's http API.
C CMake Other

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.
CMakeModules
build
contrib
evthr
libhtparse
oniguruma
.gitignore
CMakeLists.txt
ChangeLog
Doxyfile
README
evhtp.c
evhtp.h
test.c
test2.c

README

v0.4.0
	- API fully documented via Doxygen

	- Major re-factoring:
			- evhtp_request_t, evhtp_connection_t evhtp_t are now exposed to the user

			- htparse_hooks are no longer tied to a evhtp_t, but are private
				globals (shouldn't ever be changed).

			- bufferevent operations now share a single set of callbacks with an
				evhtp_connection_t argument. This keeps things consistent.
					- evhtp_connection_readcb reads and parses requests
					- evhtp_connection_writecb determines if a response is completed
						and whether it should keep the connection alive or close it.

			- requests and connections can be paused and resumed.
					- if you pause a request, all further request parsing is stopped so
						that no further hooks are called until evhtp_request_resume() is
						called.

			- Callback definitions are now abstracted into a parent evhtp_callback_t
				structure containing the type, hooks which can be added to a callback
					- The callback-hooks act just like the old per-connection hooks.

			- Callback searches have been cleaned up to facilitate both connection
				based hooks and request based.

			- Callback searches have now been broken up into 3 different functions:
				_evhtp_callback_find,
				_evhtp_callback_regex_find,
				_evhtp_callback_hash_find
					- _evhtp_callback_find is a wrapper around the other functions,
					- _evhtp_callback_regex_find will now set a start and end matched
						offset (so that a user can see exactly where the regex matched)

			- Better API for defining a RFC compliant URI
				- evhtp_uri_t structure is a wrapper around an entire URI
					-> evhtp_request_authority_t
							-- Container where username/password/hostname/port information
								 is stored if in the request.
					-> evhtp_request_path_t
							-- Container where various path information from the URI is stored
									- "full" = the full path including file, query args, and fragments
									- "path" = just the parsed path (doesn't include file / qargs / fragments)
									- "file" = the file found "/path/<file.ext>": file.txt being the file
									- matched_soff = the offset where matched path was found
									- matched_eoff = the offset where matched path was ended
					-> fragment
							-- a string containing fragment data in URI "...#stuff"
					-> evhtp_request_query_t
							-- A key/val queue of parsed URI query arguments
					-> htp_scheme
							- If a scheme was present, this is the enum value of the scheme

			- Added evhtp_request_parse_query which will take the query portion of the
				request URI and does a no-copy parse into an evhtp_request_query_t structure
				(?h=b;c=d&b=4 would become a list of key-values stored in the query_t struct)

			- Added evhtp_set_pre_accept_cb which calls user-defined function prior to
				accepting a connection.

			- Added evhtp_set_post_accept_cb which calls user-defined function after
				accepting a connection.

			- Added evhtp_kv_t structures which are generic key/value queues
			- Added evhtp_kv_new()
			- Added evhtp_kvs_new()
			- Added evhtp_kv_free()
			- Added evhtp_kvs_free()
			- Added evhtp_kvs_for_each() - an iterator for kvs
			- Added evhtp_kv_find() - returns the value (if found) for a key.
			- Added evhtp_header_new()
			- Added evhtp_headers_add_header()
			- Added evhtp_header_key_add()

			- evhtp_hook_type enum's have been been changed to not be in all CAPS:
					- evhtp_hook_on_header  = type for a hook after one header is parsed
					- evhtp_hook_on_headers = type for a hook after all headers are parsed
					- evhtp_hook_on_path    = type for a hook after path is parsed
					- evhtp_hook_on_read    = type for a hook when body data is read
					- evhtp_hook_on_fini    = type for a hook just prior to being free()'d
					- evhtp_hook_on_error   = type for a hook when a fatal error occurs

    - Currently ssl bufferevents will not cleanly shutdown a SSL connection
      once bufferevent_free() is called, only SSL_free is done. Since the
      shutdown process is never taken the session is marked as "bad" and will
      remove that session for the cache and other various things that can
      break performance.

      In order to fix this, before bufferevent_free() is called, I do a non-blocking
      SSL_shutdown on the sessions SSL ctx. Since I use a set of flags which
      essentially mark the session as clean, but ignores the full handshake; this
      breaks TLS RFC. Not the best thing, but it works until a set of features I
      added to libevent are put into the main base.

    - Added a query_raw string which is the unparsed URI query arguments.

    - SSL session callbacks setting is only done if there are user-defined ones
      available.

    - libhtparse fixes when dealing with requests with schema data.

    - Fixed conditional bug for chunked responses
			- _evhtp_create_reply() was adding a Content-Length: 0 header even if
				the response is chunked (this breaks RFC).

    - Added evhtp_kv_rm_and_free which will take a evhtp_kvs_t and evhtp_kv_t set
      of arguments, remove the kv_t from kvs_t and free the kv_t structure.

    - Added evhtp_kvs_find_kv which acts like kv_find but instead returns an
      evhtp_kv_t structure.

    - Added an on_chunk_complete hook in htparse which is called
      when a single chunk has been fully parsed.

    - Added an on_chunks_complete hook in htparse which is called
      after all chunks in a request have been parsed.

    - Added thread initialization functionality in evthr

    - Added streaming reply functionality
				- evhtp_send_reply_start() - creates the initial reply and sends
				- evhtp_send_reply_body()  - sends a chunk of data to the client
				- evhtp_send_reply_end()   - informs evhtp that the user is done streaming data and figures out whether to keep the connection alive or not.

    - Added htparser_get_status to libhtparse

		- Added HTTP response parsing in libevhtparsec

    - OSX Compatability fixes

    - Added evhtp_ssl_use_threads() which will properly initialize thread support for OpenSSL operations.

    - ssl cfg now has 4 modes of defining how SSL session caching works
				- evhtp_ssl_scache_type_disabled - disable cache entirely
				- evhtp_ssl_scache_type_internal - use OpenSSL's build-in cache
				- evhtp_ssl_scache_type_user     - use user-defined caching callbacks
				- evhtp_ssl_scache_type_builtin  - use libevhtp's built-in cache (currently doesn't do anything)

    - updated test.c to use the refactored API correctly

    - Added x509_verify_cb, max_verify_depth, verify_peer and store_flags option (via Oscar Koeroo <okoeroo@gmail.com>)

    - Added HTTP return code 418 (via Oscar Koeroo <okoeroo@gmail.com>) 

    - Added dummy callbacks and values to the test.c program. (via Oscar Koeroo <okoeroo@gmail.com>)

    - Added CA Path option for ssl_cfg. (via Oscar Koeroo <okoeroo@gmail.com>) 

		- Fixed issue with htparser_should_keepalive() returning wrong values.


v0.3.7
 - Due to various problems http-parser (ry/http-parser) I have written my own
   parser (derived and ispired from various nginx functions) (./libhtparse).

 - Re-introduced the pre_accept_cb and post_accept_cb which deprecates the 
      evhtp_set_connection_hooks (which would call a defined function immediately
      after a connection was accepted, so it was confusing I think).

      The new functions to set the pre/post accepts are:
       * evhtp_set_pre_accept_cb(evhtp_t *, evhtp_pre_accept cb, void * arg);
       * evhtp_set_post_accept_cb(evhtp_t *, evhtp_post_accept cb, void * arg);
         - evhtp_pre_accept functions have the following attributes:
           * int fd            : (the allocated file descriptor)
           * struct sockaddr * : self-explanitory
           * int slen          : size of sockaddr
           * void * arg        : argument passed to evhtp_set_pre_accept_cb
         - evhtp_post_accept functions have the following attributes:
           * evhtp_conn_t *    : self explanitory
           * void * arg        : argument passed to evhtp_set_post_accept_cb


 - libevhtp now properly honors all return evhtp_res's from defined request hooks.
   Meaning if you return something other than EVHTP_RES_OK, the proper error
   handling is done with the exception of EVHTP_RES_PAUSE (see notes on pausing)

 - Added [currently only half-working] methods to allow for suspending and
   resuming parser execution and connection handling.

   A hook which returns an evhtp_res value can now return "EVHTP_RES_PAUSE" which
   informs libevhtp to stop all request processing on a connection. Alternatively
   you can use the functions evhtp_request_pause(evhtp_request_t *);

   You may also get a copy of the suspend/resume event timer directly via the
   function evhtp_request_get_resume_ev()

   To resume execution/processing one must call the function
   evhtp_request_resume(evhtp_request_t *);

    To completely disable this functionality you may call the function
    evhtp_disable_pausing(evhtp_t *) before dropping into your event loop

 - Removed unnecessary bufferevent_[enable|disable] calls, it was too tedious
   to work with as it could cause shitty race-like conditions if the client
   bufferevent was needed outside of the library.

 - EVHTP_CLOSE_* flags have been renamed to EVHTP_FLAG_CLOSE_* and length
   extended to 16 bits.

 - added functionality to both set and get user-set htp_request args:
   evhtp_request_set_cbargs()
   evhtp_request_get_cbargs()

 - added a hook which is called just prior to a evhtp_request_t being free()'d

 - Added the ability to define per-callback hooks. Much like per-connection hooks, 
   you can set various hooks which are called when a uri|regex (defined by the 
   set_cb functions) was matched.

   In order to do this properly, set_cb functions now return a evhtp_callback_t which
   can be passed to the evhtp_set_callback_hook() functions.

   For example:
   evhtp_callback_t * cb = evhtp_set_cb(htp, "/derp", derp_cb, NULL);
   evhtp_set_callback_hook(cb, EVHTP_HOOK_HDRS_READ, derp_hdrs_cb, NULL); 

   In the case above once evhtp has found that the incoming request is destined
   for the "/derp" specific callback, it will call "derp_hdrs_cb" after all
   headers have been read.

   These act just like normal per-connection hooks, but it should be noted that
   if a per-callback hook has been enabled, the per-connection hook will be ignored
   for that hook.

 
v0.3.6
 - Removed submodule dependencies 
 - Added various evhtp_hdr functions
    * evhtp_hdrs_new(): creates a new evhtp_hdrs_t struct
    * evhtp_hdr_copy(): creates a copy of a evhtp_hdr_t struct
    * evhtp_hdrs_copy(): creates a copy of a evhtp_hdrs_t struct
 - Added a default request callback if the user has not defined one.
 - Added some informational SSL accessor functions


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:
     evhtp_ssl_cfg structure must be filled with your settings:

         evhtp_ssl_cfg scfg = {
             .pemfile        = ssl_pem,
             .privfile       = ssl_pem,
             .cafile         = ssl_ca,
             .ciphers        = "RC4+RSA:HIGH:+MEDIUM:+LOW",
             .ssl_opts       = <SSL SPECIFIC FLAGS>,
             .enable_scache  = 1,
             .scache_timeout = 1024,
             .scache_init    = evhtp_ssl_scache_builtin_init,
             .scache_add     = evhtp_ssl_scache_builtin_add,
             .scache_get     = evhtp_ssl_scache_builtin_get,
             .scache_del     = NULL,
         };
   * please note that .scache_init, .scache_add, .scache_get, and .scace_del
     are function points to allow for a user to define their own session cache
     mechanism. Libevhtp has a few default built-in cache functions:
      evhtp_ssl_scache_builtin_init,
      evhtp_ssl_scache_builtin_add,
      evhtp_ssl_scache_builtin_get,
      evhtp_ssl_scache_builtin_del

     Another side note here is that currently the builtin functions do not expire,
     this will be fixed in the next beta-release.

   * The second step is to enable the use of the SSL backend by calling
     evhtp_use_ssl(evhtp_t *, evhtp_ssl_cfg *);

 - Regular expression based path callback functions added:
     evhtp_set_regex_cb(evhtp_t *, "^(/path_w_regex/).*", callback, args);

     Using the case above, any path/uri in the request with /path_w_regex/*, the API
     will execute your defined callback function. The output of which is the same as
     any other defined callback.

 - Added _htp_callbacks_find_callback_woffsets(), which (if regex) will set 2 integer
   variables in the evhtp_rquest_t structure defining the beginning and end of a matched
   URI/path.

 - _htp_callback_new() has been modified to create regex based evhtp_callback_t's

 - Made the evhtp_request_t structure private, various get/set functions have been added
   to deal with the internals.

 - Modified compile to support libonigurmura, a BSD licensed cross-platform regular expression
   library. Currently this is only used to support posix regex functionality.
Something went wrong with that request. Please try again.