Ruby 如何安全地连接相对url段?
我试图找到一种将部分url路径段连接在一起的健壮方法。有没有快速的方法可以做到这一点 我尝试了以下方法:Ruby 如何安全地连接相对url段?,ruby,uri,Ruby,Uri,我试图找到一种将部分url路径段连接在一起的健壮方法。有没有快速的方法可以做到这一点 我尝试了以下方法: puts URI::join('resource/', '/edit', '12?option=test') 我期望: resource/edit/12?option=test 但我得到了一个错误: `merge': both URI are relative (URI::BadURIError) 我过去曾使用过File.join(),但使用文件库作为URL似乎有点不正确。问题在于re
puts URI::join('resource/', '/edit', '12?option=test')
我期望:
resource/edit/12?option=test
但我得到了一个错误:
`merge': both URI are relative (URI::BadURIError)
我过去曾使用过
File.join()
,但使用文件库作为URL似乎有点不正确。问题在于resource/
是相对于当前目录的,但是/edit
由于前导斜杠而指的是顶级目录。如果不知道edit
包含resource
,就不可能加入这两个目录
如果您想要纯字符串操作,只需删除所有部分的前导或尾随斜杠,然后使用
/
作为粘合剂将它们连接起来 URI的api并不一定很棒
只有当第一个URI以协议的绝对URI开始,而后面的URI以正确的方式相对时,join才会起作用。。。除非我试着这么做,但我甚至不能让它发挥作用
这至少不会出错,但为什么会跳过中间的组件呢
URI::join('http://somewhere.com/resource', './edit', '12?option=test')
我想也许乌里有点差劲。它在实例上缺少重要的api,例如实例连接或相对于基本uri求值的方法,这是您所期望的。只是有点糟糕
我想你得自己写。或者只使用File.join和其他文件路径方法,在测试所有您可以想到的边缘情况后,确保它符合您的要求/期望
编辑2016年12月9日我发现创业板做得很好
base = Addressable::URI.parse("http://example.com")
base + "foo.html"
# => #<Addressable::URI:0x3ff9964aabe4 URI:http://example.com/foo.html>
base = Addressable::URI.parse("http://example.com/path/to/file.html")
base + "relative_file.xml"
# => #<Addressable::URI:0x3ff99648bc80 URI:http://example.com/path/to/relative_file.xml>
base = Addressable::URI.parse("https://example.com/path")
base + "//newhost/somewhere.jpg"
# => #<Addressable::URI:0x3ff9960c9ebc URI:https://newhost/somewhere.jpg>
base = Addressable::URI.parse("http://example.com/path/subpath/file.html")
base + "../up-one-level.html"
=> #<Addressable::URI:0x3fe13ec5e928 URI:http://example.com/path/up-one-level.html>
base=Addressable::URI.parse(“http://example.com")
base+“foo.html”
# => #
base=可寻址::URI.parse(“http://example.com/path/to/file.html")
base+“relative_file.xml”
# => #
base=可寻址::URI.parse(“https://example.com/path")
base+“//newhost/somewhere.jpg”
# => #
base=可寻址::URI.parse(“http://example.com/path/subpath/file.html")
基本+“./up-one-level.html”
=> #
使用URI.join的方法是:
URI.join('http://example.com“,”/foo/“,“bar”)
注意后面的斜线。您可以在此处找到完整的文档:
您可以使用
File.join('resource/','/edit','12?option=test')
使用以下代码:
File.join('resource/', '/edit', '12?option=test').
gsub(File::SEPARATOR, '/').
sub(/^\//, '')
# => resource/edit/12?option=test
带有空字符串的示例:
File.join('', '/edit', '12?option=test').
gsub(File::SEPARATOR, '/').
sub(/^\//, '')
# => edit/12?option=test
如果可能,也可以使用此选项来使用诸如resource/
,edit/
,12?option=test
,其中http:
只是获取有效URI的占位符。这对我有用
URI.
join('http:', 'resource/', 'edit/', '12?option=test').
path.
sub(/^\//, '')
# => "resource/edit/12"
正如您所注意到的,
URI::join
不会将路径与重复的斜杠组合在一起,因此它不适合该部分
事实证明,实现这一点不需要很多Ruby代码:
module GluePath
def self.join(*paths, separator: '/')
paths = paths.compact.reject(&:empty?)
last = paths.length - 1
paths.each_with_index.map { |path, index|
_expand(path, index, last, separator)
}.join
end
def self._expand(path, current, last, separator)
if path.start_with?(separator) && current != 0
path = path[1..-1]
end
unless path.end_with?(separator) || current == last
path = [path, separator]
end
path
end
end
该算法处理连续斜杠,保留起始斜杠和结束斜杠,并忽略nil
和空字符串
puts GluePath::join('resource/', '/edit', '12?option=test')
输出
resource/edit/12?option=test
将uri作为
uri::Generic
或其子类
uri.path += '/123'
享受吧
2016年6月25日更新怀疑论者
require 'uri'
uri = URI('http://ioffe.net/boris')
uri.path += '/123'
p uri
输出
<URI::HTTP:0x2341a58 URL:http://ioffe.net/boris/123>
我改进了@Maximo Mussini的脚本,使其能够优雅地工作:
SmartURI.join('http://example.com/subpath', 'hello', query: { token: secret })
=> "http://example.com/subpath/hello?token=secret"
您可以使用以下选项:
URI.join('http://exemple.com', '/a/', 'b/', 'c/', 'd')
=> #<URI::HTTP http://exemple.com/a/b/c/d>
URI.join('http://exemple.com', '/a/', 'b/', 'c/', 'd').to_s
=> "http://exemple.com/a/b/c/d"
URI.join('http://exemple.com“,”/a/“,”b/“,”c/“,”d“)
=> #
URI.join('http://exemple.com","a/","b/","c/","d"
=> "http://exemple.com/a/b/c/d"
请参阅:我对
URI::join的理解是,它的思维方式类似于web浏览器
要对其进行评估,请将mental web浏览器指向第一个参数,并持续单击链接,直到浏览到最后一个参数
例如,URI::join('http://example.com/resource/“,”/edit“,”12?option=test“
,您可以这样浏览:
- ,单击指向
/edit
(站点根目录下的文件)的链接
- ,单击指向
12?option=test
(与edit
位于同一目录中的文件)的链接
如果第一个链接是/edit/
(带尾随斜杠)或/edit/foo
,那么下一个链接将与/edit/
相关,而不是/
本页可能比我解释得更好:一个未优化的解决方案。注意,它不考虑查询参数。它只处理路径
class URL
def self.join(*str)
str.map { |path|
new_path = path
# Check the first character
if path[0] == "/"
new_path = new_path[1..-1]
end
# Check the last character
if path[-1] != "/"
new_path += "/"
end
new_path
}.join
end
end
“使用URL文件库似乎有点不对劲”,这是正确的File.join对操作系统敏感,并将根据操作系统更改用作分隔符的字符。这会给您带来糟糕的结果。除非您不是在域根目录下工作,否则在这种情况下,第一部分的前导/
会产生不同。这很容易强制使用空字符串作为第一个参数。如果您需要自己管理前导和尾随斜杠,首先使用这个方法有什么意义呢?在这种情况下,您会得到一个URI::HTTP对象。虽然你有一个有效的观点,我通常使用File.join('http://example.com“,”/foo/“,“bar”)
当我需要一个字符串时,它会处理斜杠。PS:我只在基于linux的系统和服务器上工作,因此我不会面临上述文件分隔符问题。这是一个幸运的巧合,但它不是表达您意图的正确方法。这不会在Windows上使用吗?如果您需要字符串版本的uri,请不要忘记执行操作,否则,您将获得URI::HTTP
objectAddresable
如果有多个中间段,那么也将跳过中间段。e、 g.(可寻址::URI.parse(“http://example.com“+”abc“+”xyz“)。to_s
生成http://example.com/xyz
。在我最初回答这个问题()多年之后,我仍然认为File.join
是连接URL段的最安全的方式数据这将整个路径组件替换为“/123”,它不会扩展现有路径httpx://example.com/mypath/");
class URL
def self.join(*str)
str.map { |path|
new_path = path
# Check the first character
if path[0] == "/"
new_path = new_path[1..-1]
end
# Check the last character
if path[-1] != "/"
new_path += "/"
end
new_path
}.join
end
end