robn / p5-etcd

Perl client library for etcd
3 stars 3 forks source link

use HTTP body with 'PUT' method for long URL query string #6

Open potatogim opened 6 years ago

potatogim commented 6 years ago

Hello Rob N!

I really appreciating your working of p5-etcd.

I'm using it for a project of my work!

When we use it with etcd 3.2.11 on CentOS 7, $etcd->set(...) method has failed with 599 HTTP exception.

I have traced to resolve this problem and finally I found the cause!

First, below that is strace log taken by curl http://127.0.0.1:4001/v2/keys/... -dvalue="$(cat data)"

data file size is bigger than 4KB.

4663  sendto(3, "PUT /v2/keys/Publisher HTTP/1.1\r\nUser-Agent: curl/7.29.0\r\nHost: 127.0.0.1:4001\r\nAccept: */*\r\nContent-Length: 4909\r\nContent-Type: application/x-www-form-urlencoded\r\nExpect: 100-continue\r\n\r\n", 188, MSG_NOSIGNAL, NULL, 0) = 188                    
4663  poll([{fd=3, events=POLLIN|POLLPRI|POLLRDNORM|POLLRDBAND}], 1, 0) = 0 (Timeout)
4663  poll([{fd=3, events=POLLIN}], 1, 1) = 1 ([{fd=3, revents=POLLIN}])
4663  poll([{fd=3, events=POLLIN|POLLPRI|POLLRDNORM|POLLRDBAND}], 1, 0) = 1 ([{fd=3, revents=POLLIN|POLLRDNORM}])
4663  recvfrom(3, "HTTP/1.1 100 Continue\r\n\r\n", 16384, 0, NULL, NULL) = 25
4663  poll([{fd=3, events=POLLIN}, {fd=3, events=POLLOUT}], 2, 1000) = 1 ([{fd=3, revents=POLLOUT}])
4663  poll([{fd=3, events=POLLIN|POLLPRI|POLLRDNORM|POLLRDBAND}, {fd=3, events=POLLOUT|POLLWRNORM}], 2, 0) = 1 ([{fd=3, revents=POLLOUT|POLLWRNORM}])
4663  sendto(3, "value=blahblah....")  

and another strace log with a perl script using Etcd.

22399 write(3, "PUT /v2/keys/Publisher?value=blahblah...
22399 rt_sigprocmask(SIG_BLOCK, [PIPE], [], 8) = 0
22399 rt_sigaction(SIGPIPE, {SIG_DFL, [], SA_RESTORER, 0x7f305a6ce5e0}, {SIG_IGN, [], SA_RESTORER, 0x7f305a6ce5e0}, 8) = 0
22399 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
22399 select(8, [3], NULL, NULL, {60, 0}) = 1 (in [3], left {59, 999997})
22399 read(3, 0x2c9eea0, 32768)         = -1 ECONNRESET (Connection reset by peer)
22399 close(3)                          = 0
22399 write(2, "599 Internal Exception: Could not read from socket: 'Connection reset by peer'\n at /usr/share/perl5/vendor_perl/Etcd/Keys.pm line 23.\n", 134) = 134

I guessed that URL is too long due to HTTP query string(value field), and I changed it using Content-Length HTTP header with PUT method.

Finally, It is working even though we do not wait HTTP/1.1 100 Continue response :sweat_smile:

31591 write(3, "PUT /v2/keys/Publisher HTTP/1.1\r\nHost: 127.0.0.1:4001\r\nExpect: 100-continue\r\nUser-Agent: HTTP-Tiny/0.070\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 7424\r\n\r\n", 179) = 179
31591 rt_sigprocmask(SIG_BLOCK, [PIPE], [], 8) = 0
31591 rt_sigaction(SIGPIPE, {SIG_DFL, [], SA_RESTORER, 0x7fd76d19a5e0}, {SIG_IGN, [], SA_RESTORER, 0x7fd76d19a5e0}, 8) = 0
31591 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
31591 rt_sigprocmask(SIG_BLOCK, [PIPE], [], 8) = 0
31591 rt_sigaction(SIGPIPE, {SIG_IGN, [], SA_RESTORER, 0x7fd76d19a5e0}, {SIG_DFL, [], SA_RESTORER, 0x7fd76d19a5e0}, 8) = 0
31591 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
31591 select(8, NULL, [3], NULL, {60, 0}) = 1 (out [3], left {59, 999980})
31591 write(3, "value=blahblah...")
31591 rt_sigprocmask(SIG_BLOCK, [PIPE], [], 8) = 0
31591 rt_sigaction(SIGPIPE, {SIG_DFL, [], SA_RESTORER, 0x7fd76d19a5e0}, {SIG_IGN, [], SA_RESTORER, 0x7fd76d19a5e0}, 8) = 0
31591 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
31591 select(8, [3], NULL, NULL, {60, 0}) = 1 (in [3], left {59, 999997})
31591 read(3, "HTTP/1.1 100 Continue\r\n\r\n", 32768) = 25
31591 select(8, [3], NULL, NULL, {60, 0}) = 1 (in [3], left {59, 999751})
31591 read(3, "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nX-Etcd-Cluster-Id: cc031ccb07a315ed\r\nX-Etcd-Index: 917\r\nX-Raft-Index: 1732\r\nX-Raft-Term: 6\r\nDate: Thu, 22 Mar 2018 11:41:54 GMT\r\nTransfer-Encoding: chunked\r\n\r\n2cab\r\n{\"action\":\"set\"...)
potatogim commented 5 years ago

@robn: Hello! Could you give me your feedback? :)