如何从 Rails 中的相对 URL 构建绝对 URL?

Dav*_*ave 0 ruby url ruby-on-rails href ruby-on-rails-5

我正在使用 Rails 5。我正在尝试找出一种方法,根据我从锚标记的 href 属性中删除的值来获取绝对 URL。我想出了

url = a.attr("href")
if url !~ /^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/ix
  url = "http://#{url}"
end
Run Code Online (Sandbox Code Playgroud)

认为如果 href 只是“www.mydomain.com”,我可以通过附加“http://”来创建正确的 URL。然而,如果URl是相对的(例如“/abc/def”),则上述逻辑失败。有没有一种万无一失的方法可以从锚标记的 HREF 属性构建绝对 URL,该属性本身可能是也可能不是绝对 URL?请注意,我确实可以访问包含带有锚标记的页面的原始 URL。

编辑: 但是你是说,嘿,对不起,SOB,这不是浏览器处理 href 的方式。如果它看到“www.whatever.com”,它会将其视为相对路径!所以你的问题是假的!好吧,纸杯蛋糕,尽管你是对的,但这不是我的问题。我想识别一个域并将其转换为有效的 URL,并识别以“/”开头的路径并将其转换为有效的 URL。你说不可能?以此作为你的答案,当其他人同意你的观点时,你的分数就会上升。

dtr*_*oof 5

我建议使用 URI.join,它是内置 URI 库的一部分。

一个主要好处是,它可以解析给定页面绝对 URL 的任何相对 URL,特别是当您从网页解析 href 属性时。

require 'uri'

base = 'http://example.com/subsection/'

URI.join(base, 'inner.html')        #=> http://example.com/subsection/inner.html
URI.join(base, '/index.html')       #=> http://example.com/index.html
URI.join(base, 'http://google.com') #=> http://google.com
Run Code Online (Sandbox Code Playgroud)

编辑:对以“www.example.com”开头的 href 进行例外处理会增加另一个问题。将其视为域是不标准的。鉴于该免责声明,这是一个快速而肮脏的正则表达式,可能会有所帮助:

href = 'www.example.com'
href.gsub!(/^((([a-z0-9\-]*)\.)+(com|net|org|edu))\/?/i, 'http://\1/') #=> http://www.example.com/
URI.join(base, href) #=> http://www.example.com/
Run Code Online (Sandbox Code Playgroud)

请记住,任何标准 URI 解析器都不会出现同样的异常。每个主要浏览器都会将“www.example.com”视为路径而不是域名。如果您从实时网页获取这些 href,则链接已经损坏。