mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-15 10:29:47 +00:00
mg_read() does not block on content_len=0. mg_read() reads until socket is closed if content-length is not provided
This commit is contained in:
1 parent
70154f6c23
commit
5153eebc9b
4 files changed
+43
-42
No files matched your search
+6
-10
@@ -734,10 +734,8 @@ int mg_read(struct mg_connection *conn, void *buf, int len) {
|
||||
int n, buffered_len, nread = 0;
|
||||
int64_t left;
|
||||
|
||||
// If Content-Length is not set, read until socket is closed
|
||||
if (conn->content_len <= 0) {
|
||||
conn->content_len = INT64_MAX;
|
||||
conn->must_close = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// conn->buf body
|
||||
@@ -1790,7 +1788,7 @@ static int forward_body_data(struct mg_connection *conn, FILE *fp,
|
||||
expect = mg_get_header(conn, "Expect");
|
||||
assert(fp != NULL);
|
||||
|
||||
if (conn->content_len == -1) {
|
||||
if (conn->content_len == INT64_MAX) {
|
||||
send_http_error(conn, 411, "Length Required", "%s", "");
|
||||
} else if (expect != NULL && mg_strcasecmp(expect, "100-continue")) {
|
||||
send_http_error(conn, 417, "Expectation Failed", "%s", "");
|
||||
@@ -3644,14 +3642,12 @@ static int getreq(struct mg_connection *conn, char *ebuf, size_t ebuf_len) {
|
||||
&conn->request_info) <= 0) {
|
||||
snprintf(ebuf, ebuf_len, "Bad request: [%.*s]", conn->data_len, conn->buf);
|
||||
} else {
|
||||
// Request is valid
|
||||
// Request is valid. Set content_len attribute by parsing Content-Length
|
||||
// If Content-Length is absent, instruct mg_read() to read from the socket
|
||||
// until socket is closed.
|
||||
conn->content_len = INT64_MAX;
|
||||
if ((cl = get_header(&conn->request_info, "Content-Length")) != NULL) {
|
||||
conn->content_len = strtoll(cl, NULL, 10);
|
||||
} else if (!mg_strcasecmp(conn->request_info.request_method, "POST") ||
|
||||
!mg_strcasecmp(conn->request_info.request_method, "PUT")) {
|
||||
conn->content_len = -1;
|
||||
} else {
|
||||
conn->content_len = 0;
|
||||
}
|
||||
conn->birth_time = time(NULL);
|
||||
}
|
||||
|
||||
+6
-10
@@ -2045,10 +2045,8 @@ int mg_read(struct mg_connection *conn, void *buf, int len) {
|
||||
int n, buffered_len, nread = 0;
|
||||
int64_t left;
|
||||
|
||||
// If Content-Length is not set, read until socket is closed
|
||||
if (conn->content_len <= 0) {
|
||||
conn->content_len = INT64_MAX;
|
||||
conn->must_close = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// conn->buf body
|
||||
@@ -3101,7 +3099,7 @@ static int forward_body_data(struct mg_connection *conn, FILE *fp,
|
||||
expect = mg_get_header(conn, "Expect");
|
||||
assert(fp != NULL);
|
||||
|
||||
if (conn->content_len == -1) {
|
||||
if (conn->content_len == INT64_MAX) {
|
||||
send_http_error(conn, 411, "Length Required", "%s", "");
|
||||
} else if (expect != NULL && mg_strcasecmp(expect, "100-continue")) {
|
||||
send_http_error(conn, 417, "Expectation Failed", "%s", "");
|
||||
@@ -4955,14 +4953,12 @@ static int getreq(struct mg_connection *conn, char *ebuf, size_t ebuf_len) {
|
||||
&conn->request_info) <= 0) {
|
||||
snprintf(ebuf, ebuf_len, "Bad request: [%.*s]", conn->data_len, conn->buf);
|
||||
} else {
|
||||
// Request is valid
|
||||
// Request is valid. Set content_len attribute by parsing Content-Length
|
||||
// By default, in the absence of Content-Length, instruct mg_read()
|
||||
// to read from the socket until the socket is closed.
|
||||
conn->content_len = INT64_MAX;
|
||||
if ((cl = get_header(&conn->request_info, "Content-Length")) != NULL) {
|
||||
conn->content_len = strtoll(cl, NULL, 10);
|
||||
} else if (!mg_strcasecmp(conn->request_info.request_method, "POST") ||
|
||||
!mg_strcasecmp(conn->request_info.request_method, "PUT")) {
|
||||
conn->content_len = -1;
|
||||
} else {
|
||||
conn->content_len = 0;
|
||||
}
|
||||
conn->birth_time = time(NULL);
|
||||
}
|
||||
|
||||
+2
-1
@@ -180,7 +180,8 @@ o("GET /dir%20with%20spaces/桌面/ HTTP/1.0\r\n\r\n", 'куку!',
|
||||
'Non-ascii chars in path');
|
||||
o("GET /hello.txt HTTP/1.1\nConnection: close\nRange: bytes=3-50\r\n\r\n",
|
||||
'Content-Length: 15\s', 'Range past the file end');
|
||||
o("GET /hello.txt HTTP/1.1\n\n GET /hello.txt HTTP/1.0\n\n",
|
||||
o("GET /hello.txt HTTP/1.1\nContent-Length: 0\n\n ".
|
||||
"GET /hello.txt HTTP/1.0\nContent-Length: 0\n\n",
|
||||
'HTTP/1.1 200.+keep-alive.+HTTP/1.1 200.+close',
|
||||
'Request pipelining', 2);
|
||||
|
||||
|
||||
+29
-21
@@ -220,6 +220,15 @@ static int event_handler(struct mg_event *event) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!strcmp(ri->uri, "/zerolen")) {
|
||||
char buf[100];
|
||||
mg_printf(event->conn, "%s",
|
||||
"HTTP/1.0 200 OK\r\nContent-Length: 2\r\n\r\nok");
|
||||
printf("[%d]\n", mg_read(event->conn, buf, sizeof(buf)));
|
||||
ASSERT(mg_read(event->conn, buf, sizeof(buf)) == 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!strcmp(ri->uri, "/upload")) {
|
||||
test_upload(event->conn, "lua_5.2.1.h", "./f1.txt");
|
||||
test_upload(event->conn, "lsqlite3.c", "./f2.txt");
|
||||
@@ -281,6 +290,16 @@ static void test_mg_download(void) {
|
||||
"GET / HTTP/1.0\r\n\r\n")) != NULL);
|
||||
mg_close_connection(conn);
|
||||
|
||||
// POST with "Content-Length: 0", must not block
|
||||
ASSERT((conn = mg_download("localhost", atoi(HTTPS_PORT), 1,
|
||||
ebuf, sizeof(ebuf), "%s",
|
||||
"POST /zerolen HTTP/1.1\r\n"
|
||||
"Content-Lengh: 0\r\n\r\n ")) != NULL);
|
||||
ASSERT((p1 = read_conn(conn, &len1)) != NULL);
|
||||
ASSERT(len1 = 2);
|
||||
ASSERT(memcmp(p1, "ok", 2) == 0);
|
||||
mg_close_connection(conn);
|
||||
|
||||
// Fetch main.c, should succeed
|
||||
ASSERT((conn = mg_download("localhost", port, 1, ebuf, sizeof(ebuf), "%s",
|
||||
"GET /main.c HTTP/1.0\r\n\r\n")) != NULL);
|
||||
@@ -333,27 +352,16 @@ static void test_mg_upload(void) {
|
||||
ASSERT((file2_data = read_file("lsqlite3.c", &file2_len)) != NULL);
|
||||
post_data = NULL;
|
||||
post_data_len = alloc_printf(&post_data, 0,
|
||||
// First file
|
||||
"--%s\r\n"
|
||||
"Content-Disposition: form-data; "
|
||||
"name=\"file\"; "
|
||||
"filename=\"%s\"\r\n\r\n"
|
||||
"%.*s\r\n"
|
||||
|
||||
// Second file
|
||||
"--%s\r\n"
|
||||
"Content-Disposition: form-data; "
|
||||
"name=\"file\"; "
|
||||
"filename=\"%s\"\r\n\r\n"
|
||||
"%.*s\r\n"
|
||||
|
||||
// Final boundary
|
||||
"--%s--\r\n",
|
||||
boundary, "f1.txt",
|
||||
file_len, file_data,
|
||||
boundary, "f2.txt",
|
||||
file2_len, file2_data,
|
||||
boundary);
|
||||
// First file
|
||||
"--%s\r\n" "Content-Disposition: form-data; " "name=\"file\"; "
|
||||
"filename=\"%s\"\r\n\r\n" "%.*s\r\n"
|
||||
// Second file
|
||||
"--%s\r\n" "Content-Disposition: form-data; " "name=\"file\"; "
|
||||
"filename=\"%s\"\r\n\r\n" "%.*s\r\n"
|
||||
// Final boundary
|
||||
"--%s--\r\n",
|
||||
boundary, "f1.txt", file_len, file_data, boundary, "f2.txt",
|
||||
file2_len, file2_data, boundary);
|
||||
ASSERT(post_data_len > 0);
|
||||
ASSERT((conn = mg_download("localhost", atoi(HTTPS_PORT), 1,
|
||||
ebuf, sizeof(ebuf),
|
||||
|
||||
Reference in new issue
Block a user