You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@couchdb.apache.org by Dylan Ambauen <dy...@ambauen.com> on 2011/09/18 09:13:19 UTC

Empty response for PUT in CouchDB 1.1.0

I'm getting an empty response body to a PUT request with CouchDB 1.1.0.

This is unexpected behavior.

Response headers are properly formatted.
The response is 201 Created, which usually means the operation completed
successfully.
The PUT operation does complete, all of the data is written back to couchdb.
The Etag header is appropriately updated to the next revision, and matches
what is actually saved to couch.
Content-length is set to 97, but the response itself is empty.
Response body is blank.

Now, for the inconsistent part. The empty response only occurs when the
document being PUT gets big. The issue does not seem to correlate to number
of updates to the doc, but rather size of the doc being updated. When I
update a doc of size 1206 bytes (which is not that big!), I get an
appropriate response. When I update a doc of 1310 bytes, I get an empty
response. 1206 and 1310 specifically are sample values from my tests to
isolate the problem. Those byte counts are included in the request headers
as content length. It is the string length of the doc I am attempting to
write. In my example below, the request content length is 1534, but i have
shortened the content for brevity. Doubt that the data itself matters, but
maybe 10 simple string fields of <100 bytes and a few fields containing
arrays or hashes, with < 100 items, etc. Nothing fancy, Couch should be able
to handle this.


For example:

REQUEST:
PUT /testdb/36e04ac8eb90ca90269c1712510593f0 HTTP/1.0
Host: 192.168.0.116
Content-Length: 1534
Content-Type: application/json

{"_id":"36e04ac8eb90ca90269c1712510593f0","_rev":"182-6046970607e6f9f39ee8d9f774c57fb4","foo":"bar...."}


RESPONSE:
HTTP/1.0 201 Created
Server: CouchDB/1.1.0 (Erlang OTP/R13B03)
Location: http://192.168.0.116/testdb/36e04ac8eb90ca90269c1712510593f0
Etag: "183-4006347f2e64ed9b4e5ce8c3f57e4dfc"
Date: Sat, 17 Sep 2011 20:04:26 GMT
Content-Type: text/plain;charset=utf-8
Content-Length: 97
Cache-Control: must-revalidate


(the body of the response is empty, this is the error condition. nothing.)

Whereas, we would expect to see a response like:

{"ok":true,"id":"36e04ac8eb90ca90269c1712510593f0","rev":"183-4006347f2e64ed9b4e5ce8c3f57e4dfc"}


The only two links I've found so far are below, but both were solved by some
javascript client settings. I'm not using a js client. First link is from
this list, thanks.
http://mail-archives.apache.org/mod_mbox/couchdb-user/201011.mbox/%3CAANLkTimSxUWQhwYfTTGe1vNkhkf2xnMiWmt9eriKMU8P@mail.gmail.com%3E
http://stackoverflow.com/questions/2503911/getting-an-empty-response-when-calling-couchdb-over-ajax


I'm connecting from PHP with a simple PHP Couch client, like:
private function execute() {
        fwrite($this->sock, $this->getRequest());
        $response = '';
        while(!feof($this->sock)) {
            $response .= fgets($this->sock);
        }
        echo "<pre>REQUEST: {$this->getRequest()}
RESPONSE: {$response}</pre>"; //the debug statement outputting my example
above
        $this->response = new CouchDBResponse($response);
        return $this->response;
}



