Content-length not required if request body is empty

This commit is contained in:
robert committed 2026-03-12 05:54:21 -04:00
1 parent 70f14336f1
commit 81b61d335f
3 files changed
+14 -30

No files matched your search

+6 -13
View File
@@ -1999,17 +1999,9 @@ int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm) {
// responses. If HTTP response does not have Content-Length set, then
// body is read until socket is closed, i.e. body.len is infinite (~0).
//
// For HTTP requests though, according to
// http://tools.ietf.org/html/rfc7231#section-8.1.3,
// only POST and PUT methods have defined body semantics.
// Therefore, if Content-Length is not specified and methods are
// not one of PUT or POST, set body length to 0.
//
// So, if it is HTTP request, and Content-Length is not set,
// and method is not (PUT or POST) then reset body length to zero.
if (hm->body.len == (size_t) ~0 && !is_response &&
mg_strcasecmp(hm->method, mg_str("PUT")) != 0 &&
mg_strcasecmp(hm->method, mg_str("POST")) != 0) {
// For HTTP requests though, if Content-Length is not specified
// set body length to 0.
if (hm->body.len == (size_t) ~0 && !is_response) {
hm->body.len = 0;
hm->message.len = (size_t) req_len;
}
@@ -2740,9 +2732,10 @@ static void http_cb(struct mg_connection *c, int ev, void *ev_data) {
if (!is_response && (mg_strcasecmp(hm.method, mg_str("POST")) == 0 ||
mg_strcasecmp(hm.method, mg_str("PUT")) == 0)) {
// POST and PUT should include an entity body. Therefore, they should
// contain a Content-length header. Other requests can also contain a
// contain a Content-length header (unless the body length is 0, in
// which case it can be omitted). Other requests can also contain a
// body, but their content has no defined semantics (RFC 7231)
require_content_len = true;
if (hm.body.len != 0) require_content_len = true;
ofs += (size_t) n; // this request has been processed
} else if (is_response) {
// HTTP spec 7.2 Entity body: All other responses must include a body
+6 -13
View File
@@ -317,17 +317,9 @@ int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm) {
// responses. If HTTP response does not have Content-Length set, then
// body is read until socket is closed, i.e. body.len is infinite (~0).
//
// For HTTP requests though, according to
// http://tools.ietf.org/html/rfc7231#section-8.1.3,
// only POST and PUT methods have defined body semantics.
// Therefore, if Content-Length is not specified and methods are
// not one of PUT or POST, set body length to 0.
//
// So, if it is HTTP request, and Content-Length is not set,
// and method is not (PUT or POST) then reset body length to zero.
if (hm->body.len == (size_t) ~0 && !is_response &&
mg_strcasecmp(hm->method, mg_str("PUT")) != 0 &&
mg_strcasecmp(hm->method, mg_str("POST")) != 0) {
// For HTTP requests though, if Content-Length is not specified
// set body length to 0.
if (hm->body.len == (size_t) ~0 && !is_response) {
hm->body.len = 0;
hm->message.len = (size_t) req_len;
}
@@ -1058,9 +1050,10 @@ static void http_cb(struct mg_connection *c, int ev, void *ev_data) {
if (!is_response && (mg_strcasecmp(hm.method, mg_str("POST")) == 0 ||
mg_strcasecmp(hm.method, mg_str("PUT")) == 0)) {
// POST and PUT should include an entity body. Therefore, they should
// contain a Content-length header. Other requests can also contain a
// contain a Content-length header (unless the body length is 0, in
// which case it can be omitted). Other requests can also contain a
// body, but their content has no defined semantics (RFC 7231)
require_content_len = true;
if (hm.body.len != 0) require_content_len = true;
ofs += (size_t) n; // this request has been processed
} else if (is_response) {
// HTTP spec 7.2 Entity body: All other responses must include a body
+2 -4
View File
@@ -1672,14 +1672,12 @@ static void test_http_no_content_length(void) {
// 12348 is in TIME_WAIT, use another port
mg_mgr_init(&mgr);
mg_http_listen(&mgr, url2, f41, (void *) NULL);
ASSERT(fetch(&mgr, buf, url2, "POST / HTTP/1.1\r\n\r\n") == 411);
ASSERT(fetch(&mgr, buf, url2, "POST / HTTP/1.1\r\n\r\n") == 200);
ASSERT(fetch(&mgr, buf, url2, "HTTP/1.1 200\r\n\r\n") == 411);
ASSERT(fetch(&mgr, buf, url2, "HTTP/1.1 100\r\n\r\n") != 411);
ASSERT(fetch(&mgr, buf, url2, "HTTP/1.1 304\r\n\r\n") != 411);
ASSERT(fetch(&mgr, buf, url2, "HTTP/1.1 305\r\n\r\n") == 411);
ASSERT(fetch(&mgr, buf, url2, post_req) != 411);
// Check it is processed only once (see #2811)
ASSERT(fpr(&mgr, buf, url2, "POST / HTTP/1.1\r\n\r\n") == 411);
mg_mgr_free(&mgr);
ASSERT(mgr.conns == NULL);
}
@@ -1844,7 +1842,7 @@ static void test_http_parse(void) {
{
const char *s = "POST /x HTTP/1.0\n\n";
ASSERT(mg_http_parse(s, strlen(s), &req) == (int) strlen(s));
ASSERT(req.body.len == (size_t) ~0);
ASSERT(req.body.len == 0);
}
{