}
}
+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
evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
{
(size_t)req->ntoread > req->evcon->max_body_size)) {
/* XXX: The above casted comparison must checked for overflow */
/* failed body length test */
- event_debug(("Request body is too long"));
- evhttp_connection_fail_(evcon,
- EVREQ_HTTP_DATA_TOO_LONG);
+
+ if (evcon->flags & EVHTTP_CON_LINGERING_CLOSE)
+ evhttp_lingering_close(evcon, req);
+ else
+ evhttp_connection_fail_(evcon, EVREQ_HTTP_DATA_TOO_LONG);
+
return;
}
}
}
- if (req->ntoread == 0) {
+ if (!req->ntoread) {
bufferevent_disable(evcon->bufev, EV_READ);
/* Completed content length */
evhttp_connection_done(evcon);
}
}
+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
evhttp_set_max_headers_size(struct evhttp* http, ev_ssize_t max_headers_size)
{
evcon->max_headers_size = http->default_max_headers_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->state = EVCON_READING_FIRSTLINE;
EVENT2_EXPORT_SYMBOL
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 */
/**
* 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. */
#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 */
#define EVHTTP_CON_PUBLIC_FLAGS_END 0x100000
/**