I recently upgraded from CouchDB 0.8.0 to 1.1.0, my client did not have any
problems with 0.8.0. It is a problem now because without a response body,
the client thinks the PUT failed. Normally we would want to validate a PUT
with some logic like:
$res = CouchDB::q("/36e04ac8eb90ca90269c1712510593f0", 'PUT',
json_encode($doc))->getBody(true);
if (isset($res->ok) && ($res->ok == 1) && ($res->id == $doc->_id) ) { //ok }
else { throw new Exception(...); }

So the client thinks the update failed, when in fact it did not. Only that
Couch failed to send back a properly formatted response. Client copy of the
doc is now out of rev sync with the server, and the client dies. Additional
updates to the client side doc are lost as later writebacks are rejected
without the correct _rev.

Suppose I could inspect the Etag header of the response, which appears to be
accurate. However, also seems like a hack that shouldnt be necessary.
Furthermore, I cant find any documentation that it is ok to rely upon an
Etag header when the response body is empty. Thats the point of awaiting a
response with ok=1, right?

Also, I have set etc/couchdb/local.ini without luck.
[couchdb]
delayed_commits = false


Thanks for any assistance or ideas.

Cheers,
Dylan

Re: Empty response for PUT in CouchDB 1.1.0

Posted by Dylan Ambauen <dy...@ambauen.com>.
Thank you Jens, Patrick, Jason,

A quick check with curl demonstrated that couch was in fact serving
well-formed responses, chunked into multiple packets. Confirmed with
tcpdump.
Upgraded to https://github.com/dready92/PHP-on-Couch/ and it works great,
using curl libraries.

I did not go back to test against r979368. As far as the presence of an RST
packet, I admit I'm not certain, but I only see one ACK from the client back
to the server before the next packet comes down the wire.
Request from client
ACK from server
Response headers from server
ACK from client
Response body from server
ACK from client
... seems pretty standard.

All was solved within an hour last weekend, thank you for your responses to
my inquiry.

Sincerely, Dylan



On Sun, Sep 18, 2011 at 4:53 AM, Patrick Barnes <mr...@gmail.com> wrote:

> There is additionally several PHP couch libraries.
> I use and would recommend you try https://github.com/dready92/**
> PHP-on-Couch/ <https://github.com/dready92/PHP-on-Couch/>
>
> There's no sense in reinventing the wheel again and again...
>
>
> On 18/09/2011 5:29 PM, Jens Alfke wrote:
>
>> Looks like you're rolling your own HTTP library, which is a bit worrisome.
>> (I thought there was already an HTTP client library in PHP, maybe as part of
>> PEAR?) Can you reproduce the bug using an existing HTTP client like curl?
>>
>> --Jens
>>
>

Re: Empty response for PUT in CouchDB 1.1.0

Posted by Patrick Barnes <mr...@gmail.com>.
There is additionally several PHP couch libraries.
I use and would recommend you try https://github.com/dready92/PHP-on-Couch/

There's no sense in reinventing the wheel again and again...

On 18/09/2011 5:29 PM, Jens Alfke wrote:
> Looks like you're rolling your own HTTP library, which is a bit worrisome. (I thought there was already an HTTP client library in PHP, maybe as part of PEAR?) Can you reproduce the bug using an existing HTTP client like curl?
>
> --Jens

Re: Empty response for PUT in CouchDB 1.1.0

Posted by Jens Alfke <je...@couchbase.com>.
Looks like you're rolling your own HTTP library, which is a bit worrisome. (I thought there was already an HTTP client library in PHP, maybe as part of PEAR?) Can you reproduce the bug using an existing HTTP client like curl?

--Jens

Re: Empty response for PUT in CouchDB 1.1.0

Posted by Jason Smith <jh...@iriscouch.com>.
Hi, Jason. I think you might be right. Notice that Dylan's bug
triggers around the 1,500 byte mark. That is the typical Ethernet
maximum transmission unit. It is likely Dylan's queries are being
broken into two packets.

Dylan, another thing to do is to identify the exact byte size of a
query that triggers this bug. I predict that when you click over to
1,501 bytes it will happen. (The only catch is, that is 1,500 total
bytes, including TCP headers and also HTTP headers, so the way to be
sure is to use tcpdump or Wireshark).

Good luck!

On Sun, Sep 18, 2011 at 8:55 PM, Jason Smith <jh...@iriscouch.com> wrote:
> Hi, Dylan. Are you able to Build CouchDB from Git or Subversion?
>
> If you can confirm whether the change occurs at commit 4b0948d (or
> Subversion r979368) that would be a major clue.
>
> In addition (or alternatively) are you able to run tcpdump on the
> CouchDB machine? Could you confirm whether it is sending RST packets
> after its response headers?
>
> I struggled with a similar symptom but was unable to identify the root
> cause. I confirmed that the bug was introduced in that commit (SSL
> support) and in particular, the Mochiweb upgrade. In my case, if an
> unauthorized request was split into two TCP packets (a packet with
> headers and a PSH flag, then a packet with the body), I would get the
> same response.
>
> Finally, does adding delay_send to the socket options helps at all? It
> is in the config.
>
> [httpd]
>  socket_options = [{delay_send, true}]
>
> That was my final workaround; but I feel like Shatner on the airplane
> and I still wonder whether the bug will kill us all yet.
>
> (If none of these tests change your couch behavior then we probably
> have different bugs after all.)
>
> On Sun, Sep 18, 2011 at 2:13 PM, Dylan Ambauen <dy...@ambauen.com> wrote:
>> I'm getting an empty response body to a PUT request with CouchDB 1.1.0.
>>
>> This is unexpected behavior.
>>
>> Response headers are properly formatted.
>> The response is 201 Created, which usually means the operation completed
>> successfully.
>> The PUT operation does complete, all of the data is written back to couchdb.
>> The Etag header is appropriately updated to the next revision, and matches
>> what is actually saved to couch.
>> Content-length is set to 97, but the response itself is empty.
>> Response body is blank.
>>
>> Now, for the inconsistent part. The empty response only occurs when the
>> document being PUT gets big. The issue does not seem to correlate to number
>> of updates to the doc, but rather size of the doc being updated. When I
>> update a doc of size 1206 bytes (which is not that big!), I get an
>> appropriate response. When I update a doc of 1310 bytes, I get an empty
>> response. 1206 and 1310 specifically are sample values from my tests to
>> isolate the problem. Those byte counts are included in the request headers
>> as content length. It is the string length of the doc I am attempting to
>> write. In my example below, the request content length is 1534, but i have
>> shortened the content for brevity. Doubt that the data itself matters, but
>> maybe 10 simple string fields of <100 bytes and a few fields containing
>> arrays or hashes, with < 100 items, etc. Nothing fancy, Couch should be able
>> to handle this.
>>
>>
>> For example:
>>
>> REQUEST:
>> PUT /testdb/36e04ac8eb90ca90269c1712510593f0 HTTP/1.0
>> Host: 192.168.0.116
>> Content-Length: 1534
>> Content-Type: application/json
>>
>> {"_id":"36e04ac8eb90ca90269c1712510593f0","_rev":"182-6046970607e6f9f39ee8d9f774c57fb4","foo":"bar...."}
>>
>>
>> RESPONSE:
>> HTTP/1.0 201 Created
>> Server: CouchDB/1.1.0 (Erlang OTP/R13B03)
>> Location: http://192.168.0.116/testdb/36e04ac8eb90ca90269c1712510593f0
>> Etag: "183-4006347f2e64ed9b4e5ce8c3f57e4dfc"
>> Date: Sat, 17 Sep 2011 20:04:26 GMT
>> Content-Type: text/plain;charset=utf-8
>> Content-Length: 97
>> Cache-Control: must-revalidate
>>
>>
>> (the body of the response is empty, this is the error condition. nothing.)
>>
>> Whereas, we would expect to see a response like:
>>
>> {"ok":true,"id":"36e04ac8eb90ca90269c1712510593f0","rev":"183-4006347f2e64ed9b4e5ce8c3f57e4dfc"}
>>
>>
>> The only two links I've found so far are below, but both were solved by some
>> javascript client settings. I'm not using a js client. First link is from
>> this list, thanks.
>> http://mail-archives.apache.org/mod_mbox/couchdb-user/201011.mbox/%3CAANLkTimSxUWQhwYfTTGe1vNkhkf2xnMiWmt9eriKMU8P@mail.gmail.com%3E
>> http://stackoverflow.com/questions/2503911/getting-an-empty-response-when-calling-couchdb-over-ajax
>>
>>
>> I'm connecting from PHP with a simple PHP Couch client, like:
>> private function execute() {
>>        fwrite($this->sock, $this->getRequest());
>>        $response = '';
>>        while(!feof($this->sock)) {
>>            $response .= fgets($this->sock);
>>        }
>>        echo "<pre>REQUEST: {$this->getRequest()}
>> RESPONSE: {$response}</pre>"; //the debug statement outputting my example
>> above
>>        $this->response = new CouchDBResponse($response);
>>        return $this->response;
>> }
>>
>>
>>
>> I recently upgraded from CouchDB 0.8.0 to 1.1.0, my client did not have any
>> problems with 0.8.0. It is a problem now because without a response body,
>> the client thinks the PUT failed. Normally we would want to validate a PUT
>> with some logic like:
>> $res = CouchDB::q("/36e04ac8eb90ca90269c1712510593f0", 'PUT',
>> json_encode($doc))->getBody(true);
>> if (isset($res->ok) && ($res->ok == 1) && ($res->id == $doc->_id) ) { //ok }
>> else { throw new Exception(...); }
>>
>> So the client thinks the update failed, when in fact it did not. Only that
>> Couch failed to send back a properly formatted response. Client copy of the
>> doc is now out of rev sync with the server, and the client dies. Additional
>> updates to the client side doc are lost as later writebacks are rejected
>> without the correct _rev.
>>
>> Suppose I could inspect the Etag header of the response, which appears to be
>> accurate. However, also seems like a hack that shouldnt be necessary.
>> Furthermore, I cant find any documentation that it is ok to rely upon an
>> Etag header when the response body is empty. Thats the point of awaiting a
>> response with ok=1, right?
>>
>> Also, I have set etc/couchdb/local.ini without luck.
>> [couchdb]
>> delayed_commits = false
>>
>>
>> Thanks for any assistance or ideas.
>>
>> Cheers,
>> Dylan
>>
>
>
>
> --
> Iris Couch
>



-- 
Iris Couch

Re: Empty response for PUT in CouchDB 1.1.0

Posted by Jason Smith <jh...@iriscouch.com>.
Hi, Dylan. Are you able to Build CouchDB from Git or Subversion?

If you can confirm whether the change occurs at commit 4b0948d (or
Subversion r979368) that would be a major clue.

In addition (or alternatively) are you able to run tcpdump on the
CouchDB machine? Could you confirm whether it is sending RST packets
after its response headers?

I struggled with a similar symptom but was unable to identify the root
cause. I confirmed that the bug was introduced in that commit (SSL
support) and in particular, the Mochiweb upgrade. In my case, if an
unauthorized request was split into two TCP packets (a packet with
headers and a PSH flag, then a packet with the body), I would get the
same response.

Finally, does adding delay_send to the socket options helps at all? It
is in the config.

[httpd]
  socket_options = [{delay_send, true}]

That was my final workaround; but I feel like Shatner on the airplane
and I still wonder whether the bug will kill us all yet.

(If none of these tests change your couch behavior then we probably
have different bugs after all.)

On Sun, Sep 18, 2011 at 2:13 PM, Dylan Ambauen <dy...@ambauen.com> wrote:
> I'm getting an empty response body to a PUT request with CouchDB 1.1.0.
>
> This is unexpected behavior.
>
> Response headers are properly formatted.
> The response is 201 Created, which usually means the operation completed
> successfully.
> The PUT operation does complete, all of the data is written back to couchdb.
> The Etag header is appropriately updated to the next revision, and matches
> what is actually saved to couch.
> Content-length is set to 97, but the response itself is empty.
> Response body is blank.
>
> Now, for the inconsistent part. The empty response only occurs when the
> document being PUT gets big. The issue does not seem to correlate to number
> of updates to the doc, but rather size of the doc being updated. When I
> update a doc of size 1206 bytes (which is not that big!), I get an
> appropriate response. When I update a doc of 1310 bytes, I get an empty
> response. 1206 and 1310 specifically are sample values from my tests to
> isolate the problem. Those byte counts are included in the request headers
> as content length. It is the string length of the doc I am attempting to
> write. In my example below, the request content length is 1534, but i have
> shortened the content for brevity. Doubt that the data itself matters, but
> maybe 10 simple string fields of <100 bytes and a few fields containing
> arrays or hashes, with < 100 items, etc. Nothing fancy, Couch should be able
> to handle this.
>
>
> For example:
>
> REQUEST:
> PUT /testdb/36e04ac8eb90ca90269c1712510593f0 HTTP/1.0
> Host: 192.168.0.116
> Content-Length: 1534
> Content-Type: application/json
>
> {"_id":"36e04ac8eb90ca90269c1712510593f0","_rev":"182-6046970607e6f9f39ee8d9f774c57fb4","foo":"bar...."}
>
>
> RESPONSE:
> HTTP/1.0 201 Created
> Server: CouchDB/1.1.0 (Erlang OTP/R13B03)
> Location: http://192.168.0.116/testdb/36e04ac8eb90ca90269c1712510593f0
> Etag: "183-4006347f2e64ed9b4e5ce8c3f57e4dfc"
> Date: Sat, 17 Sep 2011 20:04:26 GMT
> Content-Type: text/plain;charset=utf-8
> Content-Length: 97
> Cache-Control: must-revalidate
>
>
> (the body of the response is empty, this is the error condition. nothing.)
>
> Whereas, we would expect to see a response like:
>
> {"ok":true,"id":"36e04ac8eb90ca90269c1712510593f0","rev":"183-4006347f2e64ed9b4e5ce8c3f57e4dfc"}
>
>
> The only two links I've found so far are below, but both were solved by some
> javascript client settings. I'm not using a js client. First link is from
> this list, thanks.
> http://mail-archives.apache.org/mod_mbox/couchdb-user/201011.mbox/%3CAANLkTimSxUWQhwYfTTGe1vNkhkf2xnMiWmt9eriKMU8P@mail.gmail.com%3E
> http://stackoverflow.com/questions/2503911/getting-an-empty-response-when-calling-couchdb-over-ajax
>
>
> I'm connecting from PHP with a simple PHP Couch client, like:
> private function execute() {
>        fwrite($this->sock, $this->getRequest());
>        $response = '';
>        while(!feof($this->sock)) {
>            $response .= fgets($this->sock);
>        }
>        echo "<pre>REQUEST: {$this->getRequest()}
> RESPONSE: {$response}</pre>"; //the debug statement outputting my example
> above
>        $this->response = new CouchDBResponse($response);
>        return $this->response;
> }
>
>
>
> I recently upgraded from CouchDB 0.8.0 to 1.1.0, my client did not have any
> problems with 0.8.0. It is a problem now because without a response body,
> the client thinks the PUT failed. Normally we would want to validate a PUT
> with some logic like:
> $res = CouchDB::q("/36e04ac8eb90ca90269c1712510593f0", 'PUT',
> json_encode($doc))->getBody(true);
> if (isset($res->ok) && ($res->ok == 1) && ($res->id == $doc->_id) ) { //ok }
> else { throw new Exception(...); }
>
> So the client thinks the update failed, when in fact it did not. Only that
> Couch failed to send back a properly formatted response. Client copy of the
> doc is now out of rev sync with the server, and the client dies. Additional
> updates to the client side doc are lost as later writebacks are rejected
> without the correct _rev.
>
> Suppose I could inspect the Etag header of the response, which appears to be
> accurate. However, also seems like a hack that shouldnt be necessary.
> Furthermore, I cant find any documentation that it is ok to rely upon an
> Etag header when the response body is empty. Thats the point of awaiting a
> response with ok=1, right?
>
> Also, I have set etc/couchdb/local.ini without luck.
> [couchdb]
> delayed_commits = false
>
>
> Thanks for any assistance or ideas.
>
> Cheers,
> Dylan
>



-- 
Iris Couch