无法从 Rails 应用的 Ruby 中的外部 URL 中提取完整的 header

Unable to pull complete header from external URL in Ruby on Rails app

背景:
我正在开发的 rails 应用程序可以在 iframe 中打开来自其他网站的文章。但是一些发布者网站(如 pitchfork.com、vox.com、medium.com)通过在其 header 中设置 "X-Frame-Options: SAMEORIGIN" 来阻止自己在 iframe 中打开。因此,鉴于文章的 URL,我正在尝试检查 header 并在 iframe(默认)中打开它或在新选项卡中打开原始站点(当我检测到 X-Frame-Options 在 header).


问题:
当我使用以下代码拉取(并打印到控制台)时,我拉入 Rails 的 header 有时不完整:

puts y['site'] # example: "vox.com"
puts y['head'] # example: "/2016/1/25/10829662/obama-on-clinton-media"
require 'net/http'
http = Net::HTTP.start(y['site'])
resp = http.head(y['head'])
resp.each { |k, v| puts "#{k}: #{v}" }
http.finish

示例:rails为这篇vox.com文章(http://www.vox.com/2016/1/25/10829662/obama-on-clinton-media)拉取的header如下:

server: nginx/1.6.2
date: Fri, 29 Jan 2016 22:05:17 GMT
content-type: text/html
content-length: 184
connection: keep-alive
location: http://www.vox.com/2016/1/25/10829662/obama-on-clinton-media

但是当我尝试在 iframe 中打开它时,chrome 控制台告诉我不能,因为 X-Frame-Options 设置为 SAMEORIGIN。在“网络”选项卡中进一步调查后,我能够检查完整的 header,如下所示:

HTTP/1.1 200 OK
Server: nginx
Content-Type: text/html; charset=utf-8
Status: 200 OK
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Cache-Control: max-age=0, must-revalidate
X-Request-Id: 693f75c9be4dde491ba3cd78232ac4870c4f82e2
X-Runtime: 0.404545
Content-Encoding: gzip
Via: 1.1 varnish-v4
Content-Length: 26450
Accept-Ranges: bytes
Date: Fri, 29 Jan 2016 22:10:47 GMT
Via: 1.1 varnish
Age: 106
Connection: keep-alive
X-Served-By: cache-jfk1034-JFK
X-Cache: MISS
X-Cache-Hits: 0
X-Timer: S1454105446.991771,VS0,VE12
Vary: Accept-Encoding, Origin, X-Forwarded-Proto

并非所有网站都会出现此问题。例如,我从 pitchfork.com 中提取的 header 清楚地表明它已设置 x-frame-options 。但是对于像 vox.com 和 medium.com 这样的网站,我拉取的 header 不显示 x-frame-options(以及许多其他被遗漏的项目)。

我怎样才能在我的 Rails 控制器中拉动 correct/complete header 并且总是检测 URL 是否有 X-Frame-Options header?

我在 IRB 控制台中尝试了这里,我注意到对 vox.com 网站的请求正在返回 301 永久移动,并且它在 header.

中发送了新位置
irb(main):001:0> y = {}
=> {}
irb(main):002:0> y['site'] = "vox.com"
=> "vox.com"
irb(main):003:0> y['head'] = "/2016/1/25/10829662/obama-on-clinton-media"
=> "/2016/1/25/10829662/obama-on-clinton-media"
irb(main):004:0> require 'net/http'
=> true
irb(main):005:0> http = Net::HTTP.start(y['site'])
=> #<Net::HTTP vox.com:80 open=true>
irb(main):006:0> resp = http.head(y['head'])
=> #<Net::HTTPMovedPermanently 301 Moved Permanently readbody=true> (HERE)
irb(main):007:0> resp.each { |k, v| puts "#{k}: #{v}" }
server: nginx/1.6.2
date: Fri, 29 Jan 2016 22:40:07 GMT
content-type: text/html
content-length: 184
connection: keep-alive
location: http://www.vox.com/2016/1/25/10829662/obama-on-clinton-media
=> {"server"=>["nginx/1.6.2"], "date"=>["Fri, 29 Jan 2016 22:40:07 GMT"], "content-type"=>["text/html"], "content-length"=>["184"], "connection"=>["keep-alive"], "location"=>["http://www.vox.com/2016/1/25/10829662/obama-on-clinton-media"]}
irb(main):008:0> http.finish
=> nil

您使用的 URL 与服务器为重定向发送的位置之间的唯一区别是 'www'。尝试与 'www' 一起使用,看看它是否有效。

您可以改进代码以读取响应代码,如果是 301,请使用服务器发送的 URL 重试。