From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.0 required=3.0 tests=ALL_TRUSTED,BAYES_00 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id B3E7E1F61C for ; Tue, 17 Mar 2020 06:56:52 +0000 (UTC) From: Eric Wong To: cmogstored-public@yhbt.net Subject: [PATCH 2/2] http: favor chunked over Content-Length Date: Tue, 17 Mar 2020 06:56:52 +0000 Message-Id: <20200317065652.10324-3-e@yhbt.net> In-Reply-To: <20200317065652.10324-1-e@yhbt.net> References: <20200317065652.10324-1-e@yhbt.net> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: RFC 7230 is actually explicit about favoring the "Transfer-Encoding: chunked" over a Content-Length header when a client specifies both. --- http_parser.rl | 13 +++++++++++-- test/http_put.rb | 16 ++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/http_parser.rl b/http_parser.rl index 0685d27..835ba65 100644 --- a/http_parser.rl +++ b/http_parser.rl @@ -62,7 +62,12 @@ static char *skip_header(struct mog_http *http, char *buf, const char *pe) content_length = "Content-Length:"i sep (digit+) $ { - if (!length_incr(&http->_p.content_len, fc)) + /* + * RFC 7230 3.3.2, 3.3.3,: + * favor Transfer-Encoding over Content-Length + */ + if (!http->_p.chunked && + !length_incr(&http->_p.content_len, fc)) fbreak; } $! { errno = EINVAL; fbreak; } @@ -116,7 +121,11 @@ static char *skip_header(struct mog_http *http, char *buf, const char *pe) # "compress" as described in RFC 7230, so reject them, here. "chunked"i $! { errno = EINVAL; fbreak; } - eor @ { http->_p.chunked = 1; }; + eor @ { + http->_p.chunked = 1; + /* RFC 7230 3.3.2, 3.3.3,: ignore length if chunked */ + http->_p.content_len = 0; + }; trailer = "Trailer:"i sep (("Content-MD5"i @ { http->_p.has_md5 = 1; }) | header_name | ',') diff --git a/test/http_put.rb b/test/http_put.rb index 0479629..34e2cdb 100644 --- a/test/http_put.rb +++ b/test/http_put.rb @@ -226,6 +226,22 @@ def test_put_bad_content_length assert( ! File.exist?("#@tmpdir/dev666/foo") ) end + def test_put_favors_chunked + order = [ "Transfer-Encoding: chunked", "Content-Length: 123" ] + %w[a b].each do + path = '/dev666/a' + req = "PUT #{path} HTTP/1.1\r\n" \ + "#{order.join("\r\n")}\r\n\r\n" \ + "a\r\nhelloworld\r\n0\r\n\r\n" + order.reverse! + @client.write(req) + resp = @client.readpartial(4096) + assert_match(%r{\AHTTP/1\.1 201 Created\r\n}, resp, "#{path} created") + assert(File.exist?("#@tmpdir#{path}")) + assert_equal('helloworld', File.read("#@tmpdir#{path}")) + end + end + def test_content_md5_good req = "PUT /dev666/foo HTTP/1.1\r\n" \ "Host: #@host:#@port\r\n" \