Libevhtp
Overview
libevhtp 는 libevent 를 이용한 HTTP API 라이브러리이다. libevhtp 를 사용하면 손쉽게 REST 인터페이스를 구현할 수 있다.
홈페이지: https://github.com/ellzey/libevhtp
Types
이벤트 베이스
<source lang=c> typedef struct evhtp_s evhtp_t;
/**
* @brief main structure containing all configuration information */
struct evhtp_s {
evhtp_t * parent; /**< only when this is a vhost */ evbase_t * evbase; /**< the initialized event_base */ evserv_t * server; /**< the libevent listener struct */ char * server_name; /**< the name included in Host: responses */ void * arg; /**< user-defined evhtp_t specific arguments */ int bev_flags; /**< bufferevent flags to use on bufferevent_*_socket_new() */ uint64_t max_body_size; uint64_t max_keepalive_requests; int disable_100_cont; /**< if set, evhtp will not respond to Expect: 100-continue */
- ifndef EVHTP_DISABLE_SSL
evhtp_ssl_ctx_t * ssl_ctx; /**< if ssl enabled, this is the servers CTX */ evhtp_ssl_cfg_t * ssl_cfg;
- endif
- ifndef EVHTP_DISABLE_EVTHR
evthr_pool_t * thr_pool; /**< connection threadpool */
- endif
- ifndef EVHTP_DISABLE_EVTHR
pthread_mutex_t * lock; /**< parent lock for add/del cbs in threads */ evhtp_thread_init_cb thread_init_cb; void * thread_init_cbarg;
- endif
evhtp_callbacks_t * callbacks; evhtp_defaults_t defaults;
struct timeval recv_timeo; struct timeval send_timeo;
TAILQ_HEAD(, evhtp_alias_s) aliases; TAILQ_HEAD(, evhtp_s) vhosts; TAILQ_ENTRY(evhtp_s) next_vhost;
}; </source>
이벤트 콜백
<source lang=c> typedef struct evhtp_callback_s evhtp_callback_t;
/**
* @brief structure containing a single callback and configuration * * The definition structure which is used within the evhtp_callbacks_t * structure. This holds information about what should execute for either * a single or regex path. * * For example, if you registered a callback to be executed on a request * for "/herp/derp", your defined callback will be executed. * * Optionally you can set callback-specific hooks just like per-connection * hooks using the same rules. * */
struct evhtp_callback_s {
evhtp_callback_type type; /**< the type of callback (regex|path) */ evhtp_callback_cb cb; /**< the actual callback function */ unsigned int hash; /**< the full hash generated integer */ void * cbarg; /**< user-defind arguments passed to the cb */ evhtp_hooks_t * hooks; /**< per-callback hooks */
union { char * path; char * glob;
- ifndef EVHTP_DISABLE_REGEX
regex_t * regex;
- endif
} val;
TAILQ_ENTRY(evhtp_callback_s) next;
}; </source>
evhtp_request_t
HTTP request 요청시 모든 정보가 저장되는 구조체이다. <source lang=c> typedef struct evhtp_request_s evhtp_request_t;
/**
* @brief a structure containing all information for a http request. */
struct evhtp_request_s {
evhtp_t * htp; /**< the parent evhtp_t structure */ evhtp_connection_t * conn; /**< the associated connection */ evhtp_hooks_t * hooks; /**< request specific hooks */ evhtp_uri_t * uri; /**< request URI information */ evbuf_t * buffer_in; /**< buffer containing data from client */ evbuf_t * buffer_out; /**< buffer containing data to client */ evhtp_headers_t * headers_in; /**< headers from client */ evhtp_headers_t * headers_out; /**< headers to client */ evhtp_proto proto; /**< HTTP protocol used */ htp_method method; /**< HTTP method used */ evhtp_res status; /**< The HTTP response code or other error conditions */ int keepalive; /**< set to 1 if the connection is keep-alive */ int finished; /**< set to 1 if the request is fully processed */ int chunked; /**< set to 1 if the request is chunked */
evhtp_callback_cb cb; /**< the function to call when fully processed */ void * cbarg; /**< argument which is passed to the cb function */ int error;
TAILQ_ENTRY(evhtp_request_s) next;
}; </source>
Functions
생성/삭제
<source lang=c> /**
* @brief creates a new evhtp_t instance * * @param evbase the initialized event base * @param arg user-defined argument which is evhtp_t specific * * @return a new evhtp_t structure or NULL on error */
evhtp_t * evhtp_new(evbase_t * evbase, void * arg); void evhtp_free(evhtp_t * evhtp); </source> evhtp 인스턴스 생성/삭제 함수
콜백 등록
- Interface
<source lang=c> /**
* @brief sets a callback to be executed on a specific path * * @param htp the initialized evhtp_t * @param path the path to match * @param cb the function to be executed * @param arg user-defined argument passed to the callback * * @return evhtp_callback_t * on success, NULL on error. */
evhtp_callback_t * evhtp_set_cb(evhtp_t * htp, const char * path, evhtp_callback_cb cb, void * arg); </source> 지정된 경로가 호출되었을 때 실행 될 콜백 함수를 지정한다.
- Example
<source lang=c> void testcb(evhtp_request_t *req, void *a) {
const char *str = a; evbuffer_add_printf(req->buffer_out, "%s", str); evhtp_send_reply(req, EVHTP_RES_OK);
}
evhtp_t *htp = evhtp_new(evbase, NULL);
evhtp_set_cb(htp, "/simple/", testcb, "simple"); </source>
Listen 소켓 설정/해제
- Interface
<source lang=c> /**
* @brief bind to a socket, optionally with specific protocol support * formatting. The addr can be defined as one of the following: * ipv6:<ipv6addr> for binding to an IPv6 address. * unix:<named pipe> for binding to a unix named socket * ipv4:<ipv4addr> for binding to an ipv4 address * Otherwise the addr is assumed to be ipv4. * * @param htp * @param addr * @param port * @param backlog * * @return */
int evhtp_bind_socket(evhtp_t * htp, const char * addr, uint16_t port, int backlog);
/**
* @brief stops the listening socket. * * @param htp */
void evhtp_unbind_socket(evhtp_t * htp); </source> Listen 주소를 설정/해제한다. 주소 설정 시, 자동으로 주소 타입을 파싱해서 알맞은 소켓 타입으로 생성한 후, listen 한다. "0.0.0.0" 설정시, localhost 주소를 listen 한다.
- Example
<source lang=c> evhtp_bind_socket(htp, "0.0.0.0", 8081, 1024);
evhtp_unbind_socket(htp); </source>
Samples
test_basic
- test_basic.c
<source lang=c>
- include <stdio.h>
- include <stdlib.h>
- include <string.h>
- include <stdint.h>
- include <errno.h>
- include <evhtp.h>
void testcb(evhtp_request_t *req, void *a) {
const char *str = a; evbuffer_add_printf(req->buffer_out, "%s", str); evhtp_send_reply(req, EVHTP_RES_OK);
}
int main(int argc, char **argv) {
evbase_t *evbase = event_base_new(); evhtp_t *htp = evhtp_new(evbase, NULL); evhtp_set_cb(htp, "/simple/", testcb, "simple"); evhtp_set_cb(htp, "/1/ping", testcb, "one"); evhtp_set_cb(htp, "/1/ping.json", testcb, "two");
- ifndef EVHTP_DISABLE_EVTHR
evhtp_use_threads(htp, NULL, 4, NULL);
- endif
evhtp_bind_socket(htp, "0.0.0.0", 8081, 1024); event_base_loop(evbase, 0); evhtp_unbind_socket(htp); evhtp_free(htp); event_base_free(evbase); return 0;
} </source>
References
<references />