<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>lubyruffy (LubyRuffy)</title>
    <link>https://ruby-china.org/lubyruffy</link>
    <description></description>
    <language>en-us</language>
    <item>
      <title>net/http 库的一个让人抓狂的 bug</title>
      <description>&lt;p&gt;我用 net http 去请求一个 https 的页面，如下两种方法在某些网站返回居然不同：
1、先用 ip 连接，然后手动设置 Host 头
2、直接用 host 连接
绝大部分情况下都是正常的，只有在少部分网站返回的结果完全不一样（一个返回 200，一个返回 404），比如下面的演示：&lt;/p&gt;

&lt;p&gt;#!/usr/bin/env ruby
require 'net/http'
require 'uri'
require 'open-uri'
require 'openssl'&lt;/p&gt;

&lt;p&gt;&lt;a href="/uri" class="user-mention" title="@uri"&gt;&lt;i&gt;@&lt;/i&gt;uri&lt;/a&gt; = URI('&lt;a href="https://ebs.shasteel.cn" rel="nofollow" target="_blank"&gt;https://ebs.shasteel.cn&lt;/a&gt;')&lt;/p&gt;

&lt;p&gt;def get_ip_of_host(host)
  require 'socket'
  ip = Socket.getaddrinfo(host, nil)
  return nil if !ip || !ip[0] || !ip[0][2]
  ip[0][2]
rescue =&amp;gt; e
  nil
end&lt;/p&gt;

&lt;p&gt;def test_connect_ip
  ip = get_ip_of_host(&lt;a href="/uri.host" class="user-mention" title="@uri.host"&gt;&lt;i&gt;@&lt;/i&gt;uri.host&lt;/a&gt;)
  http = Net::HTTP.new(ip, &lt;a href="/uri.port" class="user-mention" title="@uri.port"&gt;&lt;i&gt;@&lt;/i&gt;uri.port&lt;/a&gt;)
  http.use_ssl = true if &lt;a href="/uri.scheme" class="user-mention" title="@uri.scheme"&gt;&lt;i&gt;@&lt;/i&gt;uri.scheme&lt;/a&gt; == 'https'
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  http.set_debug_output($stdout)
  http.start { |h|
    request = Net::HTTP::Get.new &lt;a href="/uri.request_uri" class="user-mention" title="@uri.request_uri"&gt;&lt;i&gt;@&lt;/i&gt;uri.request_uri&lt;/a&gt;
    request['Host'] = &lt;a href="/uri.host" class="user-mention" title="@uri.host"&gt;&lt;i&gt;@&lt;/i&gt;uri.host&lt;/a&gt;
    response = h.request request
    puts response.code
  }
end&lt;/p&gt;

&lt;p&gt;def test_connect_host
  http = Net::HTTP.new(&lt;a href="/uri.host" class="user-mention" title="@uri.host"&gt;&lt;i&gt;@&lt;/i&gt;uri.host&lt;/a&gt;, &lt;a href="/uri.port" class="user-mention" title="@uri.port"&gt;&lt;i&gt;@&lt;/i&gt;uri.port&lt;/a&gt;)
  http.use_ssl = true if &lt;a href="/uri.scheme" class="user-mention" title="@uri.scheme"&gt;&lt;i&gt;@&lt;/i&gt;uri.scheme&lt;/a&gt; == 'https'
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  http.set_debug_output($stdout)
  http.start { |h|
    request = Net::HTTP::Get.new &lt;a href="/uri.request_uri" class="user-mention" title="@uri.request_uri"&gt;&lt;i&gt;@&lt;/i&gt;uri.request_uri&lt;/a&gt;
    response = h.request request
    puts response.code
  }
end&lt;/p&gt;

&lt;p&gt;test_connect_ip #will be 400
test_connect_host #will be 200&lt;/p&gt;

&lt;p&gt;============我打开了发包调试，可以看到发送和接收的包内容==============
opening connection to 61.177.60.85:443...
opened
starting SSL for 61.177.60.85:443...
SSL established
&amp;lt;- "GET / HTTP/1.1\r\nAccept-Encoding:
gzip;q=1.0,deflate;q=0.6,identity;q=0.3\r\nAccept: &lt;em&gt;/&lt;/em&gt;\r\nUser-Agent:
Ruby\r\nHost: ebs.shasteel.cn\r\n\r\n"
-&amp;gt; "HTTP/1.1 400 Bad Request\r\n"
-&amp;gt; "Date: Wed, 03 Sep 2014 11:43:55 GMT\r\n"
-&amp;gt; "Server: Apache/2.2.17 (Win32) mod_ssl/2.2.17 OpenSSL/0.9.8o\r\n"
-&amp;gt; "Content-Length: 226\r\n"
-&amp;gt; "Connection: close\r\n"
-&amp;gt; "Content-Type: text/html; charset=iso-8859-1\r\n"
-&amp;gt; "\r\n"
reading 226 bytes...
-&amp;gt; ""
-&amp;gt; "&amp;lt;!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML
2.0//EN\"&amp;gt;\n&lt;/p&gt;\n400 Bad
Request\n\n&lt;h1&gt;Bad Request&lt;/h1&gt;\n&lt;p&gt;Your browser
sent a request that this server could not understand.&lt;br&gt;\n&lt;/p&gt;\n\n"
read 226 bytes
Conn close
400

&lt;p&gt;opening connection to ebs.shasteel.cn:443...
opened
starting SSL for ebs.shasteel.cn:443...
SSL established
&amp;lt;- "GET / HTTP/1.1\r\nAccept-Encoding:
gzip;q=1.0,deflate;q=0.6,identity;q=0.3\r\nAccept: &lt;em&gt;/&lt;/em&gt;\r\nUser-Agent:
Ruby\r\nHost: ebs.shasteel.cn\r\n\r\n"
-&amp;gt; "HTTP/1.1 200 OK\r\n"
-&amp;gt; "Date: Wed, 03 Sep 2014 11:43:55 GMT\r\n"
-&amp;gt; "Server: Apache/2.2.17 (Win32) mod_ssl/2.2.17 OpenSSL/0.9.8o\r\n"
-&amp;gt; "Accept-Ranges: bytes\r\n"
-&amp;gt; "Content-Length: 341\r\n"
-&amp;gt; "Last-Modified: Fri, 16 Dec 2011 01:35:36 GMT\r\n"
-&amp;gt; "X-Powered-By: Servlet/2.4 JSP/2.0\r\n"
-&amp;gt; "Content-Type: text/html\r\n"
-&amp;gt; "\r\n"
reading 341 bytes...
-&amp;gt; ""
-&amp;gt; "&amp;lt;%@ page language=\"java\" contentType=\"text/html;
charset=UTF-8\"\n    pageEncoding=\"UTF-8\"%&amp;gt;\n&amp;lt;!DOCTYPE html PUBLIC
\"-//W3C//DTD HTML 4.01 Transitional//EN\"
\"&lt;a href="http://www.w3.org/TR/html4/loose.dtdn" rel="nofollow" target="_blank"&gt;http://www.w3.org/TR/html4/loose.dtdn&lt;/a&gt;\"&amp;gt;\\n... \n\t\t\n\t\t\n\n&lt;/p&gt;\n\n</description>
      <author>lubyruffy</author>
      <pubDate>Wed, 03 Sep 2014 21:10:26 +0800</pubDate>
      <link>https://ruby-china.org/topics/21371</link>
      <guid>https://ruby-china.org/topics/21371</guid>
    </item>
  </channel>
</rss>
