環境。


$ uname -mvrs
Darwin 10.7.0 Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386 i386
 
$ ruby -v
ruby 1.8.7 (2009-06-12 patchlevel 174) [universal-darwin10.0]

URL/URIをパースしてどんな情報になるかのサンプルコード。


$ cat ./uriparse.rb 
require 'uri'
 
urilist = [
  'http://www.nilab.info/a?b=c&d=e',
  'https://www.nilab.info/a?b=c&d=e',
  'ftp://ftp.nilab.info/path;type=i',
  'ldap://ldap.nilab.info/dn',
  'mailto:hoge@example.com?subject=daimei&cc=kabonkopi',
  'file:///home/hoge/a.txt',
]
 
urilist.each{|str|
  uri = URI.parse(str)
  puts uri.inspect
  puts uri.class.inspect
  uri.component.each{|s|
    puts "#{s}=#{uri.select(s)}"
  }
  puts ''
}

実行結果。


$ ruby ./uriparse.rb 
#<URI::HTTP:0x1003839b0 URL:http://www.nilab.info/a?b=c&d=e>
URI::HTTP
scheme=http
userinfo=
host=www.nilab.info
port=80
path=/a
query=b=c&d=e
fragment=
 
#<URI::HTTPS:0x100382e48 URL:https://www.nilab.info/a?b=c&d=e>
URI::HTTPS
scheme=https
userinfo=
host=www.nilab.info
port=443
path=/a
query=b=c&d=e
fragment=
 
#<URI::FTP:0x100382308 URL:ftp://ftp.nilab.info/path;type=i>
URI::FTP
scheme=ftp
userinfo=
host=ftp.nilab.info
port=21
path=path
typecode=i
 
#<URI::LDAP:0x100381728 URL:ldap://ldap.nilab.info/dn>
URI::LDAP
scheme=ldap
host=ldap.nilab.info
port=389
dn=dn
attributes=
scope=
filter=
extensions=
 
#<URI::MailTo:0x100380b48 URL:mailto:hoge@example.com?subject=daimei&cc=kabonkopi>
URI::MailTo
scheme=mailto
to=hoge@example.com
headers=subjectdaimeicckabonkopi
 
#<URI::Generic:0x10037fe78 URL:file:/home/hoge/a.txt>
URI::Generic
scheme=file
userinfo=
host=
port=
registry=
path=/home/hoge/a.txt
opaque=
query=
fragment=

多少おかしなURIでもパースできるか(あるいはちゃんとエラー発生してくれるか)の実験サンプルコード。
URIにバックスペースとか入れてみたけど、制御文字が入っていると InvalidURIError が出るっぽい。


$ cat ./urisec.rb 
require 'uri'
 
# back space attacks
uri_list = [
  'http://www.nilab.info/a?b=c&d=e',
  'http://localhost/a?b=c&d=e',
  'http://127.0.0.1/a?b=c&d=e',
  'file:///home/hoge/a.txt',
  'http://nilab.info/\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bfile://home/hoge/a.txt',
  'http:\b\b\b\b\bfile:///home/hoge/a.txt',
  'http://nilab.info/a\n',
]
 
# 排除するホスト(というか前方一致文字列)
$ban_list = [
  'http://localhost',
  'http://127.0.0.1',
]
 
# with secure check
def get_uri(str)
  begin
    $ban_list.each{|ban|
      raise 'bad URI: ban list' if /^#{ban}/ =~ str
    }
    uri = URI.parse(str)
    raise 'bad URI: ban kind' if !uri.kind_of?(URI::HTTP)
    return uri
  rescue
    puts $!.inspect
    return nil
  end
end
 
uri_list.each{|str|
  puts '--------------------------------------------------'
  puts str
  uri = get_uri(str)
  puts uri.inspect
}

実行結果。


$ ruby ./urisec.rb 
--------------------------------------------------
http://www.nilab.info/a?b=c&d=e
#<URI::HTTP:0x100382cb8 URL:http://www.nilab.info/a?b=c&d=e>
--------------------------------------------------
http://localhost/a?b=c&d=e
#<RuntimeError: bad URI: ban list>
nil
--------------------------------------------------
http://127.0.0.1/a?b=c&d=e
#<RuntimeError: bad URI: ban list>
nil
--------------------------------------------------
file:///home/hoge/a.txt
#<RuntimeError: bad URI: ban kind>
nil
--------------------------------------------------
http://nilab.info/\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bfile://home/hoge/a.txt
#<URI::InvalidURIError: bad URI(is not URI?): http://nilab.info/\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bfile://home/hoge/a.txt>
nil
--------------------------------------------------
http:\b\b\b\b\bfile:///home/hoge/a.txt
#<URI::InvalidURIError: bad URI(is not URI?): http:\b\b\b\b\bfile:///home/hoge/a.txt>
nil
--------------------------------------------------
http://nilab.info/a\n
#<URI::InvalidURIError: bad URI(is not URI?): http://nilab.info/a\n>
nil

Ref. Ruby 1.8.7 リファレンスマニュアル > ライブラリ一覧 > uriライブラリ (library uri)

tags: ruby

Posted by NI-Lab. (@nilab)