mirror of
https://github.com/libevent/libevent.git
synced 2025-01-09 00:56:20 +08:00
Merge branch 'http_small_tweaks'
Conflicts: http-internal.h
This commit is contained in:
commit
2a3b5872fe
@ -40,8 +40,6 @@ struct evbuffer;
|
||||
struct addrinfo;
|
||||
struct evhttp_request;
|
||||
|
||||
/* A stupid connection object - maybe make this a bufferevent later */
|
||||
|
||||
enum evhttp_connection_state {
|
||||
EVCON_DISCONNECTED, /**< not currently connected not trying either*/
|
||||
EVCON_CONNECTING, /**< tries to currently connect */
|
||||
@ -56,8 +54,10 @@ enum evhttp_connection_state {
|
||||
|
||||
struct event_base;
|
||||
|
||||
/* A client or server connection. */
|
||||
struct evhttp_connection {
|
||||
/* we use tailq only if they were created for an http server */
|
||||
/* we use this tailq only if this connection was created for an http
|
||||
* server */
|
||||
TAILQ_ENTRY(evhttp_connection) next;
|
||||
|
||||
evutil_socket_t fd;
|
||||
@ -100,6 +100,7 @@ struct evhttp_connection {
|
||||
struct evdns_base *dns_base;
|
||||
};
|
||||
|
||||
/* A callback for an http server */
|
||||
struct evhttp_cb {
|
||||
TAILQ_ENTRY(evhttp_cb) next;
|
||||
|
||||
@ -120,11 +121,15 @@ struct evhttp_bound_socket {
|
||||
};
|
||||
|
||||
struct evhttp {
|
||||
TAILQ_ENTRY(evhttp) next;
|
||||
/* Next vhost, if this is a vhost. */
|
||||
TAILQ_ENTRY(evhttp) next_vhost;
|
||||
|
||||
/* All listeners for this host */
|
||||
TAILQ_HEAD(boundq, evhttp_bound_socket) sockets;
|
||||
|
||||
TAILQ_HEAD(httpcbq, evhttp_cb) callbacks;
|
||||
|
||||
/* All live connections on this host. */
|
||||
struct evconq connections;
|
||||
|
||||
TAILQ_HEAD(vhostsq, evhttp) virtualhosts;
|
||||
@ -137,12 +142,16 @@ struct evhttp {
|
||||
size_t default_max_headers_size;
|
||||
ev_uint64_t default_max_body_size;
|
||||
|
||||
/* Fallback callback if all the other callbacks for this connection
|
||||
don't match. */
|
||||
void (*gencb)(struct evhttp_request *req, void *);
|
||||
void *gencbarg;
|
||||
|
||||
struct event_base *base;
|
||||
};
|
||||
|
||||
/* XXX most of these functions could be static. */
|
||||
|
||||
/* resets the connection; can be reused for more requests */
|
||||
void evhttp_connection_reset(struct evhttp_connection *);
|
||||
|
||||
@ -153,18 +162,12 @@ int evhttp_connection_connect(struct evhttp_connection *);
|
||||
void evhttp_connection_fail(struct evhttp_connection *,
|
||||
enum evhttp_connection_error error);
|
||||
|
||||
void evhttp_get_request(struct evhttp *, evutil_socket_t, struct sockaddr *, ev_socklen_t);
|
||||
|
||||
enum message_read_status;
|
||||
|
||||
enum message_read_status evhttp_parse_firstline(struct evhttp_request *, struct evbuffer*);
|
||||
enum message_read_status evhttp_parse_headers(struct evhttp_request *, struct evbuffer*);
|
||||
|
||||
void evhttp_start_read(struct evhttp_connection *);
|
||||
void evhttp_make_header(struct evhttp_connection *, struct evhttp_request *);
|
||||
|
||||
void evhttp_write_buffer(struct evhttp_connection *,
|
||||
void (*)(struct evhttp_connection *, void *), void *);
|
||||
|
||||
/* response sending HTML the data in the buffer */
|
||||
void evhttp_response_code(struct evhttp_request *, int, const char *);
|
||||
|
65
http.c
65
http.c
@ -172,6 +172,10 @@ static void evhttp_read_header(struct evhttp_connection *evcon,
|
||||
static int evhttp_add_header_internal(struct evkeyvalq *headers,
|
||||
const char *key, const char *value);
|
||||
static const char *evhttp_response_phrase_internal(int code);
|
||||
static void evhttp_get_request(struct evhttp *, evutil_socket_t, struct sockaddr *, ev_socklen_t);
|
||||
static void evhttp_write_buffer(struct evhttp_connection *,
|
||||
void (*)(struct evhttp_connection *, void *), void *);
|
||||
static void evhttp_make_header(struct evhttp_connection *, struct evhttp_request *);
|
||||
|
||||
/* callbacks for bufferevent */
|
||||
static void evhttp_read_cb(struct bufferevent *, void *);
|
||||
@ -260,6 +264,9 @@ evhttp_htmlescape(const char *html)
|
||||
return (escaped_html);
|
||||
}
|
||||
|
||||
/** Given an evhttp_cmd_type, returns a constant string containing the
|
||||
* equivalent HTTP command, or NULL if the evhttp_command_type is
|
||||
* unrecognized. */
|
||||
static const char *
|
||||
evhttp_method(enum evhttp_cmd_type type)
|
||||
{
|
||||
@ -304,6 +311,9 @@ evhttp_response_needs_body(struct evhttp_request *req)
|
||||
req->type != EVHTTP_REQ_HEAD);
|
||||
}
|
||||
|
||||
/** Helper: adds the event 'ev' with the timeout 'timeout', or with
|
||||
* default_timeout if timeout is -1.
|
||||
*/
|
||||
static int
|
||||
evhttp_add_event(struct event *ev, int timeout, int default_timeout)
|
||||
{
|
||||
@ -318,7 +328,11 @@ evhttp_add_event(struct event *ev, int timeout, int default_timeout)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
/** Helper: called after we've added some data to an evcon's bufferevent's
|
||||
* output buffer. Sets the evconn's writing-is-done callback, and puts
|
||||
* the bufferevent into writing mode.
|
||||
*/
|
||||
static void
|
||||
evhttp_write_buffer(struct evhttp_connection *evcon,
|
||||
void (*cb)(struct evhttp_connection *, void *), void *arg)
|
||||
{
|
||||
@ -332,6 +346,7 @@ evhttp_write_buffer(struct evhttp_connection *evcon,
|
||||
bufferevent_enable(evcon->bufev, EV_WRITE);
|
||||
}
|
||||
|
||||
/** Helper: returns true iff evconn is in any connected state. */
|
||||
static int
|
||||
evhttp_connected(struct evhttp_connection *evcon)
|
||||
{
|
||||
@ -350,8 +365,9 @@ evhttp_connected(struct evhttp_connection *evcon)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the headers needed for an HTTP request
|
||||
/* Create the headers needed for an outgoing HTTP request, adds them to
|
||||
* the request's header list, and writes the request line to the
|
||||
* connection's output buffer.
|
||||
*/
|
||||
static void
|
||||
evhttp_make_header_request(struct evhttp_connection *evcon,
|
||||
@ -370,6 +386,7 @@ evhttp_make_header_request(struct evhttp_connection *evcon,
|
||||
/* Add the content length on a post or put request if missing */
|
||||
if ((req->type == EVHTTP_REQ_POST || req->type == EVHTTP_REQ_PUT) &&
|
||||
evhttp_find_header(req->output_headers, "Content-Length") == NULL){
|
||||
/* XXX what if long is 64 bits? -NM */
|
||||
char size[12];
|
||||
evutil_snprintf(size, sizeof(size), "%ld",
|
||||
(long)evbuffer_get_length(req->output_buffer));
|
||||
@ -377,6 +394,9 @@ evhttp_make_header_request(struct evhttp_connection *evcon,
|
||||
}
|
||||
}
|
||||
|
||||
/** Return true if the list of headers in 'headers', intepreted with respect
|
||||
* to flags, means that we should send a "connection: close" when the request
|
||||
* is done. */
|
||||
static int
|
||||
evhttp_is_connection_close(int flags, struct evkeyvalq* headers)
|
||||
{
|
||||
@ -390,6 +410,7 @@ evhttp_is_connection_close(int flags, struct evkeyvalq* headers)
|
||||
}
|
||||
}
|
||||
|
||||
/* Return true iff 'headers' contains 'Connection: keep-alive' */
|
||||
static int
|
||||
evhttp_is_connection_keepalive(struct evkeyvalq* headers)
|
||||
{
|
||||
@ -398,6 +419,7 @@ evhttp_is_connection_keepalive(struct evkeyvalq* headers)
|
||||
&& evutil_ascii_strncasecmp(connection, "keep-alive", 10) == 0);
|
||||
}
|
||||
|
||||
/* Add a correct "Date" header to headers, unless it already has one. */
|
||||
static void
|
||||
evhttp_maybe_add_date_header(struct evkeyvalq *headers)
|
||||
{
|
||||
@ -421,22 +443,24 @@ evhttp_maybe_add_date_header(struct evkeyvalq *headers)
|
||||
}
|
||||
}
|
||||
|
||||
/* Add a "Content-Length" header with value 'content_length' to headers,
|
||||
* unless it already has a content-length or transfer-encoding header. */
|
||||
static void
|
||||
evhttp_maybe_add_content_length_header(struct evkeyvalq *headers,
|
||||
long content_length)
|
||||
long content_length) /* XXX use size_t or int64, not long. */
|
||||
{
|
||||
if (evhttp_find_header(headers, "Transfer-Encoding") == NULL &&
|
||||
evhttp_find_header(headers, "Content-Length") == NULL) {
|
||||
char len[12];
|
||||
char len[12]; /* XXX what if long is 64 bits? -NM */
|
||||
evutil_snprintf(len, sizeof(len), "%ld", content_length);
|
||||
evhttp_add_header(headers, "Content-Length", len);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the headers needed for an HTTP reply
|
||||
* Create the headers needed for an HTTP reply in req->output_headers,
|
||||
* and write the first HTTP response for req line to evcon.
|
||||
*/
|
||||
|
||||
static void
|
||||
evhttp_make_header_response(struct evhttp_connection *evcon,
|
||||
struct evhttp_request *req)
|
||||
@ -447,6 +471,7 @@ evhttp_make_header_response(struct evhttp_connection *evcon,
|
||||
req->major, req->minor, req->response_code,
|
||||
req->response_code_line);
|
||||
|
||||
/* XXX shouldn't these check for >= rather than == ? - NM */
|
||||
if (req->major == 1) {
|
||||
if (req->minor == 1)
|
||||
evhttp_maybe_add_date_header(req->output_headers);
|
||||
@ -490,7 +515,10 @@ evhttp_make_header_response(struct evhttp_connection *evcon,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
/** Generate all headers appropriate for sending the http request in req (or
|
||||
* the response, if we're sending a response), and write them to evcon's
|
||||
* bufferevent. Also writes all data from req->output_buffer */
|
||||
static void
|
||||
evhttp_make_header(struct evhttp_connection *evcon, struct evhttp_request *req)
|
||||
{
|
||||
struct evkeyval *header;
|
||||
@ -584,6 +612,10 @@ evhttp_connection_incoming_fail(struct evhttp_request *req,
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Called when evcon has experienced a (non-recoverable? -NM) error, as
|
||||
* given in error. If it's an outgoing connection, reset the connection,
|
||||
* retry any pending requests, and inform the user. If it's incoming,
|
||||
* delegates to evhttp_connection_incoming_fail(). */
|
||||
void
|
||||
evhttp_connection_fail(struct evhttp_connection *evcon,
|
||||
enum evhttp_connection_error error)
|
||||
@ -638,6 +670,8 @@ evhttp_connection_fail(struct evhttp_connection *evcon,
|
||||
(*cb)(NULL, cb_arg);
|
||||
}
|
||||
|
||||
/* Bufferevent callback: invoked when any data has been written from an
|
||||
* http connection's bufferevent */
|
||||
static void
|
||||
evhttp_write_cb(struct bufferevent *bufev, void *arg)
|
||||
{
|
||||
@ -1031,7 +1065,8 @@ evhttp_request_dispatch(struct evhttp_connection* evcon)
|
||||
evhttp_write_buffer(evcon, evhttp_write_connectioncb, NULL);
|
||||
}
|
||||
|
||||
/* Reset our connection state */
|
||||
/* Reset our connection state: disables reading/writing, closes our fd (if
|
||||
* any), clears out buffers, and puts us in state DISCONNECTED. */
|
||||
void
|
||||
evhttp_connection_reset(struct evhttp_connection *evcon)
|
||||
{
|
||||
@ -1338,6 +1373,7 @@ evhttp_parse_request_line(struct evhttp_request *req, char *line)
|
||||
req->major = 1;
|
||||
req->minor = 1;
|
||||
} else {
|
||||
/* XXX So, http/1.2 kills us? Is that right? -NM */
|
||||
event_debug(("%s: bad version %s on request %p from %s",
|
||||
__func__, version, req, req->remote_host));
|
||||
return (-1);
|
||||
@ -2597,7 +2633,7 @@ evhttp_handle_request(struct evhttp_request *req, void *arg)
|
||||
hostname = evhttp_find_header(req->input_headers, "Host");
|
||||
if (hostname != NULL) {
|
||||
struct evhttp *vhost;
|
||||
TAILQ_FOREACH(vhost, &http->virtualhosts, next) {
|
||||
TAILQ_FOREACH(vhost, &http->virtualhosts, next_vhost) {
|
||||
if (prefix_suffix_match(vhost->vhost_pattern, hostname,
|
||||
1 /* ignorecase */)) {
|
||||
evhttp_handle_request(req, vhost);
|
||||
@ -2651,6 +2687,7 @@ evhttp_handle_request(struct evhttp_request *req, void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
/* Listener callback when a connection arrives at a server. */
|
||||
static void
|
||||
accept_socket_cb(struct evconnlistener *listener, evutil_socket_t nfd, struct sockaddr *peer_sa, int peer_socklen, void *arg)
|
||||
{
|
||||
@ -2824,7 +2861,7 @@ evhttp_free(struct evhttp* http)
|
||||
}
|
||||
|
||||
while ((vhost = TAILQ_FIRST(&http->virtualhosts)) != NULL) {
|
||||
TAILQ_REMOVE(&http->virtualhosts, vhost, next);
|
||||
TAILQ_REMOVE(&http->virtualhosts, vhost, next_vhost);
|
||||
|
||||
evhttp_free(vhost);
|
||||
}
|
||||
@ -2848,7 +2885,7 @@ evhttp_add_virtual_host(struct evhttp* http, const char *pattern,
|
||||
if (vhost->vhost_pattern == NULL)
|
||||
return (-1);
|
||||
|
||||
TAILQ_INSERT_TAIL(&http->virtualhosts, vhost, next);
|
||||
TAILQ_INSERT_TAIL(&http->virtualhosts, vhost, next_vhost);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -2859,7 +2896,7 @@ evhttp_remove_virtual_host(struct evhttp* http, struct evhttp* vhost)
|
||||
if (vhost->vhost_pattern == NULL)
|
||||
return (-1);
|
||||
|
||||
TAILQ_REMOVE(&http->virtualhosts, vhost, next);
|
||||
TAILQ_REMOVE(&http->virtualhosts, vhost, next_vhost);
|
||||
|
||||
mm_free(vhost->vhost_pattern);
|
||||
vhost->vhost_pattern = NULL;
|
||||
@ -3178,7 +3215,7 @@ evhttp_associate_new_request_with_connection(struct evhttp_connection *evcon)
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
evhttp_get_request(struct evhttp *http, evutil_socket_t fd,
|
||||
struct sockaddr *sa, ev_socklen_t salen)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user