【问题标题】:Get redirect of a URL in Ruby在 Ruby 中获取 URL 的重定向
【发布时间】:2011-08-17 20:24:39
【问题描述】:

根据 Facebook 图形 API,我们可以使用此(示例)请求用户个人资料图片:

https://graph.facebook.com/1489686594/picture

但是上一个链接的真实图片网址是:

http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs356.snc4/41721_1489686594_527_q.jpg

如果您在浏览器上键入第一个链接,它会将您重定向到第二个链接。

有没有办法通过 Ruby/Rails 获取完整的 URL(第二个链接),只知道第一个 URL?

(这是 this question 的重复,但对于 Ruby)

【问题讨论】:

标签: ruby-on-rails ruby


【解决方案1】:

如果您想要一个解决方案:

  • 不使用宝石
  • 遵循所有重定向
  • 也适用于网址缩短服务
require 'net/http'
require 'uri'

def follow_redirections(url)   
  response = Net::HTTP.get_response(URI(url))
  until response['location'].nil?
    response = Net::HTTP.get_response(URI(response['location']))
  end
  response.uri.to_s
end

# EXAMPLE USAGE
follow_redirections("https://graph.facebook.com/1489686594/picture") 
# => https://static.xx.fbcdn.net/rsrc.php/v3/yo/r/UlIqmHJn-SK.gif

【讨论】:

    【解决方案2】:

    您可以使用get_final_redirect_url 之类的方法检查响应状态代码并递归获取最终 URL:

      require 'net/http'
    
      def get_final_redirect_url(url, limit = 10)
        uri = URI.parse(url)
        response = ::Net::HTTP.get_response(uri)
        if response.class == Net::HTTPOK
          return uri
        else
          redirect_location = response['location']
          location_uri = URI.parse(redirect_location)
          if location_uri.host.nil?
            redirect_location = uri.scheme + '://' + uri.host + redirect_location
          end
          warn "redirected to #{redirect_location}"
          get_final_redirect_url(redirect_location, limit - 1)
        end
      end
    

    我遇到了同样的问题。我解决了它,并围绕它构建了一个gem final_redirect_url,以便每个人都可以从中受益。

    您可以找到使用here 的详细信息。

    【讨论】:

    • 你没有对limit 做任何事情。可能需要return if limit.zero? 或类似的东西。
    • @Hunter 默认限制是10,如果有递归重定向,这意味着如果没有明确提供限制,它会进入最大10级深度,直到找到最终网址。
    • 嗯。我肯定错过了什么。看起来您的递归可以无限继续,因为没有什么可以终止它。我看到您在每次迭代时都在减少 limit,但是,一旦 limit 达到零,您在方法主体的哪个位置指示它停止?
    • 你有一个有效的观点。到目前为止,最后一个响应一直是 Net::HTTPOK,所以我没有陷入无限循环。但我同意,当限制为零时它应该有回报。感谢您指出这一点。
    【解决方案3】:

    我知道这是一个老问题,但我会为后代添加这个答案:

    我见过的大多数解决方案都只遵循一个重定向。就我而言,我必须遵循多个重定向才能获得实际的最终目标 URL。我像这样使用Curl(通过Curb gem):

    result = Curl::Easy.perform(url) do |curl|
      curl.head = true
      curl.follow_location = true
    end
    result.last_effective_url
    

    【讨论】:

      【解决方案4】:

      这已经被正确回答了,但是有一个更简单的方法:

      res = Net::HTTP.get_response(URI('https://graph.facebook.com/1489686594/picture'))
      res['location']
      

      【讨论】:

      • +1 表示发布的解决方案占用的空间不到其他解决方案的 20%,但完成了同样的事情。
      • 这很好,但它只遵循一级重定向:(
      • 太好了,这是我喜欢的解决方案。
      【解决方案5】:

      是的,“位置”响应标头会告诉您实际的图像 URL。

      但是,如果您在您的网站上使用图片作为用户的个人资料图片,我建议您使用“https://graph.facebook.com/:user_id/picture”样式的 URL 而不是实际的图片 URL。 否则,您的用户将来会看到大量“未找到”的图片或过时的个人资料图片。

      您只需将“https://graph.facebook.com/:user_id/picture”作为“img”标签的“src”属性。 他们的浏览器获取用户的更新图像。

      ps。 我在使用 Twitter 和 Yahoo! 的网站上遇到了这样的麻烦!现在打开ID..

      【讨论】:

        【解决方案6】:

        那里有 HTTPS URL,所以你会处理它...

        require 'net/http'
        require 'net/https' if RUBY_VERSION < '1.9'
        require 'uri'
        
        u = URI.parse('https://graph.facebook.com/1489686594/picture')
        
        h = Net::HTTP.new u.host, u.port
        h.use_ssl = u.scheme == 'https'
        
        head = h.start do |ua|
          ua.head u.path
        end
        
        puts head['location']
        

        【讨论】:

        • 实际上,在您的示例中,u.path 将是 "url.com",因为 "url.com" 是一个有效的 URI,只是作为一个 URI 它不包含主机、端口或方案 - 它被视为所有路径通过URI.parse。如果您希望将该数据解释为主机名,那么您需要在将其传递给 URI.parse 之前执行额外的步骤
        • ua.head
        • 这只是一个 HEAD 请求,因为所有 OP 都在寻找 Location: 响应标头。
        • ...是的 Luccas,如果您的 URI 没有路径,那么您也需要添加一些代码来处理它。这不是设计为可以在任何应用程序中导入和使用的通用库。这是特定问题的解决方案 - 因此我的parse 行中的硬编码 URI。
        【解决方案7】:

        您可以使用 Net::Http 并从响应中读取 Location: 标头

        require 'net/http'
        require 'uri'
        
        url = URI.parse('http://www.example.com/index.html')
        res = Net::HTTP.start(url.host, url.port) {|http|
          http.get('/index.html')
        }
        res['location']
        

        【讨论】:

        • 您可以使用 url.request_uri 代替 '/index.html'。
        • 如果有多个重定向怎么办?它会得到最后一个吗?还是第一个?
        • 正如@Sean 提到的,它不会遵循所有重定向。它也不适用于bit.ly 链接。我编写了一个遵循所有重定向的函数,也适用于 url 缩短器,请参阅下面的解决方案。
        猜你喜欢
        • 2015-12-20
        • 2013-06-29
        • 1970-01-01
        • 2013-09-07
        • 2022-01-09
        • 2012-06-25
        • 1970-01-01
        • 1970-01-01
        • 2013-02-24
        相关资源
        最近更新 更多