-
Notifications
You must be signed in to change notification settings - Fork 34
/
PercentEncoder.scala
48 lines (36 loc) · 1.6 KB
/
PercentEncoder.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package io.lemonlabs.uri.encoding
import PercentEncoder._
case class PercentEncoder(charsToEncode: Set[Char] = DEFAULT_CHARS_TO_ENCODE) extends UriEncoder {
def shouldEncode(ch: Char) = {
!ascii(ch) || charsToEncode.contains(ch)
}
def encodeChar(ch: Char) = "%" + toHex(ch)
def toHex(ch: Char) = "%04x".format(ch.toInt).substring(2).toUpperCase
/** Determines if this character is in the ASCII range (excluding control characters)
*/
def ascii(ch: Char) = ch > 31 && ch < 127
def --(chars: Char*) = new PercentEncoder(charsToEncode.diff(chars.toSet))
def ++(chars: Char*) = new PercentEncoder(charsToEncode ++ chars)
}
object PercentEncoder {
val USER_INFO_CHARS_TO_ENCODE = Set(
' ', '%', '<', '>', '[', ']', '#', '{', '}', '^', '`', '|', '?', '@', ':', '/'
)
val PATH_CHARS_TO_ENCODE = Set(
' ', '%', '<', '>', '[', ']', '#', '{', '}', '^', '`', '|', '?', '/'
)
val QUERY_CHARS_TO_ENCODE = Set(
'%', '<', '>', '[', ']', '#', '{', '}', '^', '`', '|', '&', '\\', '+', '='
)
val FRAGMENT_CHARS_TO_ENCODE = Set(
' ', '%', '<', '>', '[', ']', '#', '{', '}', '^', '`', '|'
)
val GEN_DELIMS = Set(':', '/', '?', '#', '[', ']', '@')
val SUB_DELIMS = Set('!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=')
val RESERVED = GEN_DELIMS ++ SUB_DELIMS
val EXCLUDED = Set('"') // RFC 2396 section 2.4.3
/** Probably more than you need to percent encode. Wherever possible try to use a tighter Set of characters
* to encode depending on your use case
*/
val DEFAULT_CHARS_TO_ENCODE = RESERVED ++ PATH_CHARS_TO_ENCODE ++ QUERY_CHARS_TO_ENCODE ++ EXCLUDED
}