Skip to content

Commit 20edd60

Browse files
authored
URL escape and unescape normalier. Fixes #110 (#119)
# Describe Request URL escape and unescape normalier. Fixes #110 # Change Type New normalizer.
1 parent 0dc52b4 commit 20edd60

File tree

8 files changed

+184
-1
lines changed

8 files changed

+184
-1
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,15 @@ This package currently provides the following checkers:
9999
This package currently provides the following normalizers. They can be mixed with the checkers when defining the validation steps for user data.
100100

101101
- [html-escape](doc/normalizers/html_escape.md) applies HTML escaping to special characters.
102-
- [html-unescape](doc//normalizers/html_unescape.md) applies HTML unescaping to special characters.
102+
- [html-unescape](doc/normalizers/html_unescape.md) applies HTML unescaping to special characters.
103103
- [lower](doc/normalizers/lower.md) maps all Unicode letters in the given value to their lower case.
104104
- [upper](doc/normalizers/upper.md) maps all Unicode letters in the given value to their upper case.
105105
- [title](doc/normalizers/title.md) maps the first letter of each word to their upper case.
106106
- [trim](doc/normalizers/trim.md) removes the whitespaces at the beginning and at the end of the given value.
107107
- [trim-left](doc/normalizers/trim_left.md) removes the whitespaces at the beginning of the given value.
108108
- [trim-right](doc/normalizers/trim_right.md) removes the whitespaces at the end of the given value.
109+
- [url-escape](doc/normalizers/url_escape.md) applies URL escaping to special characters.
110+
- [url-unescape](doc/normalizers/url_unescape.md) applies URL unescaping to special characters.
109111

110112
# Custom Checkers
111113

checker.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ var makers = map[string]MakeFunc{
6666
NormalizerTrim: makeTrim,
6767
NormalizerTrimLeft: makeTrimLeft,
6868
NormalizerTrimRight: makeTrimRight,
69+
NormalizerURLEscape: makeURLEscape,
70+
NormalizerURLUnescape: makeURLUnescape,
6971
}
7072

7173
// Register registers the given checker name and the maker function.

doc/normalizers/url_escape.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# URL Escape Normalizer
2+
3+
The `url-escape` normalizer uses [net.url.QueryEscape](https://pkg.go.dev/net/url#QueryEscape) to escape the string so it can be safely placed inside a URL query.
4+
5+
```golang
6+
type Request struct {
7+
Query string `checkers:"url-escape"`
8+
}
9+
10+
request := &Request{
11+
Query: "param1/param2 = 1 + 2 & 3 + 4",
12+
}
13+
14+
_, valid := checker.Check(request)
15+
if !valid {
16+
t.Fail()
17+
}
18+
19+
// Outputs:
20+
// param1%2Fparam2+%3D+1+%2B+2+%26+3+%2B+4
21+
fmt.Println(request.Query)
22+
```

doc/normalizers/url_unescape.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# URL Unescape Normalizer
2+
3+
The `url-unescape` normalizer uses [net.url.QueryUnescape](https://pkg.go.dev/net/url#QueryUnescape) to converte each 3-byte encoded substring of the form "%AB" into the hex-decoded byte 0xAB.
4+
5+
```golang
6+
type Request struct {
7+
Query string `checkers:"url-unescape"`
8+
}
9+
10+
request := &Request{
11+
Query: "param1%2Fparam2+%3D+1+%2B+2+%26+3+%2B+4",
12+
}
13+
14+
_, valid := checker.Check(request)
15+
if !valid {
16+
t.Fail()
17+
}
18+
19+
if request.Query != "param1/param2 = 1 + 2 & 3 + 4" {
20+
t.Fail()
21+
}
22+
23+
// Outputs:
24+
// param1/param2 = 1 + 2 & 3 + 4
25+
fmt.Println(comment.Body)
26+
```

url_escape.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package checker
2+
3+
import (
4+
"net/url"
5+
"reflect"
6+
)
7+
8+
// NormalizerURLEscape is the name of the normalizer.
9+
const NormalizerURLEscape = "url-escape"
10+
11+
// makeURLEscape makes a normalizer function for the URL escape normalizer.
12+
func makeURLEscape(_ string) CheckFunc {
13+
return normalizeURLEscape
14+
}
15+
16+
// normalizeURLEscape applies URL escaping to special characters.
17+
// Uses net.url.QueryEscape for the actual escape operation.
18+
func normalizeURLEscape(value, _ reflect.Value) Result {
19+
if value.Kind() != reflect.String {
20+
panic("string expected")
21+
}
22+
23+
value.SetString(url.QueryEscape(value.String()))
24+
25+
return ResultValid
26+
}

url_escape_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package checker_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/cinar/checker"
7+
)
8+
9+
func TestNormalizeURLEscapeNonString(t *testing.T) {
10+
defer checker.FailIfNoPanic(t)
11+
12+
type Request struct {
13+
Query int `checkers:"url-escape"`
14+
}
15+
16+
request := &Request{}
17+
18+
checker.Check(request)
19+
}
20+
21+
func TestNormalizeURLEscape(t *testing.T) {
22+
type Request struct {
23+
Query string `checkers:"url-escape"`
24+
}
25+
26+
request := &Request{
27+
Query: "param1/param2 = 1 + 2 & 3 + 4",
28+
}
29+
30+
_, valid := checker.Check(request)
31+
if !valid {
32+
t.Fail()
33+
}
34+
35+
if request.Query != "param1%2Fparam2+%3D+1+%2B+2+%26+3+%2B+4" {
36+
t.Fail()
37+
}
38+
}

url_unescape.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package checker
2+
3+
import (
4+
"net/url"
5+
"reflect"
6+
)
7+
8+
// NormalizerURLUnescape is the name of the normalizer.
9+
const NormalizerURLUnescape = "url-unescape"
10+
11+
// makeURLUnescape makes a normalizer function for the URL unscape normalizer.
12+
func makeURLUnescape(_ string) CheckFunc {
13+
return normalizeURLUnescape
14+
}
15+
16+
// normalizeURLUnescape applies URL unescaping to special characters.
17+
// Uses url.QueryUnescape for the actual unescape operation.
18+
func normalizeURLUnescape(value, _ reflect.Value) Result {
19+
if value.Kind() != reflect.String {
20+
panic("string expected")
21+
}
22+
23+
unescaped, err := url.QueryUnescape(value.String())
24+
if err == nil {
25+
value.SetString(unescaped)
26+
}
27+
28+
return ResultValid
29+
}

url_unescape_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package checker_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/cinar/checker"
7+
)
8+
9+
func TestNormalizeURLUnescapeNonString(t *testing.T) {
10+
defer checker.FailIfNoPanic(t)
11+
12+
type Request struct {
13+
Query int `checkers:"url-unescape"`
14+
}
15+
16+
request := &Request{}
17+
18+
checker.Check(request)
19+
}
20+
21+
func TestNormalizeURLUnescape(t *testing.T) {
22+
type Request struct {
23+
Query string `checkers:"url-unescape"`
24+
}
25+
26+
request := &Request{
27+
Query: "param1%2Fparam2+%3D+1+%2B+2+%26+3+%2B+4",
28+
}
29+
30+
_, valid := checker.Check(request)
31+
if !valid {
32+
t.Fail()
33+
}
34+
35+
if request.Query != "param1/param2 = 1 + 2 & 3 + 4" {
36+
t.Fail()
37+
}
38+
}

0 commit comments

Comments
 (0)