mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-11 21:34:53 -04:00
Merge branch '21_http_error_cb_squashed'
This commit is contained in:
commit
b3aca5d96c
2
evrpc.c
2
evrpc.c
@ -977,7 +977,7 @@ evrpc_request_timeout(evutil_socket_t fd, short what, void *arg)
|
||||
struct evhttp_connection *evcon = ctx->evcon;
|
||||
EVUTIL_ASSERT(evcon != NULL);
|
||||
|
||||
evhttp_connection_fail_(evcon, EVCON_HTTP_TIMEOUT);
|
||||
evhttp_connection_fail_(evcon, EVREQ_HTTP_TIMEOUT);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -29,14 +29,6 @@ enum message_read_status {
|
||||
DATA_TOO_LONG = -3
|
||||
};
|
||||
|
||||
enum evhttp_connection_error {
|
||||
EVCON_HTTP_TIMEOUT,
|
||||
EVCON_HTTP_EOF,
|
||||
EVCON_HTTP_INVALID_HEADER,
|
||||
EVCON_HTTP_BUFFER_ERROR,
|
||||
EVCON_HTTP_REQUEST_CANCEL
|
||||
};
|
||||
|
||||
struct evbuffer;
|
||||
struct addrinfo;
|
||||
struct evhttp_request;
|
||||
@ -182,9 +174,10 @@ void evhttp_connection_reset_(struct evhttp_connection *);
|
||||
/* connects if necessary */
|
||||
int evhttp_connection_connect_(struct evhttp_connection *);
|
||||
|
||||
enum evhttp_request_error;
|
||||
/* notifies the current request that it failed; resets connection */
|
||||
void evhttp_connection_fail_(struct evhttp_connection *,
|
||||
enum evhttp_connection_error error);
|
||||
enum evhttp_request_error error);
|
||||
|
||||
enum message_read_status;
|
||||
|
||||
|
56
http.c
56
http.c
@ -625,11 +625,11 @@ evhttp_connection_set_max_body_size(struct evhttp_connection* evcon,
|
||||
|
||||
static int
|
||||
evhttp_connection_incoming_fail(struct evhttp_request *req,
|
||||
enum evhttp_connection_error error)
|
||||
enum evhttp_request_error error)
|
||||
{
|
||||
switch (error) {
|
||||
case EVCON_HTTP_TIMEOUT:
|
||||
case EVCON_HTTP_EOF:
|
||||
case EVREQ_HTTP_TIMEOUT:
|
||||
case EVREQ_HTTP_EOF:
|
||||
/*
|
||||
* these are cases in which we probably should just
|
||||
* close the connection and not send a reply. this
|
||||
@ -647,9 +647,10 @@ evhttp_connection_incoming_fail(struct evhttp_request *req,
|
||||
req->evcon = NULL;
|
||||
}
|
||||
return (-1);
|
||||
case EVCON_HTTP_INVALID_HEADER:
|
||||
case EVCON_HTTP_BUFFER_ERROR:
|
||||
case EVCON_HTTP_REQUEST_CANCEL:
|
||||
case EVREQ_HTTP_INVALID_HEADER:
|
||||
case EVREQ_HTTP_BUFFER_ERROR:
|
||||
case EVREQ_HTTP_REQUEST_CANCEL:
|
||||
case EVREQ_HTTP_DATA_TOO_LONG:
|
||||
default: /* xxx: probably should just error on default */
|
||||
/* the callback looks at the uri to determine errors */
|
||||
if (req->uri) {
|
||||
@ -677,12 +678,14 @@ evhttp_connection_incoming_fail(struct evhttp_request *req,
|
||||
* delegates to evhttp_connection_incoming_fail(). */
|
||||
void
|
||||
evhttp_connection_fail_(struct evhttp_connection *evcon,
|
||||
enum evhttp_connection_error error)
|
||||
enum evhttp_request_error error)
|
||||
{
|
||||
const int errsave = EVUTIL_SOCKET_ERROR();
|
||||
struct evhttp_request* req = TAILQ_FIRST(&evcon->requests);
|
||||
void (*cb)(struct evhttp_request *, void *);
|
||||
void *cb_arg;
|
||||
void (*error_cb)(enum evhttp_request_error, void *);
|
||||
void *error_cb_arg;
|
||||
EVUTIL_ASSERT(req != NULL);
|
||||
|
||||
bufferevent_disable(evcon->bufev, EV_READ|EV_WRITE);
|
||||
@ -701,8 +704,10 @@ evhttp_connection_fail_(struct evhttp_connection *evcon,
|
||||
return;
|
||||
}
|
||||
|
||||
error_cb = req->error_cb;
|
||||
error_cb_arg = req->cb_arg;
|
||||
/* when the request was canceled, the callback is not executed */
|
||||
if (error != EVCON_HTTP_REQUEST_CANCEL) {
|
||||
if (error != EVREQ_HTTP_REQUEST_CANCEL) {
|
||||
/* save the callback for later; the cb might free our object */
|
||||
cb = req->cb;
|
||||
cb_arg = req->cb_arg;
|
||||
@ -732,6 +737,8 @@ evhttp_connection_fail_(struct evhttp_connection *evcon,
|
||||
EVUTIL_SET_SOCKET_ERROR(errsave);
|
||||
|
||||
/* inform the user */
|
||||
if (error_cb != NULL)
|
||||
error_cb(error, error_cb_arg);
|
||||
if (cb != NULL)
|
||||
(*cb)(NULL, cb_arg);
|
||||
}
|
||||
@ -925,7 +932,7 @@ evhttp_read_trailer(struct evhttp_connection *evcon, struct evhttp_request *req)
|
||||
switch (evhttp_parse_headers_(req, buf)) {
|
||||
case DATA_CORRUPTED:
|
||||
case DATA_TOO_LONG:
|
||||
evhttp_connection_fail_(evcon, EVCON_HTTP_INVALID_HEADER);
|
||||
evhttp_connection_fail_(evcon, EVREQ_HTTP_DATA_TOO_LONG);
|
||||
break;
|
||||
case ALL_DATA_READ:
|
||||
bufferevent_disable(evcon->bufev, EV_READ);
|
||||
@ -952,10 +959,10 @@ evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
|
||||
evhttp_read_trailer(evcon, req);
|
||||
return;
|
||||
case DATA_CORRUPTED:
|
||||
case DATA_TOO_LONG:/*separate error for this? XXX */
|
||||
case DATA_TOO_LONG:
|
||||
/* corrupted data */
|
||||
evhttp_connection_fail_(evcon,
|
||||
EVCON_HTTP_INVALID_HEADER);
|
||||
EVREQ_HTTP_DATA_TOO_LONG);
|
||||
return;
|
||||
case REQUEST_CANCELED:
|
||||
/* request canceled */
|
||||
@ -968,7 +975,7 @@ evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
|
||||
} else if (req->ntoread < 0) {
|
||||
/* Read until connection close. */
|
||||
if ((size_t)(req->body_size + evbuffer_get_length(buf)) < req->body_size) {
|
||||
evhttp_connection_fail_(evcon, EVCON_HTTP_INVALID_HEADER);
|
||||
evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -994,7 +1001,7 @@ evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
|
||||
/* failed body length test */
|
||||
event_debug(("Request body is too long"));
|
||||
evhttp_connection_fail_(evcon,
|
||||
EVCON_HTTP_INVALID_HEADER);
|
||||
EVREQ_HTTP_DATA_TOO_LONG);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1375,12 +1382,12 @@ evhttp_error_cb(struct bufferevent *bufev, short what, void *arg)
|
||||
}
|
||||
|
||||
if (what & BEV_EVENT_TIMEOUT) {
|
||||
evhttp_connection_fail_(evcon, EVCON_HTTP_TIMEOUT);
|
||||
evhttp_connection_fail_(evcon, EVREQ_HTTP_TIMEOUT);
|
||||
} else if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
|
||||
evhttp_connection_fail_(evcon, EVCON_HTTP_EOF);
|
||||
evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
|
||||
} else if (what == BEV_EVENT_CONNECTED) {
|
||||
} else {
|
||||
evhttp_connection_fail_(evcon, EVCON_HTTP_BUFFER_ERROR);
|
||||
evhttp_connection_fail_(evcon, EVREQ_HTTP_BUFFER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2032,7 +2039,7 @@ evhttp_get_body(struct evhttp_connection *evcon, struct evhttp_request *req)
|
||||
} else {
|
||||
if (evhttp_get_body_length(req) == -1) {
|
||||
evhttp_connection_fail_(evcon,
|
||||
EVCON_HTTP_INVALID_HEADER);
|
||||
EVREQ_HTTP_INVALID_HEADER);
|
||||
return;
|
||||
}
|
||||
if (req->kind == EVHTTP_REQUEST && req->ntoread < 1) {
|
||||
@ -2088,7 +2095,7 @@ evhttp_read_firstline(struct evhttp_connection *evcon,
|
||||
/* Error while reading, terminate */
|
||||
event_debug(("%s: bad header lines on "EV_SOCK_FMT"\n",
|
||||
__func__, EV_SOCK_ARG(evcon->fd)));
|
||||
evhttp_connection_fail_(evcon, EVCON_HTTP_INVALID_HEADER);
|
||||
evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
|
||||
return;
|
||||
} else if (res == MORE_DATA_EXPECTED) {
|
||||
/* Need more header lines */
|
||||
@ -2111,7 +2118,7 @@ evhttp_read_header(struct evhttp_connection *evcon,
|
||||
/* Error while reading, terminate */
|
||||
event_debug(("%s: bad header lines on "EV_SOCK_FMT"\n",
|
||||
__func__, EV_SOCK_ARG(fd)));
|
||||
evhttp_connection_fail_(evcon, EVCON_HTTP_INVALID_HEADER);
|
||||
evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
|
||||
return;
|
||||
} else if (res == MORE_DATA_EXPECTED) {
|
||||
/* Need more header lines */
|
||||
@ -2153,7 +2160,7 @@ evhttp_read_header(struct evhttp_connection *evcon,
|
||||
default:
|
||||
event_warnx("%s: bad header on "EV_SOCK_FMT, __func__,
|
||||
EV_SOCK_ARG(fd));
|
||||
evhttp_connection_fail_(evcon, EVCON_HTTP_INVALID_HEADER);
|
||||
evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
|
||||
break;
|
||||
}
|
||||
/* request may have been freed above */
|
||||
@ -2454,7 +2461,7 @@ evhttp_cancel_request(struct evhttp_request *req)
|
||||
* the connection.
|
||||
*/
|
||||
evhttp_connection_fail_(evcon,
|
||||
EVCON_HTTP_REQUEST_CANCEL);
|
||||
EVREQ_HTTP_REQUEST_CANCEL);
|
||||
|
||||
/* connection fail freed the request */
|
||||
return;
|
||||
@ -3764,6 +3771,13 @@ evhttp_request_set_chunked_cb(struct evhttp_request *req,
|
||||
req->chunk_cb = cb;
|
||||
}
|
||||
|
||||
void
|
||||
evhttp_request_set_error_cb(struct evhttp_request *req,
|
||||
void (*cb)(enum evhttp_request_error, void *))
|
||||
{
|
||||
req->error_cb = cb;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allows for inspection of the request URI
|
||||
*/
|
||||
|
@ -470,6 +470,47 @@ struct evhttp_request *evhttp_request_new(
|
||||
void evhttp_request_set_chunked_cb(struct evhttp_request *,
|
||||
void (*cb)(struct evhttp_request *, void *));
|
||||
|
||||
/**
|
||||
* The different error types supported by evhttp
|
||||
*
|
||||
* @see evhttp_request_set_error_cb()
|
||||
*/
|
||||
enum evhttp_request_error {
|
||||
/**
|
||||
* Timeout reached, also @see evhttp_connection_set_timeout()
|
||||
*/
|
||||
EVREQ_HTTP_TIMEOUT,
|
||||
/**
|
||||
* EOF reached
|
||||
*/
|
||||
EVREQ_HTTP_EOF,
|
||||
/**
|
||||
* Error while reading header, or invalid header
|
||||
*/
|
||||
EVREQ_HTTP_INVALID_HEADER,
|
||||
/**
|
||||
* Error encountered while reading or writing
|
||||
*/
|
||||
EVREQ_HTTP_BUFFER_ERROR,
|
||||
/**
|
||||
* The evhttp_cancel_request() called on this request.
|
||||
*/
|
||||
EVREQ_HTTP_REQUEST_CANCEL,
|
||||
/**
|
||||
* Body is greater then evhttp_connection_set_max_body_size()
|
||||
*/
|
||||
EVREQ_HTTP_DATA_TOO_LONG
|
||||
};
|
||||
/**
|
||||
* Set a callback for errors
|
||||
* @see evhttp_request_error for error types.
|
||||
*
|
||||
* On error, both the error callback and the regular callback will be called,
|
||||
* error callback is called before the regular callback.
|
||||
**/
|
||||
void evhttp_request_set_error_cb(struct evhttp_request *,
|
||||
void (*)(enum evhttp_request_error, void *));
|
||||
|
||||
/** Frees the request object and removes associated events. */
|
||||
void evhttp_request_free(struct evhttp_request *req);
|
||||
|
||||
|
@ -120,6 +120,13 @@ struct {
|
||||
* the regular callback.
|
||||
*/
|
||||
void (*chunk_cb)(struct evhttp_request *, void *);
|
||||
/*
|
||||
* Error callback - called when error is occured.
|
||||
* @see evhttp_request_error for error types.
|
||||
*
|
||||
* @see evhttp_request_set_error_cb()
|
||||
*/
|
||||
void (*error_cb)(enum evhttp_request_error, void *);
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -70,6 +70,19 @@ static struct event_base *exit_base;
|
||||
|
||||
static char const BASIC_REQUEST_BODY[] = "This is funny";
|
||||
|
||||
#define IMPL_HTTP_REQUEST_ERROR_CB(name, expecting_error) \
|
||||
static void \
|
||||
http_request_error_cb_with_##name##_(enum evhttp_request_error error, \
|
||||
void *arg) \
|
||||
{ \
|
||||
if (error != expecting_error) { \
|
||||
fprintf(stderr, "FAILED\n"); \
|
||||
exit(1); \
|
||||
} \
|
||||
test_ok = 1; \
|
||||
}
|
||||
IMPL_HTTP_REQUEST_ERROR_CB(cancel, EVREQ_HTTP_REQUEST_CANCEL)
|
||||
|
||||
static void http_basic_cb(struct evhttp_request *req, void *arg);
|
||||
static void http_chunked_cb(struct evhttp_request *req, void *arg);
|
||||
static void http_post_cb(struct evhttp_request *req, void *arg);
|
||||
@ -79,6 +92,7 @@ static void http_delay_cb(struct evhttp_request *req, void *arg);
|
||||
static void http_large_delay_cb(struct evhttp_request *req, void *arg);
|
||||
static void http_badreq_cb(struct evhttp_request *req, void *arg);
|
||||
static void http_dispatcher_cb(struct evhttp_request *req, void *arg);
|
||||
|
||||
static int
|
||||
http_bind(struct evhttp *myhttp, ev_uint16_t *pport, int ipv6)
|
||||
{
|
||||
@ -647,7 +661,7 @@ http_large_delay_cb(struct evhttp_request *req, void *arg)
|
||||
tv.tv_usec = 500000;
|
||||
|
||||
event_base_once(arg, -1, EV_TIMEOUT, http_delay_reply, req, &tv);
|
||||
evhttp_connection_fail_(delayed_client, EVCON_HTTP_EOF);
|
||||
evhttp_connection_fail_(delayed_client, EVREQ_HTTP_EOF);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1079,6 +1093,7 @@ http_cancel_test(void *arg)
|
||||
*/
|
||||
|
||||
req = evhttp_request_new(http_request_never_call, NULL);
|
||||
evhttp_request_set_error_cb(req, http_request_error_cb_with_cancel_);
|
||||
|
||||
/* Add the information that we care about */
|
||||
evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
|
||||
@ -1095,7 +1110,7 @@ http_cancel_test(void *arg)
|
||||
|
||||
event_base_dispatch(data->base);
|
||||
|
||||
tt_int_op(test_ok, ==, 2);
|
||||
tt_int_op(test_ok, ==, 3);
|
||||
|
||||
/* try to make another request over the same connection */
|
||||
test_ok = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user