From ebf9ee089bb612186d73927b508cb4ad20716c5e Mon Sep 17 00:00:00 2001 From: Sergey Lyubka <valenok@gmail.com> Date: Thu, 5 Dec 2013 11:12:07 +0000 Subject: [PATCH] Do not send 500 when timing out getreq() --- build/src/http_client.c | 6 +++--- build/src/internal.h | 2 +- build/src/mongoose.c | 38 ++++++++++++++++++++-------------- mongoose.c | 46 ++++++++++++++++++++++++----------------- test/test.pl | 2 +- 5 files changed, 55 insertions(+), 39 deletions(-) diff --git a/build/src/http_client.c b/build/src/http_client.c index 0e4a6c7af..1d812afdb 100644 --- a/build/src/http_client.c +++ b/build/src/http_client.c @@ -78,17 +78,17 @@ struct mg_connection *mg_download(const char *host, int port, int use_ssl, char *ebuf, size_t ebuf_len, const char *fmt, ...) { struct mg_connection *conn; + const char *msg = NULL; va_list ap; va_start(ap, fmt); - ebuf[0] = '\0'; if ((conn = mg_connect(host, port, use_ssl, ebuf, ebuf_len)) == NULL) { } else if (mg_vprintf(conn, fmt, ap) <= 0) { snprintf(ebuf, ebuf_len, "%s", "Error sending request"); } else { - getreq(conn, ebuf, ebuf_len); + msg = getreq(conn); } - if (ebuf[0] != '\0' && conn != NULL) { + if (msg != NULL && conn != NULL) { mg_close_connection(conn); conn = NULL; } diff --git a/build/src/internal.h b/build/src/internal.h index 11c2e85e2..16079b10e 100644 --- a/build/src/internal.h +++ b/build/src/internal.h @@ -449,7 +449,7 @@ static void send_http_error(struct mg_connection *, int, const char *, PRINTF_ARGS(4, 5); static void cry(struct mg_connection *conn, PRINTF_FORMAT_STRING(const char *fmt), ...) PRINTF_ARGS(2, 3); -static int getreq(struct mg_connection *conn, char *ebuf, size_t ebuf_len); +static const char *getreq(struct mg_connection *conn); #ifdef USE_LUA #include "lua_5.2.1.h" diff --git a/build/src/mongoose.c b/build/src/mongoose.c index bee96cc4a..b9122dc92 100644 --- a/build/src/mongoose.c +++ b/build/src/mongoose.c @@ -1023,22 +1023,24 @@ static int is_valid_uri(const char *uri) { return uri[0] == '/' || (uri[0] == '*' && uri[1] == '\0'); } -static int getreq(struct mg_connection *conn, char *ebuf, size_t ebuf_len) { - const char *cl; +static const char *getreq(struct mg_connection *conn) { + const char *cl, *ret = NULL; - ebuf[0] = '\0'; reset_per_request_attributes(conn); conn->request_len = read_request(NULL, conn, conn->buf, conn->buf_size, &conn->data_len); assert(conn->request_len < 0 || conn->data_len >= conn->request_len); if (conn->request_len == 0 && conn->data_len == conn->buf_size) { - snprintf(ebuf, ebuf_len, "%s", "Request Too Large"); + conn->status_code = 413; + ret = "Request Entity Too Large"; } else if (conn->request_len <= 0) { - snprintf(ebuf, ebuf_len, "%s", "Client closed connection"); + conn->status_code = 0; + ret = "Client closed connection"; } else if (parse_http_message(conn->buf, conn->buf_size, &conn->request_info) <= 0) { - snprintf(ebuf, ebuf_len, "Bad request: [%.*s]", conn->data_len, conn->buf); + conn->status_code = 400; + ret = "Bad Request"; } else { // Request is valid. Set content_len attribute by parsing Content-Length // If Content-Length is absent, set content_len to 0 if request is GET, @@ -1057,13 +1059,14 @@ static int getreq(struct mg_connection *conn, char *ebuf, size_t ebuf_len) { } conn->birth_time = time(NULL); } - return ebuf[0] == '\0'; + + return ret; } static void process_new_connection(struct mg_connection *conn) { struct mg_request_info *ri = &conn->request_info; int keep_alive_enabled, keep_alive, discard_len; - char ebuf[100]; + const char *msg = NULL; keep_alive_enabled = !strcmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes"); keep_alive = 0; @@ -1072,19 +1075,24 @@ static void process_new_connection(struct mg_connection *conn) { // to crule42. conn->data_len = 0; do { - if (!getreq(conn, ebuf, sizeof(ebuf))) { - send_http_error(conn, 500, "Server Error", "%s", ebuf); + if ((msg = getreq(conn)) != NULL) { conn->must_close = 1; } else if (!is_valid_uri(conn->request_info.uri)) { - snprintf(ebuf, sizeof(ebuf), "Invalid URI: [%s]", ri->uri); - send_http_error(conn, 400, "Bad Request", "%s", ebuf); + msg = "Bad Request"; + conn->status_code = 400; } else if (strcmp(ri->http_version, "1.0") && strcmp(ri->http_version, "1.1")) { - snprintf(ebuf, sizeof(ebuf), "Bad HTTP version: [%s]", ri->http_version); - send_http_error(conn, 505, "Bad HTTP version", "%s", ebuf); + msg = "Bad HTTP Version"; + conn->status_code = 505; } - if (ebuf[0] == '\0') { + if (msg != NULL) { + // Do not send anything to the client on timeout + // see https://github.com/cesanta/mongoose/issues/261 + if (conn->status_code > 0) { + send_http_error(conn, conn->status_code, msg, "%s", ""); + } + } else { handle_request(conn); call_user(MG_REQUEST_END, conn, (void *) (long) conn->status_code); log_access(conn); diff --git a/mongoose.c b/mongoose.c index 753092372..993152cf6 100644 --- a/mongoose.c +++ b/mongoose.c @@ -449,7 +449,7 @@ static void send_http_error(struct mg_connection *, int, const char *, PRINTF_ARGS(4, 5); static void cry(struct mg_connection *conn, PRINTF_FORMAT_STRING(const char *fmt), ...) PRINTF_ARGS(2, 3); -static int getreq(struct mg_connection *conn, char *ebuf, size_t ebuf_len); +static const char *getreq(struct mg_connection *conn); #ifdef USE_LUA #include "lua_5.2.1.h" @@ -2304,17 +2304,17 @@ struct mg_connection *mg_download(const char *host, int port, int use_ssl, char *ebuf, size_t ebuf_len, const char *fmt, ...) { struct mg_connection *conn; + const char *msg = NULL; va_list ap; va_start(ap, fmt); - ebuf[0] = '\0'; if ((conn = mg_connect(host, port, use_ssl, ebuf, ebuf_len)) == NULL) { } else if (mg_vprintf(conn, fmt, ap) <= 0) { snprintf(ebuf, ebuf_len, "%s", "Error sending request"); } else { - getreq(conn, ebuf, ebuf_len); + msg = getreq(conn); } - if (ebuf[0] != '\0' && conn != NULL) { + if (msg != NULL && conn != NULL) { mg_close_connection(conn); conn = NULL; } @@ -4894,22 +4894,24 @@ static int is_valid_uri(const char *uri) { return uri[0] == '/' || (uri[0] == '*' && uri[1] == '\0'); } -static int getreq(struct mg_connection *conn, char *ebuf, size_t ebuf_len) { - const char *cl; +static const char *getreq(struct mg_connection *conn) { + const char *cl, *ret = NULL; - ebuf[0] = '\0'; reset_per_request_attributes(conn); conn->request_len = read_request(NULL, conn, conn->buf, conn->buf_size, &conn->data_len); assert(conn->request_len < 0 || conn->data_len >= conn->request_len); if (conn->request_len == 0 && conn->data_len == conn->buf_size) { - snprintf(ebuf, ebuf_len, "%s", "Request Too Large"); + conn->status_code = 413; + ret = "Request Entity Too Large"; } else if (conn->request_len <= 0) { - snprintf(ebuf, ebuf_len, "%s", "Client closed connection"); + conn->status_code = 0; + ret = "Client closed connection"; } else if (parse_http_message(conn->buf, conn->buf_size, &conn->request_info) <= 0) { - snprintf(ebuf, ebuf_len, "Bad request: [%.*s]", conn->data_len, conn->buf); + conn->status_code = 400; + ret = "Bad Request"; } else { // Request is valid. Set content_len attribute by parsing Content-Length // If Content-Length is absent, set content_len to 0 if request is GET, @@ -4928,13 +4930,14 @@ static int getreq(struct mg_connection *conn, char *ebuf, size_t ebuf_len) { } conn->birth_time = time(NULL); } - return ebuf[0] == '\0'; + + return ret; } static void process_new_connection(struct mg_connection *conn) { struct mg_request_info *ri = &conn->request_info; int keep_alive_enabled, keep_alive, discard_len; - char ebuf[100]; + const char *msg = NULL; keep_alive_enabled = !strcmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes"); keep_alive = 0; @@ -4943,19 +4946,24 @@ static void process_new_connection(struct mg_connection *conn) { // to crule42. conn->data_len = 0; do { - if (!getreq(conn, ebuf, sizeof(ebuf))) { - send_http_error(conn, 500, "Server Error", "%s", ebuf); + if ((msg = getreq(conn)) != NULL) { conn->must_close = 1; } else if (!is_valid_uri(conn->request_info.uri)) { - snprintf(ebuf, sizeof(ebuf), "Invalid URI: [%s]", ri->uri); - send_http_error(conn, 400, "Bad Request", "%s", ebuf); + msg = "Bad Request"; + conn->status_code = 400; } else if (strcmp(ri->http_version, "1.0") && strcmp(ri->http_version, "1.1")) { - snprintf(ebuf, sizeof(ebuf), "Bad HTTP version: [%s]", ri->http_version); - send_http_error(conn, 505, "Bad HTTP version", "%s", ebuf); + msg = "Bad HTTP Version"; + conn->status_code = 505; } - if (ebuf[0] == '\0') { + if (msg != NULL) { + // Do not send anything to the client on timeout + // see https://github.com/cesanta/mongoose/issues/261 + if (conn->status_code > 0) { + send_http_error(conn, conn->status_code, msg, "%s", ""); + } + } else { handle_request(conn); call_user(MG_REQUEST_END, conn, (void *) (long) conn->status_code); log_access(conn); diff --git a/test/test.pl b/test/test.pl index 3f7b5b650..de4a8fcaf 100644 --- a/test/test.pl +++ b/test/test.pl @@ -217,7 +217,7 @@ write_file("$root/a+.txt", ''); o("GET /a+.txt HTTP/1.0\n\n", 'HTTP/1.1 200 OK', 'URL-decoding, + in URI'); # Test HTTP version parsing -o("GET / HTTPX/1.0\r\n\r\n", '^HTTP/1.1 500', 'Bad HTTP Version', 0); +o("GET / HTTPX/1.0\r\n\r\n", '^HTTP/1.1 400', 'Bad HTTP Version', 0); o("GET / HTTP/x.1\r\n\r\n", '^HTTP/1.1 505', 'Bad HTTP maj Version', 0); o("GET / HTTP/1.1z\r\n\r\n", '^HTTP/1.1 505', 'Bad HTTP min Version', 0); o("GET / HTTP/02.0\r\n\r\n", '^HTTP/1.1 505', 'HTTP Version >1.1', 0); -- GitLab