From 089b481fc0467687f6d1ded37a7d77377aba34df Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Tue, 5 Jul 2016 23:19:24 +0100 Subject: [PATCH] Initial work on shortner package --- shortner/normalize_url.go | 65 +++++++++++++++++++ shortner/normalize_url_test.go | 115 +++++++++++++++++++++++++++++++++ shortner/shortner.go | 86 ++++++++++++++++++++++++ shortner/shortner_test.go | 103 +++++++++++++++++++++++++++++ 4 files changed, 369 insertions(+) create mode 100644 shortner/normalize_url.go create mode 100644 shortner/normalize_url_test.go create mode 100644 shortner/shortner.go create mode 100644 shortner/shortner_test.go diff --git a/shortner/normalize_url.go b/shortner/normalize_url.go new file mode 100644 index 0000000..6e961fa --- /dev/null +++ b/shortner/normalize_url.go @@ -0,0 +1,65 @@ +package shortner + +import ( + "errors" + "net/url" +) + +var errURLFileSchema = errors.New("Schema 'file://' not allowed") +var errURLInvalid = errors.New("Invalid URL") + +var slashByte = byte(47) +var maxLengthURL = 2048 + +// NormalizeURL validates and normalizes given rawURL string. +func NormalizeURL(rawURL []byte) ([]byte, error) { + url, err := normalizeURLPassOne(rawURL) + if err != nil { + return []byte{}, err + } + + url, err = normalizeURLPassTwo(url) + if err != nil { + return []byte{}, err + } + + return url, nil +} + +func normalizeURLPassOne(rawURL []byte) ([]byte, error) { + if len(rawURL) > maxLengthURL { + return []byte{}, errURLInvalid + } + + u, err := url.Parse(string(rawURL)) + if err != nil { + return []byte{}, errURLInvalid + } + + if u.Scheme == "" { + u.Scheme = "http" + } + + if u.Scheme == "file" { + return []byte{}, errURLFileSchema + } + + if u.Host == "" && (u.Path == "" || u.Path[0] == slashByte) { + return []byte{}, errURLInvalid + } + + return []byte(u.String()), nil +} + +func normalizeURLPassTwo(rawURL []byte) ([]byte, error) { + u, err := url.Parse(string(rawURL)) + if err != nil { + return []byte{}, errURLInvalid + } + + if u.Host != "" && u.Path == "" { + u.Path = "/" + } + + return []byte(u.String()), nil +} diff --git a/shortner/normalize_url_test.go b/shortner/normalize_url_test.go new file mode 100644 index 0000000..4b6c9f2 --- /dev/null +++ b/shortner/normalize_url_test.go @@ -0,0 +1,115 @@ +package shortner + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/assert" +) + +var examples = []struct { + valid bool + url string + normalized string + error string +}{ + {valid: true, url: "google.com", normalized: "http://google.com/"}, + {valid: true, url: "google.com/", normalized: "http://google.com/"}, + {valid: true, url: "http://google.com", normalized: "http://google.com/"}, + {valid: true, url: "http://google.com/"}, + {valid: true, url: "https://google.com", normalized: "https://google.com/"}, + {valid: true, url: "https://google.com/"}, + {valid: true, url: "google.yeah", normalized: "http://google.yeah/"}, + {valid: true, url: "http://news.google.com/"}, + + {valid: true, url: "http://google.com/?h=en&foo=bar"}, + {valid: true, + url: "http://google.com?h=en&foo=bar", + normalized: "http://google.com/?h=en&foo=bar"}, + {valid: true, + url: "google.com/?h=en&foo=bar", + normalized: "http://google.com/?h=en&foo=bar"}, + {valid: true, + url: "google.com?h=en&foo=bar", + normalized: "http://google.com/?h=en&foo=bar"}, + + {valid: true, url: "http://google.com/#nope"}, + {valid: true, + url: "http://google.com#nope", + normalized: "http://google.com/#nope"}, + {valid: true, + url: "google.com/#nope", + normalized: "http://google.com/#nope"}, + {valid: true, + url: "google.com#nope", + normalized: "http://google.com/#nope"}, + + {valid: true, url: "http://google.com/?h=en&foo=bar#nope"}, + {valid: true, + url: "http://google.com?h=en&foo=bar#nope", + normalized: "http://google.com/?h=en&foo=bar#nope"}, + {valid: true, + url: "google.com/?h=en&foo=bar#nope", + normalized: "http://google.com/?h=en&foo=bar#nope"}, + {valid: true, + url: "google.com?h=en&foo=bar#nope", + normalized: "http://google.com/?h=en&foo=bar#nope"}, + + {valid: true, url: "(248034)", normalized: "http://(248034)/"}, + { + valid: false, + url: "*$)]+_