Details

      Description

      CouchDB behaves erroneously when doing a GET request with Content-Length header to long polling changes feed with filter set.

      Easiest way to reproduce:
      1. Create a new DB
      2. Create a single design doc with a filter that just returns true
      3. Query database with curl: curl -v -H "Content-Length: 123" http://localhost:5984/database/_changes?feed=longpoll&filter=designdoc/filter

      At this point CouchDB behaves strangely. It does not wait for the client to feed the Content-Length bytes of content (which I think is correct, since GET should not have payload), instead, it returns 200 OK and starts the response with '{"results":['. However, no changes done to database ever get emitted and the connection never gets closed, not even if explicit timeout is set upon the request.

        Activity

        Hide
        Jan Lehnardt added a comment -

        As per RFC2616 GEt requests can have a body and thus a valid Content-Length header.

        Technically, you are sending a malformed HTTP request. The question now is how CouchDB should behave. I agree that the current behaviour is odd.

        I'd propose that we respond with a 400 Bad Request, but I am happy for other suggestions.

        Fwiw, querying with a GET body does work as expected:

        > curl -X GET $COUCH'/a/_changes?filter=test/foo&feed=longpoll' -H"Content-Length: 2" -d "ab"
        {"results":[
        {"seq":1,"id":"_design/test","changes":[

        {"rev":"1-0b4478e601ec850f0d3c009b9889917b"}

        ]},
        {"seq":2,"id":"3fb73daa9078091698c732c8130018be","changes":[

        {"rev":"1-23202479633c2b380f79507a776743d5"}

        ]}
        ],
        "last_seq":2}

        Show
        Jan Lehnardt added a comment - As per RFC2616 GEt requests can have a body and thus a valid Content-Length header. Technically, you are sending a malformed HTTP request. The question now is how CouchDB should behave. I agree that the current behaviour is odd. I'd propose that we respond with a 400 Bad Request, but I am happy for other suggestions. Fwiw, querying with a GET body does work as expected: > curl -X GET $COUCH'/a/_changes?filter=test/foo&feed=longpoll' -H"Content-Length: 2" -d "ab" {"results":[ {"seq":1,"id":"_design/test","changes":[ {"rev":"1-0b4478e601ec850f0d3c009b9889917b"} ]}, {"seq":2,"id":"3fb73daa9078091698c732c8130018be","changes":[ {"rev":"1-23202479633c2b380f79507a776743d5"} ]} ], "last_seq":2}
        Hide
        Nathan Vander Wilt added a comment -

        I think this is a symptom of https://issues.apache.org/jira/browse/COUCHDB-1146. CouchDB never cares about the message body on a GET request, so it "interrupts" as soon as it's ready to respond.

        Show
        Nathan Vander Wilt added a comment - I think this is a symptom of https://issues.apache.org/jira/browse/COUCHDB-1146 . CouchDB never cares about the message body on a GET request, so it "interrupts" as soon as it's ready to respond.
        Hide
        Paul Joseph Davis added a comment -

        First pass at a patch:

        Index: src/couchdb/couch_httpd.erl
        ===================================================================
        — src/couchdb/couch_httpd.erl (revision 1097601)
        +++ src/couchdb/couch_httpd.erl (working copy)
        @@ -170,6 +170,15 @@
        handle_request(MochiReq, DefaultFun, UrlHandlers, DbUrlHandlers,
        DesignUrlHandlers) ->

        + case

        {MochiReq:get(method), MochiReq:get(body_length)}

        of
        +

        {'GET', chunked}

        ->
        + throw(not_on_my_watch);
        +

        {'GET', Len}

        when is_integer(Len), Len > 0 ->
        + throw(not_on_my_watch);
        + _ ->
        + ok
        + end,
        +
        MochiReq1 = couch_httpd_vhost:dispatch_host(MochiReq),

        handle_request_int(MochiReq1, DefaultFun,

        Show
        Paul Joseph Davis added a comment - First pass at a patch: Index: src/couchdb/couch_httpd.erl =================================================================== — src/couchdb/couch_httpd.erl (revision 1097601) +++ src/couchdb/couch_httpd.erl (working copy) @@ -170,6 +170,15 @@ handle_request(MochiReq, DefaultFun, UrlHandlers, DbUrlHandlers, DesignUrlHandlers) -> + case {MochiReq:get(method), MochiReq:get(body_length)} of + {'GET', chunked} -> + throw(not_on_my_watch); + {'GET', Len} when is_integer(Len), Len > 0 -> + throw(not_on_my_watch); + _ -> + ok + end, + MochiReq1 = couch_httpd_vhost:dispatch_host(MochiReq), handle_request_int(MochiReq1, DefaultFun,
        Hide
        Randall Leeds added a comment -

        Without looking I think throwing here would cause a 500 to be sent to the client when we should probably send 400 instead and put something useful in the response body.

        Show
        Randall Leeds added a comment - Without looking I think throwing here would cause a 500 to be sent to the client when we should probably send 400 instead and put something useful in the response body.
        Hide
        Randall Leeds added a comment -

        But, yeah. that looks like the right place .

        Show
        Randall Leeds added a comment - But, yeah. that looks like the right place .
        Hide
        Paul Joseph Davis added a comment -

        Pretty sure it needs to go down into the body of handle_request. I just wanted to paste a patch that had not_on_my_watch in it.

        Show
        Paul Joseph Davis added a comment - Pretty sure it needs to go down into the body of handle_request. I just wanted to paste a patch that had not_on_my_watch in it.
        Show
        Randall Leeds added a comment - http://www.youtube.com/watch?v=TpP8N-X1dF4
        Hide
        Paul Joseph Davis added a comment -

        I love you man.

        Show
        Paul Joseph Davis added a comment - I love you man.

          People

          • Assignee:
            Unassigned
            Reporter:
            Jyrki Pulliainen
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:

              Development