mirror of
https://github.com/libevent/libevent.git
synced 2025-01-31 09:12:55 +08: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 separate signal events from io events; making the code less complex.
|
||||
o support for periodic timeouts
|
||||
o support for virtual HTTP hosts.
|
||||
|
||||
Changes in 1.4.0:
|
||||
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.
|
||||
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
|
||||
AC_MSG_CHECKING(for TAILQ_FOREACH in sys/queue.h)
|
||||
AC_EGREP_CPP(yes,
|
||||
@ -146,7 +146,7 @@ AC_C_INLINE
|
||||
AC_HEADER_TIME
|
||||
|
||||
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)
|
||||
|
||||
|
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 (*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.
|
||||
*
|
||||
|
@ -99,11 +99,18 @@ struct evhttp_bound_socket {
|
||||
};
|
||||
|
||||
struct evhttp {
|
||||
TAILQ_ENTRY(evhttp) next;
|
||||
|
||||
TAILQ_HEAD(boundq, evhttp_bound_socket) sockets;
|
||||
|
||||
TAILQ_HEAD(httpcbq, evhttp_cb) callbacks;
|
||||
struct evconq connections;
|
||||
|
||||
TAILQ_HEAD(vhostsq, evhttp) virtualhosts;
|
||||
|
||||
/* NULL if this server is not a vhost */
|
||||
char *vhost_pattern;
|
||||
|
||||
int timeout;
|
||||
|
||||
void (*gencb)(struct evhttp_request *req, void *);
|
||||
|
60
http.c
60
http.c
@ -79,6 +79,9 @@
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#ifdef HAVE_FNMATCH_H
|
||||
#include <fnmatch.h>
|
||||
#endif
|
||||
|
||||
#undef timeout_pending
|
||||
#undef timeout_initialized
|
||||
@ -1891,12 +1894,26 @@ evhttp_handle_request(struct evhttp_request *req, void *arg)
|
||||
{
|
||||
struct evhttp *http = arg;
|
||||
struct evhttp_cb *cb = NULL;
|
||||
const char *hostname;
|
||||
|
||||
if (req->uri == NULL) {
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
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) {
|
||||
(*cb->cb)(req, cb->cbarg);
|
||||
return;
|
||||
@ -2017,6 +2034,7 @@ evhttp_new_object(void)
|
||||
TAILQ_INIT(&http->sockets);
|
||||
TAILQ_INIT(&http->callbacks);
|
||||
TAILQ_INIT(&http->connections);
|
||||
TAILQ_INIT(&http->virtualhosts);
|
||||
|
||||
return (http);
|
||||
}
|
||||
@ -2054,6 +2072,7 @@ evhttp_free(struct evhttp* http)
|
||||
struct evhttp_cb *http_cb;
|
||||
struct evhttp_connection *evcon;
|
||||
struct evhttp_bound_socket *bound;
|
||||
struct evhttp* vhost;
|
||||
evutil_socket_t fd;
|
||||
|
||||
/* Remove the accepting part */
|
||||
@ -2077,10 +2096,51 @@ evhttp_free(struct evhttp* http)
|
||||
mm_free(http_cb->what);
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
evhttp_set_timeout(struct evhttp* http, int timeout_in_secs)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user