ウェブサービスを作っています。

URI Encode と Punycode の共存

http://日本語.jp/カ/ひ?a=漢

みたいな URL を Ruby

http://xn--wgv71a119e.jp/%E3%82%AB/%E3%81%B2?a=%E6%BC%A2

に変換する必要があったので、適当にでっち上げました。
弾さんの記事に感謝。あと、punycode4r っていう gem のおかげです。


とりあえず encode だけ。

# -*- coding: utf-8 -*-
require 'rubygems'
require 'punycode'
require 'uri'
require 'open-uri'

$KCODE='u'

def encode_punicode_url(str)
  URI.encode str.sub(/\:\/\/([^\/]+)/) {
    str = $1

    re_fullstop = [0x002E, 0x0589, 0x06D4, 0x0701, 0x0702, 0x1362, 0x166E, 0x1803,
      0x1809, 0x2CF9, 0x2CFE, 0x3002, 0xFE12, 0xFE52, 0xFF0E, 0xFF61].map { |v| [v].pack('U') }.join
    re_fullstop = Regexp.new("[#{ re_fullstop }]")

    words = str.downcase.split(re_fullstop)
    words.each_with_index { |word, i|
      next if word =~ /[0-9a-z\-]/
      words[i] = "xn--#{ Punycode.encode(word) }"
    }

    "://#{ words * '.' }"
  }
end

encode_punicode_url('http://日本語.jp/カ/ひ?a=漢')  # => http://xn--wgv71a119e.jp/%E3%82%AB/%E3%81%B2?a=%E6%BC%A2