]> granicus.if.org Git - libevent/commitdiff
Handle evhttp PUT/POST requests with an empty body
authorNick Mathewson <nickm@torproject.org>
Wed, 24 Nov 2010 01:31:28 +0000 (20:31 -0500)
committerNick Mathewson <nickm@torproject.org>
Wed, 24 Nov 2010 01:31:28 +0000 (20:31 -0500)
When we call evhttp_get_bodylen() [when transfer-encoding isn't set],
having req->ntoread == -1 means that we have no content-length.  But a
request with no content-length has no body!  We were treating the
absent content-length as meaning "read till closed", which only holds
for replies, not requests.

This patch also allows PATCH requests to have a body.

http.c

diff --git a/http.c b/http.c
index b08e04c5b8dffea9b254726f292f3adf4b174ca4..4464bbebfe807557524584f381478866da578579 100644 (file)
--- a/http.c
+++ b/http.c
@@ -1734,6 +1734,28 @@ evhttp_get_body_length(struct evhttp_request *req)
        return (0);
 }
 
+static int
+evhttp_method_may_have_body(enum evhttp_cmd_type type)
+{
+       switch (type) {
+       case EVHTTP_REQ_POST:
+       case EVHTTP_REQ_PUT:
+       case EVHTTP_REQ_PATCH:
+               return 1;
+       case EVHTTP_REQ_TRACE:
+               return 0;
+       /* XXX May any of the below methods have a body? */
+       case EVHTTP_REQ_GET:
+       case EVHTTP_REQ_HEAD:
+       case EVHTTP_REQ_DELETE:
+       case EVHTTP_REQ_OPTIONS:
+       case EVHTTP_REQ_CONNECT:
+               return 0;
+       default:
+               return 0;
+       }
+}
+
 static void
 evhttp_get_body(struct evhttp_connection *evcon, struct evhttp_request *req)
 {
@@ -1741,7 +1763,7 @@ evhttp_get_body(struct evhttp_connection *evcon, struct evhttp_request *req)
 
        /* If this is a request without a body, then we are done */
        if (req->kind == EVHTTP_REQUEST &&
-           (req->type != EVHTTP_REQ_POST && req->type != EVHTTP_REQ_PUT)) {
+           !evhttp_method_may_have_body(req->type)) {
                evhttp_connection_done(evcon);
                return;
        }
@@ -1756,6 +1778,12 @@ evhttp_get_body(struct evhttp_connection *evcon, struct evhttp_request *req)
                            EVCON_HTTP_INVALID_HEADER);
                        return;
                }
+               if (req->kind == EVHTTP_REQUEST && req->ntoread < 1) {
+                       /* An incoming request with no content-length and no
+                        * transfer-encoding has no body. */
+                       evhttp_connection_done(evcon);
+                       return;
+               }
        }
        evhttp_read_body(evcon, req);
        /* note the request may have been freed in evhttp_read_body */