mirror of
https://github.com/cuberite/libevent.git
synced 2025-08-04 01:36:23 -04:00
http: lingering close (like nginx have) for entity-too-large
By lingering close I mean something what nginx have for this name, by this term I mean that we need to read all the body even if it's size greater then `max_body_size`, otherwise browsers on win32 (including chrome) failed read the http status - entity-too-large (while on linux chrome for instance are good), and also this includes badly written http clients. Refs: #321 v2: do this only under EVHTTP_SERVER_LINGERING_CLOSE
This commit is contained in:
parent
680742e166
commit
9fde5189df
@ -154,6 +154,7 @@ struct evhttp {
|
|||||||
|
|
||||||
size_t default_max_headers_size;
|
size_t default_max_headers_size;
|
||||||
ev_uint64_t default_max_body_size;
|
ev_uint64_t default_max_body_size;
|
||||||
|
int flags;
|
||||||
const char *default_content_type;
|
const char *default_content_type;
|
||||||
|
|
||||||
/* Bitmask of all HTTP methods that we accept and pass to user
|
/* Bitmask of all HTTP methods that we accept and pass to user
|
||||||
|
46
http.c
46
http.c
@ -984,6 +984,25 @@ evhttp_read_trailer(struct evhttp_connection *evcon, struct evhttp_request *req)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
evhttp_lingering_close(struct evhttp_connection *evcon, struct evhttp_request *req)
|
||||||
|
{
|
||||||
|
struct evbuffer *buf = bufferevent_get_input(evcon->bufev);
|
||||||
|
|
||||||
|
size_t n = evbuffer_get_length(buf);
|
||||||
|
if (n > (size_t) req->ntoread)
|
||||||
|
n = (size_t) req->ntoread;
|
||||||
|
req->ntoread -= n;
|
||||||
|
req->body_size += n;
|
||||||
|
|
||||||
|
event_debug(("Request body is too long, left " EV_SIZE_FMT,
|
||||||
|
EV_SIZE_ARG(req->ntoread)));
|
||||||
|
|
||||||
|
evbuffer_drain(buf, n);
|
||||||
|
if (!req->ntoread)
|
||||||
|
evhttp_connection_fail_(evcon, EVREQ_HTTP_DATA_TOO_LONG);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
|
evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
|
||||||
{
|
{
|
||||||
@ -1037,9 +1056,12 @@ evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
|
|||||||
(size_t)req->ntoread > req->evcon->max_body_size)) {
|
(size_t)req->ntoread > req->evcon->max_body_size)) {
|
||||||
/* XXX: The above casted comparison must checked for overflow */
|
/* XXX: The above casted comparison must checked for overflow */
|
||||||
/* failed body length test */
|
/* failed body length test */
|
||||||
event_debug(("Request body is too long"));
|
|
||||||
evhttp_connection_fail_(evcon,
|
if (evcon->flags & EVHTTP_CON_LINGERING_CLOSE)
|
||||||
EVREQ_HTTP_DATA_TOO_LONG);
|
evhttp_lingering_close(evcon, req);
|
||||||
|
else
|
||||||
|
evhttp_connection_fail_(evcon, EVREQ_HTTP_DATA_TOO_LONG);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1055,7 +1077,7 @@ evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req->ntoread == 0) {
|
if (!req->ntoread) {
|
||||||
bufferevent_disable(evcon->bufev, EV_READ);
|
bufferevent_disable(evcon->bufev, EV_READ);
|
||||||
/* Completed content length */
|
/* Completed content length */
|
||||||
evhttp_connection_done(evcon);
|
evhttp_connection_done(evcon);
|
||||||
@ -3719,6 +3741,20 @@ evhttp_set_timeout_tv(struct evhttp* http, const struct timeval* tv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int evhttp_set_flags(struct evhttp *http, int flags)
|
||||||
|
{
|
||||||
|
int avail_flags = 0;
|
||||||
|
avail_flags |= EVHTTP_SERVER_LINGERING_CLOSE;
|
||||||
|
|
||||||
|
if (flags & ~avail_flags)
|
||||||
|
return 1;
|
||||||
|
http->flags &= ~avail_flags;
|
||||||
|
|
||||||
|
http->flags |= flags;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
evhttp_set_max_headers_size(struct evhttp* http, ev_ssize_t max_headers_size)
|
evhttp_set_max_headers_size(struct evhttp* http, ev_ssize_t max_headers_size)
|
||||||
{
|
{
|
||||||
@ -4091,6 +4127,8 @@ evhttp_get_request_connection(
|
|||||||
|
|
||||||
evcon->max_headers_size = http->default_max_headers_size;
|
evcon->max_headers_size = http->default_max_headers_size;
|
||||||
evcon->max_body_size = http->default_max_body_size;
|
evcon->max_body_size = http->default_max_body_size;
|
||||||
|
if (http->flags & EVHTTP_SERVER_LINGERING_CLOSE)
|
||||||
|
evcon->flags |= EVHTTP_CON_LINGERING_CLOSE;
|
||||||
|
|
||||||
evcon->flags |= EVHTTP_CON_INCOMING;
|
evcon->flags |= EVHTTP_CON_INCOMING;
|
||||||
evcon->state = EVCON_READING_FIRSTLINE;
|
evcon->state = EVCON_READING_FIRSTLINE;
|
||||||
|
@ -373,6 +373,19 @@ void evhttp_set_timeout(struct evhttp *http, int timeout_in_secs);
|
|||||||
EVENT2_EXPORT_SYMBOL
|
EVENT2_EXPORT_SYMBOL
|
||||||
void evhttp_set_timeout_tv(struct evhttp *http, const struct timeval* tv);
|
void evhttp_set_timeout_tv(struct evhttp *http, const struct timeval* tv);
|
||||||
|
|
||||||
|
/* Read all the clients body, and only after this respond with an error if the
|
||||||
|
* clients body exceed max_body_size */
|
||||||
|
#define EVHTTP_SERVER_LINGERING_CLOSE 0x0001
|
||||||
|
/**
|
||||||
|
* Set connection flags for HTTP server.
|
||||||
|
*
|
||||||
|
* @see EVHTTP_SERVER_*
|
||||||
|
* @return 0 on success, otherwise non zero (for example if flag doesn't
|
||||||
|
* supported).
|
||||||
|
*/
|
||||||
|
EVENT2_EXPORT_SYMBOL
|
||||||
|
int evhttp_set_flags(struct evhttp *http, int flags);
|
||||||
|
|
||||||
/* Request/Response functionality */
|
/* Request/Response functionality */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -643,6 +656,8 @@ void evhttp_connection_set_family(struct evhttp_connection *evcon,
|
|||||||
* connection, but if at that time we have some data to send then we
|
* connection, but if at that time we have some data to send then we
|
||||||
* can send get EPIPE and fail, while we can read that HTTP error. */
|
* can send get EPIPE and fail, while we can read that HTTP error. */
|
||||||
#define EVHTTP_CON_READ_ON_WRITE_ERROR 0x0010
|
#define EVHTTP_CON_READ_ON_WRITE_ERROR 0x0010
|
||||||
|
/* @see EVHTTP_SERVER_LINGERING_CLOSE */
|
||||||
|
#define EVHTTP_CON_LINGERING_CLOSE 0x0020
|
||||||
/* Padding for public flags, @see EVHTTP_CON_* in http-internal.h */
|
/* Padding for public flags, @see EVHTTP_CON_* in http-internal.h */
|
||||||
#define EVHTTP_CON_PUBLIC_FLAGS_END 0x100000
|
#define EVHTTP_CON_PUBLIC_FLAGS_END 0x100000
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user