Note that there are some explanatory texts on larger screens.

plurals
  1. POAm I doing it wrong or is it a bug in net/http?
    text
    copied!<p>I'm using Ruby Net::HTTP under a NginX/Phusion Passenger server, attempting to POST a JSON string to the server. It appears that my POST, only when sending as 'application/json', prematurely closes the session to the server. I.E.:</p> <p>On the server side:</p> <pre><code>127.0.0.1 - - [03/Sep/2013 07:47:14] "POST /path/to/submit " 200 45 0.0013 pid=12893 thr=47197563169088 file=ext/nginx/HelperAgent.cpp:933 time=2013-09-03 07:47:14.830 ]: Uncaught exception in PassengerServer client thread: exception: Cannot read response from backend process: Connection reset by peer (104) backtrace: in 'void Client::forwardResponse(Passenger::SessionPtr&amp;, Passenger::FileDescriptor&amp;, const Passenger::AnalyticsLogPtr&amp;)' (HelperAgent.cpp:698) in 'void Client::handleRequest(Passenger::FileDescriptor&amp;)' (HelperAgent.cpp:859) in 'void Client::threadMain()' (HelperAgent.cpp:952) </code></pre> <p>A client side debug session is:</p> <pre><code>opening connection to hostname.com... opened &lt;- "POST /path/to/submit HTTP/1.1\r\nContent-Type: application/json\r\nAccept: application/json\r\nUser-Agent: agent+test\r\nConnection: close\r\nHost: hostname.com\r\nContent-Length: 660\r\n\r\n" &lt;- "[{json string}]" -&gt; "HTTP/1.1 301 Moved Permanently\r\n" -&gt; "Server: nginx/1.2.6\r\n" -&gt; "Date: Tue, 03 Sep 2013 14:47:15 GMT\r\n" -&gt; "Content-Type: text/html\r\n" -&gt; "Content-Length: 184\r\n" -&gt; "Connection: close\r\n" -&gt; "Location: https://hostname.com/path/to/submit\r\n" -&gt; "\r\n" reading 184 bytes... -&gt; "&lt;html&gt;\r\n&lt;head&gt;&lt;title&gt;301 Moved Permanently&lt;/title&gt;&lt;/head&gt;\r\n&lt;body bgcolor=\"white\"&gt;\r\n&lt;center&gt;&lt;h1&gt;301 Moved Permanently&lt;/h1&gt;&lt;/center&gt;\r\n&lt;hr&gt;&lt;center&gt;nginx/1.2.6&lt;/center&gt;\r\n&lt;/body&gt;\r\n&lt;/html&gt;\r\n" read 184 bytes Conn close opening connection to hostname.com... opened &lt;- "POST /path/to/submit HTTP/1.1\r\nContent-Type: application/json\r\nAccept: application/json\r\nUser-Agent: agent+test\r\nConnection: close\r\nHost: hostname.com\r\nContent-Length: 660\r\n\r\n" &lt;- "[{json string}]" -&gt; "HTTP/1.1 200 OK\r\n" -&gt; "Content-Type: text/html;charset=utf-8\r\n" -&gt; "Content-Length: 45\r\n" -&gt; "Connection: close\r\n" -&gt; "Status: 200\r\n" -&gt; "X-Powered-By: Phusion Passenger (mod_rails/mod_rack) 3.0.17\r\n" -&gt; "X-Frame-Options: SAMEORIGIN\r\n" -&gt; "X-XSS-Protection: 1; mode=block\r\n" -&gt; "X-Content-Type-Options: nosniff\r\n" -&gt; "Server: nginx/1.2.6 + Phusion Passenger 3.0.17 (mod_rails/mod_rack)\r\n" -&gt; "Strict-Transport-Security: max-age=31536000\r\n" -&gt; "X-Frame-Options: DENY\r\n" -&gt; "\r\n" reading 45 bytes... -&gt; "some url string" &lt;-- this is suspicous to me. read 45 bytes Conn close </code></pre> <p>The code I'm using to submit my data is:</p> <pre><code>private def _http_client(method = 'get', location = nil, limit = 10) raise ArgumentError, 'FATAL: too many HTTP redirects attempted...' if limit == 0 response = nil if location.nil? if @uri.nil? raise ArgumentError 'FATAL: no location specified. Quitting.' end else @uri = URI.parse(location) end client = Net::HTTP.new(@uri.host,@uri.port) client.open_timeout = 15 # in seconds client.read_timeout = 15 # in seconds initheader = {'content-type' =&gt; 'application/json', 'accept' =&gt; 'application/json', 'user-agent' =&gt; UA ,} client.set_debug_output $stderr # XXX TEMPORARY if @uri.scheme == 'https' client.use_ssl = true client.verify_mode = 0 end if method == 'post' serialized = JSON.generate(@payload) response = client.send_request('POST',@uri.path,serialized,initheader = initheader) puts serialized end # Only intended for pings. In order to do # full GETs (including query_params) this # will need to be refactored a little. if method == 'get' response = client.get(@uri.path) end case response when Net::HTTPSuccess @status = true when Net::HTTPMovedPermanently @status = false limit = limit - 1 _http_client(method,response['location'],limit) when Net::HTTPClientError $stderr.puts 'Client error.' @status = false when Net::HTTPServerError $stderr.puts 'Server error.' @status = false else $stderr.puts 'No idea what the server returned.' @status = false end unless response.nil? @response = {:code =&gt; response.code, :body =&gt; (response.body || 'OK')} @code = @response[:code].to_s @http_body = @response[:body].to_s else $stderr.puts 'response from server was empty. :(' end _send_status end </code></pre> <p>I'm using:</p> <ul> <li>Ruby version: 1.9.3p448</li> <li>NginX 1.2.6</li> <li>Passenger 3.0.17</li> </ul> <p>I'm pretty sure I might be doing something wrong, but I'm new to Ruby and semi-new to this kind of web programming.</p> <p>The code snippet above uses the <code>send_request</code> method but I've also tried <code>post</code>, and <code>post2</code>, resulting in the same outcome.</p> <p>It's really suspicious to me that as soon as I use 'application/json' in my <code>initheader</code> everything breaks. When I remove it, everything works alright.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload