Add max_document_size checking for multipart PUT requests

Previously multipart/related PUT requests didn't check maximum request sizes.

This commit checks content-length and compares that with the maximum.

This means keeping the current "semantics" of max_document_size which actually
means "max request size". But this makes the check more efficient and can
be done earlier in request processing time.

Jira: COUCHDB-3174
diff --git a/src/couch_httpd.erl b/src/couch_httpd.erl
index 7c4e573..8e7dfeb 100644
--- a/src/couch_httpd.erl
+++ b/src/couch_httpd.erl
@@ -33,6 +33,8 @@
 -export([http_1_0_keep_alive/2]).
 -export([validate_host/1]).
 -export([validate_bind_address/1]).
+-export([check_max_request_length/1]).
+
 
 -define(HANDLER_NAME_IN_MODULE_POS, 6).
 
@@ -446,6 +448,18 @@
         end
     end.
 
+
+check_max_request_length(Req) ->
+    Len = list_to_integer(header_value(Req, "Content-Length", "0")),
+    MaxLen = config:get_integer("couchdb", "max_document_size", 4294967296),
+    case Len > MaxLen of
+        true ->
+            exit({body_too_large, Len});
+        false ->
+            ok
+    end.
+
+
 % Utilities
 
 partition(Path) ->
diff --git a/src/couch_httpd_db.erl b/src/couch_httpd_db.erl
index 965e8fb..c46733f 100644
--- a/src/couch_httpd_db.erl
+++ b/src/couch_httpd_db.erl
@@ -583,6 +583,7 @@
 
     case couch_util:to_list(couch_httpd:header_value(Req, "Content-Type")) of
     ("multipart/related;" ++ _) = ContentType ->
+        couch_chttpd:check_max_request_length(Req),
         {ok, Doc0, WaitFun, Parser} = couch_doc:doc_from_multi_part_stream(
             ContentType, fun() -> receive_request_data(Req) end),
         Doc = couch_doc_from_req(Req, DocId, Doc0),