いろいろアレですが多少不安なところもあるので晒します。
object EncodeUnencodedPart {
private[this] val rfc3986ReservredAndUnreserved = ":/?#[]@!$&'()*+,;=ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~"
private[this] val hexChars = "0123456789ABCDEF"
private[this] def isAscii(ch: Char) = ch > 31 && ch < 127
private[this] def isReservedOrUnreserved(ch: Char) = rfc3986ReservredAndUnreserved.contains(ch.toUpper)
private[this] def isHex(ch: Char) = hexChars.contains(ch.toUpper)
private[this] def percentEncode(ch: Char): String =
ch.toString.getBytes.map(b => "%%%02x".format(b).toUpperCase).mkString
def encode(urlString: String): String = {
val lenMinus2 = urlString.length - 2
(for ((c, i) <- urlString.zipWithIndex) yield {
if (isAscii(c) == false) percentEncode(c)
else if (isReservedOrUnreserved(c)) c.toString
else if (c == '%') {
//%の場合はパーセントエンコードかどうか判定
if (i < lenMinus2 && isHex(urlString.charAt(i + 1)) && isHex(urlString.charAt(i + 2))) c.toString
else percentEncode(c)
} else percentEncode(c)
}).mkString
}
}
- 文字コード中にURLエンコード(percent encode)されてないと思しき箇所があればエンコードする
- 冪等性がある処理にする
- 自分なりにパフォーマンスを気にする
-
0x20
(ホワイトスペース)は%20
とし+
はそのまま