I am getting strange responses from CouchDB 2.0.0 when accessing a list handler 
through a rewrite. The result to my single request is two responses: the 
expected one, plus an extra "unknown_error" 500 response. Over HTTP/1.1 this 
issue is masked because the extra response is not properly chunked, but over 
HTTP/1.0 the two responses appear as a single body before the connection is 
closed. So in local development the problem isn't seen in the browser, but when 
hosted behind an HTTP/1.0 proxy like nginx in production all clients will see 
the extra content appended to the intended HTML.

Regardless of the HTTP version of the request, the behavior is accompanied in 
the console logs by:

    [error] 2017-06-20T20:54:43.637726Z couchdb@localhost <0.23057.8> 
4d6c7d7e8f req_err(2053811356) unknown_error : undef
        [<<"lacc:get/2">>,<<"chttpd:split_response/1 
L343">>,<<"chttpd:handle_request_int/1 L234">>,<<"chttpd:process_request/1 
L293">>,<<"chttpd:handle_request_int/1 L229">>,<<"mochiweb_http:headers/6 
L122">>,<<"proc_lib:init_p_do_apply/3 L247">>]
    [notice] 2017-06-20T20:54:43.637979Z couchdb@localhost <0.23057.8> 
4d6c7d7e8f undefined 127.0.0.1 undefined GET 
/test/_design/glob/_rewrite/2015/04/f1040_spreadsheet 500 ok 22


Note there is no separate log for the initial "200" response, just the second 
"500" one.

Turns out if I call `getRows()` an extra times in the list function (or if 
there are no matching rows), the extra 500 response does not happen. Also if I 
bypass the rewrite and query the list function directly, I do not see an extra 
response.

So it seems there might be a bug, maybe something like "the rewrite handler 
generates an extra, broken response if a list function doesn't consume beyond 
all the available rows".

Is this something I should file in JIRA, or have I made a mistake somewhere? 
Details below. (The original code can be seen at https://github.com/natevw/glob 
but I've simplified things down in my notes above and still seeing the issue.)

thanks,
-natevw


---


The rewrite used looks like

  "rewrites": [{
      "from": "/:path1/:path2/:path3",
      "to": "_list/posts/by_path",
      "query": {
          "include_docs": "true",
          "key": [":path1",":path2",":path3"]
      }
  }]

And the list function can be as simple as

    function() {
      return "[LIST FN OUTPUT]";
    }

When I query this such that "key" ends up matching a row from a simple 
"by_path" view, I get an extra garbage response when I access the rewrite:

    $ telnet localhost 5984
    GET /test/_design/glob/_rewrite/2015/04/f1040_spreadsheet

    HTTP/1.1 200 OK
    Connection: close
    Content-Type: application/json
    Date: Tue, 20 Jun 2017 20:34:49 GMT
    Server: CouchDB/2.0.0 (Erlang OTP/19)

    [LIST FN OUTPUT]HTTP/1.1 500 Internal Server Error
    Cache-Control: must-revalidate
    Connection: close
    Content-Length: 60
    Content-Type: application/json
    Date: Tue, 20 Jun 2017 20:34:49 GMT
    Server: CouchDB/2.0.0 (Erlang OTP/19)
    X-Couch-Request-ID: 5e0e7f467b
    X-Couch-Stack-Hash: 2053811356
    X-CouchDB-Body-Time: 0

    {"error":"unknown_error","reason":"undef","ref":2053811356}
    Connection closed by foreign host.


This does not happen with a direct request to the list, bypassing the rewrite:

    GET 
/test/_design/glob/_list/posts/by_path?include_docs=true&key=["2015","04","f1040_spreadsheet"]

    HTTP/1.1 200 OK
    Connection: close
    Content-Type: application/json
    Date: Tue, 20 Jun 2017 20:38:08 GMT
    Server: CouchDB/2.0.0 (Erlang OTP/19)

    [LIST FN OUTPUT]Connection closed by foreign host.


Nor does it happen if I make a request through the rewrite targeting a "missing 
key", i.e. one that was not emitted by the view:

    GET /test/_design/glob/_rewrite/2020/13/not_exist

    HTTP/1.1 200 OK
    Connection: close
    Content-Type: application/json
    Date: Tue, 20 Jun 2017 20:40:29 GMT
    Server: CouchDB/2.0.0 (Erlang OTP/19)

    [LIST FN OUTPUT]Connection closed by foreign host.


If I change my list function to

    function() {
      getRow();
      getRow();
      return "[LIST FN OUTPUT]";
    }

then the problem goes away even when accessed via the rewrite. With just a 
single call to `getRow()` the extra response persists.


Also note that the chunked responses of HTTP/1.1 mask this "double response" 
issue, so you'll see it in telnet or if CouchDB is behind nginx, but not in a 
browser or similar: 


    GET /test/_design/glob/_rewrite/2015/04/f1040_spreadsheet HTTP/1.1
    
    HTTP/1.1 200 OK
    Content-Type: application/json
    Date: Tue, 20 Jun 2017 20:50:12 GMT
    Server: CouchDB/2.0.0 (Erlang OTP/19)
    Transfer-Encoding: chunked
    
    d
    [LIST FN OUTPUT]
    0
    
    HTTP/1.1 500 Internal Server Error
    Cache-Control: must-revalidate
    Content-Length: 60
    Content-Type: application/json
    Date: Tue, 20 Jun 2017 20:50:12 GMT
    Server: CouchDB/2.0.0 (Erlang OTP/19)
    X-Couch-Request-ID: 524b67d8db
    X-Couch-Stack-Hash: 2053811356
    X-CouchDB-Body-Time: 0
    
    {"error":"unknown_error","reason":"undef","ref":2053811356}

Reply via email to