Ruby:强制open-uri返回IPv4地址

时间:2013-09-13 19:31:24

标签: ruby-on-rails ruby open-uri

在我们的Rails应用程序中,我们有一个控制器操作,可以打开一个外部URL,并将其作为JSON返回给我们的前端消费。

今天,我收到了以下错误:

Errno::EAFNOSUPPORT: Address family not supported by protocol - socket(2)

我们的开发人员建议,如果地址返回IPv6响应以及IPv4响应,则这将是错误。我们不支持IPv6,因此可以解释它。

以下是触发请求的方法:

def medline_response
  open("http://apps.nlm.nih.gov/medlineplus/services/mpconnect_service.cfm?mainSearchCriteria.v.cs=#{codesys}&mainSearchCriteria.v.c=#{code}")
end

实际上,来自该服务器主机的响应:

$ host apps.nlm.nih.gov
apps.nlm.nih.gov is an alias for apps.wip.nlm.nih.gov.
apps.wip.nlm.nih.gov has address 130.14.16.117
apps.wip.nlm.nih.gov has IPv6 address 2607:f220:41e:1016::117

docs for open-uri对IP版本没有任何说明。是否有一个参数可以传递到强制它读取IPv4的open方法,或者另一种方法来解决这个问题?

修改

当我尝试从控制台打开谷歌时,我明白了:

[18] pry(main)> require 'open-uri'
=> false
[19] pry(main)> open 'http://google.com'   
=> #<File:/var/folders/hq/7_rgkt4565q728y91dtqzs2r2wxb1y/T/open-uri20130913-50258-1af4zhv>

因此看起来IPv6地址不是问题。

编辑2

$ ruby -v
ruby 1.9.3p385 (2013-02-06 revision 39114) [x86_64-darwin11.4.2]

OS X 10.7.5

编辑3

这是每个人最喜欢的错误:间歇性错误。这是当我在open-uri对象上调用read时会发生什么。我在本地获得了相同的输出以及我们所有的3个应用服务器。

[22] pry(main)> open("http://apps.nlm.nih.gov/medlineplus/services/mpconnect_service.cfm?mainSearchCriteria.v.cs=2.16.840.1.113883.6.103&mainSearchCriteria.v.c=238.4").read
=> "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<feed xml:base=\"http://apps.nlm.nih.gov/medlineplus/services/\" xml:lang=\"en\" xmlns=\"http://www.w3.org/2005/Atom\" xmlns:v3=\"urn:hl7-org:v3\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><title type=\"text\">MedlinePlus Connect</title><subtitle type=\"text\">MedlinePlus Connect results for ICD-9-CM 238.4</subtitle><author><name>U.S. National Library of Medicine</name><uri>http://www.nlm.nih.gov</uri></author><updated type=\"text\">2013-09-13T12:09:48Z</updated><category scheme=\"REDS_MT010001UV\" term=\"MATCHED\"><v3:mainSearchCriteria classCode=\"OBS\" moodCode=\"DEF\" xmlns:v3=\"urn:hl7-org:v3\"><v3:code code=\"KSUBJ\" codeSystem=\"2.16.840.1.113883.5.4\" xmlns:v3=\"urn:hl7-org:v3\"/><v3:value code=\"238.4\" codeSystem=\"2.16.840.1.113883.6.103\" displayName=\"\" xmlns:v3=\"urn:hl7-org:v3\"/></v3:mainSearchCriteria><v3:informationRecipient typeCode=\"IRCP\" xmlns:v3=\"urn:hl7-org:v3\"><v3:patient classCode=\"PAT\" xmlns:v3=\"urn:hl7-org:v3\"/></v3:informationRecipient></category><id></id><entry><title>Bone Marrow Diseases</title><link href=\"http://www.nlm.nih.gov/medlineplus/bonemarrowdiseases.html\" rel=\"alternate\"/><id>tag: nlm.nih.gov, 2013-13-09:/medlineplus/bonemarrowdiseases.html</id><updated>2013-09-13T12:09:48Z</updated><summary type=\"html\">&lt;p&gt;Bone marrow is the spongy tissue inside some of your bones, such as your hip and thigh bones. It contains immature cells, called stem cells. The stem cells can develop into the red blood cells that carry oxygen through your body, the white blood cells that fight infections, and the platelets that help with blood clotting. &lt;/p&gt;&#xd;&#xd;&lt;p&gt;If you have a bone marrow disease, there are problems with the stem cells or how they develop. &lt;a href=\"http://www.nlm.nih.gov/medlineplus/leukemia.html\"&gt;Leukemia&lt;/a&gt; is a cancer in which the bone marrow produces abnormal white blood cells. With &lt;a href=\"http://www.nlm.nih.gov/medlineplus/aplasticanemia.html\"&gt;aplastic anemia&lt;/a&gt;, the bone marrow doesn't make red blood cells. Other diseases, such as &lt;a href=\"http://www.nlm.nih.gov/medlineplus/lymphoma.html\"&gt;lymphoma&lt;/a&gt;, can spread into the bone marrow and affect the production of blood cells.  Other causes of bone marrow disorders include your genetic makeup and environmental factors.&lt;/p&gt; &#xd;&#xd;&lt;p&gt;Symptoms of bone marrow diseases vary. Treatments depend on the disorder and how severe it is. They might involve medicines, blood transfusions or a &lt;a href=\"http://www.nlm.nih.gov/medlineplus/bonemarrowtransplantation.html\"&gt;bone marrow transplant&lt;/a&gt;. &lt;/p&gt;&#xd; &lt;p class=\"NLMrelatedLinks\"&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=\"http://www.nlm.nih.gov/medlineplus/ency/article/003658.htm\"&gt;Bone marrow aspiration&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=\"http://www.nlm.nih.gov/medlineplus/ency/article/003934.htm\"&gt;Bone marrow biopsy&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=\"http://www.nlm.nih.gov/medlineplus/ency/article/003682.htm\"&gt;Bone marrow culture&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=\"http://www.nlm.nih.gov/medlineplus/ency/article/003009.htm\"&gt;Bone marrow transplant&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=\"http://www.nlm.nih.gov/medlineplus/ency/patientinstructions/000010.htm\"&gt;Bone marrow transplant - discharge&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=\"http://www.nlm.nih.gov/medlineplus/ency/article/000589.htm\"&gt;Polycythemia vera&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=\"http://www.nlm.nih.gov/medlineplus/ency/article/000531.htm\"&gt;Primary myelofibrosis&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;</summary></entry></feed>  \n\n"

也就是说,它会将HTML作为字符串返回,就像您期望的那样。

1 个答案:

答案 0 :(得分:0)

您似乎需要更新的红宝石,请参阅ruby bug report

你可以强迫&#34; open-uri使用ip例如:

require 'open-uri'
require 'socket'

url = "google.com"
ip = IPSocket::getaddress(url)

open("http://#{url}") do |f|
  puts "i'm using url #{url} #{f.base_uri}"
end
open("http://#{ip}") do |f|
  puts "i'm using ip #{ip} #{f.base_uri}"
end