mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-13 14:26:30 -04:00
add support for virtual http hosts; no tests yet
svn:r771
This commit is contained in:
parent
f940eb4b8d
commit
f2a81fbc67
@ -88,6 +88,7 @@ Changes in current version:
|
|||||||
o reduce system calls for getting current time by caching it.
|
o reduce system calls for getting current time by caching it.
|
||||||
o separate signal events from io events; making the code less complex.
|
o separate signal events from io events; making the code less complex.
|
||||||
o support for periodic timeouts
|
o support for periodic timeouts
|
||||||
|
o support for virtual HTTP hosts.
|
||||||
|
|
||||||
Changes in 1.4.0:
|
Changes in 1.4.0:
|
||||||
o allow \r or \n individually to separate HTTP headers instead of the standard "\r\n"; from Charles Kerr.
|
o allow \r or \n individually to separate HTTP headers instead of the standard "\r\n"; from Charles Kerr.
|
||||||
|
@ -53,7 +53,7 @@ AM_CONDITIONAL(ZLIB_REGRESS, [test "$have_zlib" != "no"])
|
|||||||
|
|
||||||
dnl Checks for header files.
|
dnl Checks for header files.
|
||||||
AC_HEADER_STDC
|
AC_HEADER_STDC
|
||||||
AC_CHECK_HEADERS(fcntl.h stdarg.h inttypes.h stdint.h stddef.h poll.h signal.h unistd.h sys/epoll.h sys/time.h sys/queue.h sys/event.h sys/param.h sys/ioctl.h sys/select.h sys/devpoll.h port.h netinet/in6.h sys/socket.h sys/uio.h)
|
AC_CHECK_HEADERS(fcntl.h stdarg.h inttypes.h stdint.h stddef.h poll.h signal.h unistd.h sys/epoll.h sys/time.h sys/queue.h sys/event.h sys/param.h sys/ioctl.h sys/select.h sys/devpoll.h port.h netinet/in6.h sys/socket.h sys/uio.h fnmatch.h)
|
||||||
if test "x$ac_cv_header_sys_queue_h" = "xyes"; then
|
if test "x$ac_cv_header_sys_queue_h" = "xyes"; then
|
||||||
AC_MSG_CHECKING(for TAILQ_FOREACH in sys/queue.h)
|
AC_MSG_CHECKING(for TAILQ_FOREACH in sys/queue.h)
|
||||||
AC_EGREP_CPP(yes,
|
AC_EGREP_CPP(yes,
|
||||||
@ -146,7 +146,7 @@ AC_C_INLINE
|
|||||||
AC_HEADER_TIME
|
AC_HEADER_TIME
|
||||||
|
|
||||||
dnl Checks for library functions.
|
dnl Checks for library functions.
|
||||||
AC_CHECK_FUNCS(gettimeofday vasprintf fcntl clock_gettime strtok_r strsep getaddrinfo getnameinfo strlcpy inet_ntop signal sigaction strtoll)
|
AC_CHECK_FUNCS(gettimeofday vasprintf fcntl clock_gettime strtok_r strsep getaddrinfo getnameinfo strlcpy inet_ntop signal sigaction strtoll fnmatch)
|
||||||
|
|
||||||
AC_CHECK_SIZEOF(long)
|
AC_CHECK_SIZEOF(long)
|
||||||
|
|
||||||
|
35
evhttp.h
35
evhttp.h
@ -138,6 +138,41 @@ int evhttp_del_cb(struct evhttp *, const char *);
|
|||||||
void evhttp_set_gencb(struct evhttp *http,
|
void evhttp_set_gencb(struct evhttp *http,
|
||||||
void (*cb)(struct evhttp_request *, void *), void *arg);
|
void (*cb)(struct evhttp_request *, void *), void *arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Adds a virtual host to the http server.
|
||||||
|
|
||||||
|
A virtual host is a newly initialized evhttp object that has request
|
||||||
|
callbacks set on it via evhttp_set_cb() or evhttp_set_gencb(). It
|
||||||
|
most not have any listing sockets associated with it.
|
||||||
|
|
||||||
|
If the virtual host has not been removed by the time that evhttp_free()
|
||||||
|
is called on the main http server, it will be automatically freed, too.
|
||||||
|
|
||||||
|
It is possible to have hierarchical vhosts. For example: A vhost
|
||||||
|
with the pattern *.example.com may have other vhosts with patterns
|
||||||
|
foo.example.com and bar.example.com associated with it.
|
||||||
|
|
||||||
|
@param http the evhttp object to which to add a virtual host
|
||||||
|
@param pattern the glob pattern against which the hostname is matched.
|
||||||
|
The match is case insensitive and follows otherwise regular shell
|
||||||
|
matching.
|
||||||
|
@param vhost the virtual host to add the regular http server.
|
||||||
|
@return 0 on success, -1 on failure
|
||||||
|
@see evhttp_remove_virtual_host()
|
||||||
|
*/
|
||||||
|
int evhttp_add_virtual_host(struct evhttp* http, const char *pattern,
|
||||||
|
struct evhttp* vhost);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Removes a virtual host from the http server.
|
||||||
|
|
||||||
|
@param http the evhttp object from which to remove the virtual host
|
||||||
|
@param vhost the virtual host to remove from the regular http server.
|
||||||
|
@return 0 on success, -1 on failure
|
||||||
|
@see evhttp_add_virtual_host()
|
||||||
|
*/
|
||||||
|
int evhttp_remove_virtual_host(struct evhttp* http, struct evhttp* vhost);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the timeout for an HTTP request.
|
* Set the timeout for an HTTP request.
|
||||||
*
|
*
|
||||||
|
@ -99,11 +99,18 @@ struct evhttp_bound_socket {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct evhttp {
|
struct evhttp {
|
||||||
|
TAILQ_ENTRY(evhttp) next;
|
||||||
|
|
||||||
TAILQ_HEAD(boundq, evhttp_bound_socket) sockets;
|
TAILQ_HEAD(boundq, evhttp_bound_socket) sockets;
|
||||||
|
|
||||||
TAILQ_HEAD(httpcbq, evhttp_cb) callbacks;
|
TAILQ_HEAD(httpcbq, evhttp_cb) callbacks;
|
||||||
struct evconq connections;
|
struct evconq connections;
|
||||||
|
|
||||||
|
TAILQ_HEAD(vhostsq, evhttp) virtualhosts;
|
||||||
|
|
||||||
|
/* NULL if this server is not a vhost */
|
||||||
|
char *vhost_pattern;
|
||||||
|
|
||||||
int timeout;
|
int timeout;
|
||||||
|
|
||||||
void (*gencb)(struct evhttp_request *req, void *);
|
void (*gencb)(struct evhttp_request *req, void *);
|
||||||
|
60
http.c
60
http.c
@ -79,6 +79,9 @@
|
|||||||
#ifdef HAVE_FCNTL_H
|
#ifdef HAVE_FCNTL_H
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_FNMATCH_H
|
||||||
|
#include <fnmatch.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#undef timeout_pending
|
#undef timeout_pending
|
||||||
#undef timeout_initialized
|
#undef timeout_initialized
|
||||||
@ -1891,12 +1894,26 @@ evhttp_handle_request(struct evhttp_request *req, void *arg)
|
|||||||
{
|
{
|
||||||
struct evhttp *http = arg;
|
struct evhttp *http = arg;
|
||||||
struct evhttp_cb *cb = NULL;
|
struct evhttp_cb *cb = NULL;
|
||||||
|
const char *hostname;
|
||||||
|
|
||||||
if (req->uri == NULL) {
|
if (req->uri == NULL) {
|
||||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* handle potential virtual hosts */
|
||||||
|
hostname = evhttp_find_header(req->input_headers, "Host");
|
||||||
|
if (hostname != NULL) {
|
||||||
|
struct evhttp *vhost;
|
||||||
|
TAILQ_FOREACH(vhost, &http->virtualhosts, next) {
|
||||||
|
if (fnmatch(vhost->vhost_pattern, hostname,
|
||||||
|
FNM_CASEFOLD) == 0) {
|
||||||
|
evhttp_handle_request(req, vhost);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((cb = evhttp_dispatch_callback(&http->callbacks, req)) != NULL) {
|
if ((cb = evhttp_dispatch_callback(&http->callbacks, req)) != NULL) {
|
||||||
(*cb->cb)(req, cb->cbarg);
|
(*cb->cb)(req, cb->cbarg);
|
||||||
return;
|
return;
|
||||||
@ -2017,6 +2034,7 @@ evhttp_new_object(void)
|
|||||||
TAILQ_INIT(&http->sockets);
|
TAILQ_INIT(&http->sockets);
|
||||||
TAILQ_INIT(&http->callbacks);
|
TAILQ_INIT(&http->callbacks);
|
||||||
TAILQ_INIT(&http->connections);
|
TAILQ_INIT(&http->connections);
|
||||||
|
TAILQ_INIT(&http->virtualhosts);
|
||||||
|
|
||||||
return (http);
|
return (http);
|
||||||
}
|
}
|
||||||
@ -2054,6 +2072,7 @@ evhttp_free(struct evhttp* http)
|
|||||||
struct evhttp_cb *http_cb;
|
struct evhttp_cb *http_cb;
|
||||||
struct evhttp_connection *evcon;
|
struct evhttp_connection *evcon;
|
||||||
struct evhttp_bound_socket *bound;
|
struct evhttp_bound_socket *bound;
|
||||||
|
struct evhttp* vhost;
|
||||||
evutil_socket_t fd;
|
evutil_socket_t fd;
|
||||||
|
|
||||||
/* Remove the accepting part */
|
/* Remove the accepting part */
|
||||||
@ -2078,9 +2097,50 @@ evhttp_free(struct evhttp* http)
|
|||||||
mm_free(http_cb);
|
mm_free(http_cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while ((vhost = TAILQ_FIRST(&http->virtualhosts)) != NULL) {
|
||||||
|
TAILQ_REMOVE(&http->virtualhosts, vhost, next);
|
||||||
|
|
||||||
|
evhttp_free(vhost);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (http->vhost_pattern != NULL)
|
||||||
|
mm_free(http->vhost_pattern);
|
||||||
|
|
||||||
mm_free(http);
|
mm_free(http);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
evhttp_add_virtual_host(struct evhttp* http, const char *pattern,
|
||||||
|
struct evhttp* vhost)
|
||||||
|
{
|
||||||
|
/* a vhost can only be a vhost once and should not have bound sockets */
|
||||||
|
if (vhost->vhost_pattern != NULL ||
|
||||||
|
TAILQ_FIRST(&vhost->sockets) != NULL)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
vhost->vhost_pattern = mm_strdup(pattern);
|
||||||
|
if (vhost->vhost_pattern == NULL)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
TAILQ_INSERT_TAIL(&http->virtualhosts, vhost, next);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
evhttp_remove_virtual_host(struct evhttp* http, struct evhttp* vhost)
|
||||||
|
{
|
||||||
|
if (vhost->vhost_pattern == NULL)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
TAILQ_REMOVE(&http->virtualhosts, vhost, next);
|
||||||
|
|
||||||
|
mm_free(vhost->vhost_pattern);
|
||||||
|
vhost->vhost_pattern = NULL;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
evhttp_set_timeout(struct evhttp* http, int timeout_in_secs)
|
evhttp_set_timeout(struct evhttp* http, int timeout_in_secs)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user