I am experimenting with Net::HTTP in Rails 3.0.3 but can’t get it to work due to a Timeout::Error.
I am having two controllers: Controller A is called by Controller B.
Controller A (xml_provider_controller.rb):
class XmlProviderController < ApplicationController
def availabilityByDateRequest
respond_to do |format|
format.xml # availabilityByDateRequest.xml.builder
end
end
end
File “availabilityByDateRequest.xml.builder” is a simple static XML which works.
Controller B (mains_controller.rb):
require 'nokogiri'
require 'net/http'
require 'uri'
require "logger"
class MainsController < ApplicationController
def search
url = URI.parse("http://127.0.0.1:3000/xmlprovider/availabilityByDateRequest/")
http = Net::HTTP.new(url.host, url.port)
http.open_timeout = 10 # in seconds
http.read_timeout = 10 # in seconds
req = Net::HTTP::Post.new(url.path,
initheader = {'Content-Type' => 'application/xml',
'Accept' => 'application/xml'})
req.body = "<?xml version='1.0' encoding='UTF-8'?><somedata></somedata>"
res = http.request(req)
logger.debug res.body
xml_doc = Nokogiri::XML(res.body)
@results = xml_doc.xpath('//startLocation')
respond_to do |format|
format.html # search.html.erb
end
end
end
Ok, “req.body” is not required at this point because only a static XML is returned by Controller B. However, a dynamically generated XML will be sent to Controller A and processed accordingly in the future, so I left it in.
I also defined a route:
match 'xmlprovider/availabilityByDateRequest' => 'xml_provider#availabilityByDateRequest', :via => :post, :format => 'xml'
Once I call “http://0.0.0.0:3000/mains/search“, I get a Timeout::Error.
The log says:
Started GET "/mains/search" for 127.0.0.1 at 2011-01-30 10:48:17 +0100
opening connection to localhost...
opened
<- "POST /xmlprovider/availabilityByDateRequest/ HTTP/1.1\r\nAccept: */*\r\nUser-Agent: Ruby\r\nConnection: close\r\nHost: localhost:3000\r\nContent-Length: 136\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n"
<- "<?xml version='1.0' encoding='UTF-8'?><somedata></somedata>"
Conn close because of error Timeout::Error
Timeout::Error (Timeout::Error):
app/controllers/mains_controller.rb:43:in `search'
Processing by MainsController#search as HTML
...
Started POST "/xmlprovider/availabilityByDateRequest/" for 127.0.0.1 at 2011-01-30 10:48:27 +0100
Processing by XmlProviderController#availabilityByDateRequest as XML
Parameters: {"<?xml version"=>"'1.0' encoding='UTF-8'?><somedata><name>Test Name 1</name><description>Some data for Unit testing</description></somedata>"}
Rendered xml_provider/availabilityByDateRequest.xml.builder (8.8ms)
Completed 200 OK in 14ms (Views: 13.9ms | ActiveRecord: 0.0ms)
According to the log, Controller B is called and returns the XML (last line in the log).
However, what causes the Timeout::Error? It’s certainly not a “timeout” in terms of insufficient processing time. Something gets stuck somewhere, most probably at line “res = http.request(req)“
Are you POSTing into your ‘current application’? If you are, you probably need to make sure you have at least two back end processes handling requests, otherwise this one method will lock itself. If you have two back end processes handling requests, then you better hope they aren’t both making this same request 😉 and so on.