Am I doing it wrong or is it a network / http error?

I am using Ruby Net :: HTTP under a NginX / Phusion Passenger server, trying to POST a JSON string on the server. It seems that my POST, only when sent as "application / json", prematurely closes the session on the server. I.e:.

On the server side:

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&, Passenger::FileDescriptor&, const Passenger::AnalyticsLogPtr&)' (HelperAgent.cpp:698) in 'void Client::handleRequest(Passenger::FileDescriptor&)' (HelperAgent.cpp:859) in 'void Client::threadMain()' (HelperAgent.cpp:952) 

Client side debugging session:

 opening connection to hostname.com... opened <- "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" <- "[{json string}]" -> "HTTP/1.1 301 Moved Permanently\r\n" -> "Server: nginx/1.2.6\r\n" -> "Date: Tue, 03 Sep 2013 14:47:15 GMT\r\n" -> "Content-Type: text/html\r\n" -> "Content-Length: 184\r\n" -> "Connection: close\r\n" -> "Location: https://hostname.com/path/to/submit\r\n" -> "\r\n" reading 184 bytes... -> "<html>\r\n<head><title>301 Moved Permanently</title></head>\r\n<body bgcolor=\"white\">\r\n<center><h1>301 Moved Permanently</h1></center>\r\n<hr><center>nginx/1.2.6</center>\r\n</body>\r\n</html>\r\n" read 184 bytes Conn close opening connection to hostname.com... opened <- "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" <- "[{json string}]" -> "HTTP/1.1 200 OK\r\n" -> "Content-Type: text/html;charset=utf-8\r\n" -> "Content-Length: 45\r\n" -> "Connection: close\r\n" -> "Status: 200\r\n" -> "X-Powered-By: Phusion Passenger (mod_rails/mod_rack) 3.0.17\r\n" -> "X-Frame-Options: SAMEORIGIN\r\n" -> "X-XSS-Protection: 1; mode=block\r\n" -> "X-Content-Type-Options: nosniff\r\n" -> "Server: nginx/1.2.6 + Phusion Passenger 3.0.17 (mod_rails/mod_rack)\r\n" -> "Strict-Transport-Security: max-age=31536000\r\n" -> "X-Frame-Options: DENY\r\n" -> "\r\n" reading 45 bytes... -> "some url string" <-- this is suspicous to me. read 45 bytes Conn close 

The code I use to send my data is:

 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' => 'application/json', 'accept' => 'application/json', 'user-agent' => 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 => response.code, :body => (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 

I use:

  • Ruby version: 1.9.3p448
  • Nginx 1.2.6
  • Passenger 3.0.17

I'm sure something may be wrong, but I'm new to Ruby and half-way for this kind of web programming.

The above code snippet uses the send_request method, but I also tried post and post2 , which led to the same result.

It really seems suspicious to me that as soon as I use "application / json" in my initheader , everything breaks. When I delete it, everything works well.

+4
source share
1 answer

Try upgrading to Phusion Passenger 4. It handles I / O asynchrony better and in many cases avoids problems with closing the connection.

+1
source

Source: https://habr.com/ru/post/1500327/


All Articles