Ruby 规范化HTTP URI

Ruby 规范化HTTP URI,ruby,uri,Ruby,Uri,我从Akamai的日志文件中获取URI,其中包括以下条目: /foo/jim/jam /福/吉姆/果酱? /foo//jim/jam /foo/bar//jim/jam /foo/jim/jam?autho=&file=jam 我希望根据规则将所有这些标准化为同一条目: 如果有查询字符串,则从中剥离autho和file 如果查询字符串为空,请删除尾随的? 应删除/的目录项 应删除/../的目录项 我本以为Ruby库会涵盖这一点,但是: 它不提供任何解析查询字符串部分的机制。(这不是很难做

我从Akamai的日志文件中获取URI,其中包括以下条目:

/foo/jim/jam
/福/吉姆/果酱?
/foo//jim/jam
/foo/bar//jim/jam
/foo/jim/jam?autho=&file=jam
我希望根据规则将所有这些标准化为同一条目:

  • 如果有查询字符串,则从中剥离
    autho
    file
  • 如果查询字符串为空,请删除尾随的
  • 应删除
    /
    的目录项
  • 应删除
    /../
    的目录项
我本以为Ruby库会涵盖这一点,但是:

  • 它不提供任何解析查询字符串部分的机制。(这不是很难做到,也不是标准。)
  • 如果查询字符串为空,则不会删除尾随的

    URI.parse('/foo?jim').tap{ |u| u.query='' }.to_s #=> "/foo?"
    
  • normalize
    方法不会清除路径中的
因此,如果没有一个官方图书馆,我发现自己正在编写一个基于正则表达式的解决方案

def normalize(path)
  result = path.dup
  path.sub! /(?<=\?).+$/ do |query|
    query.split('&').reject do |kv|
      %w[ autho file ].include?(kv[/^[^=]+/])
    end.join('&')
  end
  path.sub! /\?$/, ''
  path.sub!(/^[^?]+/){ |path| path.gsub(%r{[^/]+/\.\.},'').gsub('/./','/') }
end
def正常化(路径)
结果=path.dup
path.sub/(?gem将为您标准化这些:

require 'addressable/uri'

# normalize relative paths
uri = Addressable::URI.parse('http://example.com/foo/bar/../jim/jam')
puts uri.normalize.to_s #=> "http://example.com/foo/jim/jam"

# removes trailing ?
uri = Addressable::URI.parse('http://example.com/foo/jim/jam?')
puts uri.normalize.to_s #=> "http://example.com/foo/jim/jam"

# leaves empty parameters alone
uri = Addressable::URI.parse('http://example.com/foo/jim/jam?jim')
puts uri.normalize.to_s #=> "http://example.com/foo/jim/jam?jim"

# remove specific query parameters
uri = Addressable::URI.parse('http://example.com/foo/jim/jam?autho=<randomstring>&file=jam')
cleaned_query = uri.query_values
cleaned_query.delete('autho')
cleaned_query.delete('file')
uri.query_values = cleaned_query
uri.normalize.to_s #=> "http://example.com/foo/jim/jam"
需要“可寻址/uri”
#规范化相对路径
uri=可寻址::uri.parse('http://example.com/foo/bar/../jim/jam')
将uri.normalize.to#u s#=>”http://example.com/foo/jim/jam"
#删除尾随?
uri=可寻址::uri.parse('http://example.com/foo/jim/jam?')
将uri.normalize.to#u s#=>”http://example.com/foo/jim/jam"
#只保留空参数
uri=可寻址::uri.parse('http://example.com/foo/jim/jam?jim')
将uri.normalize.to#u s#=>”http://example.com/foo/jim/jam?jim"
#删除特定的查询参数
uri=可寻址::uri.parse('http://example.com/foo/jim/jam?autho=&file=jam')
已清除的\u query=uri.query\u值
已清理的\u查询。删除('autho')
已清理\u查询。删除('文件')
uri.query\u values=已清理的\u查询
uri.normalize.to#u s#=>”http://example.com/foo/jim/jam"
真正重要的是,需要记住的是,URL/URI是一个协议,一个主机,一个指向资源的文件路径,然后是传递给被引用资源的选项/参数。(对于学究来说,还有其他可选的东西,但这已经足够了。)

我们可以通过使用类和方法对URL进行解析,从URL中提取路径。获得路径后,我们将根据站点的根拥有绝对路径或相对路径。处理绝对路径很容易:

require 'uri'

%w[
  /foo/jim/jam
  /foo/jim/jam?
  /foo/./jim/jam
  /foo/bar/../jim/jam
  /foo/jim/jam?autho=<randomstring>&file=jam
].each do |url|
  uri = URI.parse(url)
  path = uri.path
  puts File.absolute_path(path)
end
# >> /foo/jim/jam
# >> /foo/jim/jam
# >> /foo/jim/jam
# >> /foo/jim/jam
# >> /foo/jim/jam
require'uri'
%w[
/foo/jim/jam
/福/吉姆/果酱?
/foo//jim/jam
/foo/bar//jim/jam
/foo/jim/jam?autho=&file=jam
].每个do | url|
uri=uri.parse(url)
path=uri.path
放置文件。绝对路径(path)
结束
#>>/foo/jim/jam
#>>/foo/jim/jam
#>>/foo/jim/jam
#>>/foo/jim/jam
#>>/foo/jim/jam
因为路径是基于服务器根目录的文件路径,所以我们可以使用Ruby的方法玩游戏来规范化“.”和“..”并获得真正的绝对路径。如果有更多的
,这将中断。
(父目录)而不是目录链,但您不应该在提取的路径中找到,因为这也会破坏服务器/浏览器服务/请求/接收资源的能力


当处理相对路径时,它变得更“有趣”,但文件仍然是我们的朋友,但这是一个不同的问题。

这很好,但对于一个(非常小的)问题:请求/设置
query\u值
会导致查询值按字母顺序排序。因此,往返“OK”通过此URL不必要地将其更改为(功能相同但不同的内容)。
CGI::parse
URI::split
可以帮助
URI规范化!
可以从中受益。在2.3.0中,它只是将“”更改为“/”,并关闭方案和主机。