Skip to content

Commit

Permalink
URL escape and unescape normalier. Fixes #110 (#119)
Browse files Browse the repository at this point in the history
# Describe Request

URL escape and unescape normalier. 

Fixes #110

# Change Type

New normalizer.
  • Loading branch information
cinar committed Jun 25, 2023
1 parent 0dc52b4 commit 20edd60
Show file tree
Hide file tree
Showing 8 changed files with 184 additions and 1 deletion.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,15 @@ This package currently provides the following checkers:
This package currently provides the following normalizers. They can be mixed with the checkers when defining the validation steps for user data.

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

# Custom Checkers

Expand Down
2 changes: 2 additions & 0 deletions checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ var makers = map[string]MakeFunc{
NormalizerTrim: makeTrim,
NormalizerTrimLeft: makeTrimLeft,
NormalizerTrimRight: makeTrimRight,
NormalizerURLEscape: makeURLEscape,
NormalizerURLUnescape: makeURLUnescape,
}

// Register registers the given checker name and the maker function.
Expand Down
22 changes: 22 additions & 0 deletions doc/normalizers/url_escape.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# URL Escape Normalizer

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.

```golang
type Request struct {
Query string `checkers:"url-escape"`
}

request := &Request{
Query: "param1/param2 = 1 + 2 & 3 + 4",
}

_, valid := checker.Check(request)
if !valid {
t.Fail()
}

// Outputs:
// param1%2Fparam2+%3D+1+%2B+2+%26+3+%2B+4
fmt.Println(request.Query)
```
26 changes: 26 additions & 0 deletions doc/normalizers/url_unescape.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# URL Unescape Normalizer

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.

```golang
type Request struct {
Query string `checkers:"url-unescape"`
}

request := &Request{
Query: "param1%2Fparam2+%3D+1+%2B+2+%26+3+%2B+4",
}

_, valid := checker.Check(request)
if !valid {
t.Fail()
}

if request.Query != "param1/param2 = 1 + 2 & 3 + 4" {
t.Fail()
}

// Outputs:
// param1/param2 = 1 + 2 & 3 + 4
fmt.Println(comment.Body)
```
26 changes: 26 additions & 0 deletions url_escape.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package checker

import (
"net/url"
"reflect"
)

// NormalizerURLEscape is the name of the normalizer.
const NormalizerURLEscape = "url-escape"

// makeURLEscape makes a normalizer function for the URL escape normalizer.
func makeURLEscape(_ string) CheckFunc {
return normalizeURLEscape
}

// normalizeURLEscape applies URL escaping to special characters.
// Uses net.url.QueryEscape for the actual escape operation.
func normalizeURLEscape(value, _ reflect.Value) Result {
if value.Kind() != reflect.String {
panic("string expected")
}

value.SetString(url.QueryEscape(value.String()))

return ResultValid
}
38 changes: 38 additions & 0 deletions url_escape_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package checker_test

import (
"testing"

"github.com/cinar/checker"
)

func TestNormalizeURLEscapeNonString(t *testing.T) {
defer checker.FailIfNoPanic(t)

type Request struct {
Query int `checkers:"url-escape"`
}

request := &Request{}

checker.Check(request)
}

func TestNormalizeURLEscape(t *testing.T) {
type Request struct {
Query string `checkers:"url-escape"`
}

request := &Request{
Query: "param1/param2 = 1 + 2 & 3 + 4",
}

_, valid := checker.Check(request)
if !valid {
t.Fail()
}

if request.Query != "param1%2Fparam2+%3D+1+%2B+2+%26+3+%2B+4" {
t.Fail()
}
}
29 changes: 29 additions & 0 deletions url_unescape.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package checker

import (
"net/url"
"reflect"
)

// NormalizerURLUnescape is the name of the normalizer.
const NormalizerURLUnescape = "url-unescape"

// makeURLUnescape makes a normalizer function for the URL unscape normalizer.
func makeURLUnescape(_ string) CheckFunc {
return normalizeURLUnescape
}

// normalizeURLUnescape applies URL unescaping to special characters.
// Uses url.QueryUnescape for the actual unescape operation.
func normalizeURLUnescape(value, _ reflect.Value) Result {
if value.Kind() != reflect.String {
panic("string expected")
}

unescaped, err := url.QueryUnescape(value.String())
if err == nil {
value.SetString(unescaped)
}

return ResultValid
}
38 changes: 38 additions & 0 deletions url_unescape_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package checker_test

import (
"testing"

"github.com/cinar/checker"
)

func TestNormalizeURLUnescapeNonString(t *testing.T) {
defer checker.FailIfNoPanic(t)

type Request struct {
Query int `checkers:"url-unescape"`
}

request := &Request{}

checker.Check(request)
}

func TestNormalizeURLUnescape(t *testing.T) {
type Request struct {
Query string `checkers:"url-unescape"`
}

request := &Request{
Query: "param1%2Fparam2+%3D+1+%2B+2+%26+3+%2B+4",
}

_, valid := checker.Check(request)
if !valid {
t.Fail()
}

if request.Query != "param1/param2 = 1 + 2 & 3 + 4" {
t.Fail()
}
}

0 comments on commit 20edd60

Please sign in to comment.