Skip to content
This repository has been archived by the owner on Feb 27, 2023. It is now read-only.

Commit

Permalink
Merge pull request #438 from Starnop/supernode-utils
Browse files Browse the repository at this point in the history
feature: add some utils that supernode will use
  • Loading branch information
lowzj authored Mar 6, 2019
2 parents 9831c25 + 1de7ee2 commit f64fe80
Show file tree
Hide file tree
Showing 12 changed files with 528 additions and 89 deletions.
27 changes: 26 additions & 1 deletion common/util/assert.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package util
import (
"encoding/json"
"reflect"
"strconv"
)

// Max returns the larger of x or y.
Expand All @@ -39,11 +40,16 @@ func Min(x, y int32) int32 {
return y
}

// IsEmptyStr returns whether the string x is empty.
// IsEmptyStr returns whether the string s is empty.
func IsEmptyStr(s string) bool {
return s == ""
}

// IsEmptySlice returns whether the slice values is empty.
func IsEmptySlice(values []string) bool {
return len(values) == 0
}

// IsNil returns whether the value is nil.
func IsNil(value interface{}) (result bool) {
if value == nil {
Expand All @@ -57,6 +63,25 @@ func IsNil(value interface{}) (result bool) {
return
}

// IsTrue returns whether the value is true.
func IsTrue(value bool) bool {
return value == true
}

// IsPositive returns whether the value is a positive number.
func IsPositive(value int64) bool {
return value > 0
}

// IsNumeric returns whether the value is a numeric.
// If the bitSize of value below 0 or above 64 an error is returned.
func IsNumeric(value string) bool {
if _, err := strconv.Atoi(value); err != nil {
return false
}
return true
}

// JSONString returns json string of the v.
func JSONString(v interface{}) string {
if str, e := json.Marshal(v); e == nil {
Expand Down
26 changes: 26 additions & 0 deletions common/util/assert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ func (suite *AssertSuite) TestIsEmptyStr(c *check.C) {
c.Assert(IsEmptyStr("x"), check.Equals, false)
}

func (suite *AssertSuite) TestIsEmptySlice(c *check.C) {
c.Assert(IsEmptySlice(nil), check.Equals, true)
c.Assert(IsEmptySlice([]string{}), check.Equals, true)
c.Assert(IsEmptySlice([]string{""}), check.Equals, false)
c.Assert(IsEmptySlice([]string{"aaa", "bbb"}), check.Equals, false)
}

func (suite *AssertSuite) TestIsNil(c *check.C) {
c.Assert(IsNil(nil), check.Equals, true)
c.Assert(IsNil(suite), check.Equals, false)
Expand All @@ -59,6 +66,25 @@ func (suite *AssertSuite) TestIsNil(c *check.C) {
c.Assert(IsNil(temp), check.Equals, true)
}

func (suite *AssertSuite) TestIsTrue(c *check.C) {
c.Assert(IsTrue(true), check.Equals, true)
c.Assert(IsTrue(false), check.Equals, false)
}

func (suite *AssertSuite) TestIsPositive(c *check.C) {
c.Assert(IsPositive(0), check.Equals, false)
c.Assert(IsPositive(1), check.Equals, true)
c.Assert(IsPositive(-1), check.Equals, false)
}

func (suite *AssertSuite) TestIsNumeric(c *check.C) {
c.Assert(IsNumeric("0"), check.Equals, true)
c.Assert(IsNumeric("1"), check.Equals, true)
c.Assert(IsNumeric("-1"), check.Equals, true)
c.Assert(IsNumeric("1 "), check.Equals, false)
c.Assert(IsNumeric("aaa"), check.Equals, false)
}

func (suite *AssertSuite) TestJsonString(c *check.C) {
type T1 struct {
A int
Expand Down
40 changes: 40 additions & 0 deletions common/util/digest_util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright The Dragonfly Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package util

import (
"crypto/sha1"
"crypto/sha256"
"encoding/hex"
"io"
)

// Sha256 returns the SHA-256 checksum of the data.
func Sha256(value string) string {
h := sha256.New()
h.Write([]byte(value))
return hex.EncodeToString(h.Sum(nil))
}

// Sha1 returns the SHA-1 checksum of the contents.
func Sha1(contents []string) string {
h := sha1.New()
for _, content := range contents {
io.WriteString(h, content)
}
return hex.EncodeToString(h.Sum(nil))
}
6 changes: 6 additions & 0 deletions common/util/file_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ func Link(src string, linkName string) error {
return os.Link(src, linkName)
}

// SymbolicLink creates target as a symbolic link to src.
func SymbolicLink(src string, target string) error {
// TODO Add verifications.
return os.Symlink(src, target)
}

// CopyFile copies the file src to dst.
func CopyFile(src string, dst string) (err error) {
var (
Expand Down
79 changes: 79 additions & 0 deletions common/util/net_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ import (
log "github.com/sirupsen/logrus"
)

const (
separator = "&"
)

var defaultRateLimit = "20M"

// NetLimit parse speed of interface that it has prefix of eth
Expand Down Expand Up @@ -108,3 +112,78 @@ func ExtractHost(hostAndPort string) string {
fields := strings.Split(strings.TrimSpace(hostAndPort), ":")
return fields[0]
}

// FilterURLParam filters request queries in URL.
// Eg:
// If you pass parameters as follows:
// url: http://a.b.com/locate?key1=value1&key2=value2&key3=value3
// filter: key2
// and then you will get the following value as the return:
// http://a.b.com/locate?key1=value1&key3=value3
func FilterURLParam(url string, filters []string) string {
rawUrls := strings.SplitN(url, "?", 2)
if len(filters) <= 0 || len(rawUrls) != 2 || strings.TrimSpace(rawUrls[1]) == "" {
return url
}
filtersMap := slice2Map(filters)

var params []string
for _, param := range strings.Split(rawUrls[1], separator) {
kv := strings.SplitN(param, "=", 2)
if !(len(kv) >= 1 && isExist(filtersMap, kv[0])) {
params = append(params, param)
}
}
if len(params) > 0 {
return rawUrls[0] + "?" + strings.Join(params, separator)
}
return rawUrls[0]
}

// IsValidURL returns whether the string url is a valid HTTP URL.
func IsValidURL(url string) bool {
// shorter than the shortest case 'http://a.b'
if len(url) < 10 {
return false
}
reg := regexp.MustCompile(`(https?|HTTPS?)://([\w_]+:[\w_]+@)?([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?`)
if result := reg.FindString(url); IsEmptyStr(result) {
return false
}
return true
}

// IsValidIP returns whether the string ip is a valid IP Address.
func IsValidIP(ip string) bool {
if strings.TrimSpace(ip) == "" {
return false
}

// str is a regex which matches a digital
// greater than or equal to 0 and less than or equal to 255
str := "(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)"
result, err := regexp.MatchString("^(?:"+str+"\\.){3}"+str+"$", ip)
if err != nil {
return false
}

return result
}

// slice2Map translate a slice to a map with
// the value in slice as the key and true as the value.
func slice2Map(value []string) map[string]bool {
mmap := make(map[string]bool)
for _, v := range value {
mmap[v] = true
}
return mmap
}

// isExist returns whether the map contains the key.
func isExist(mmap map[string]bool, key string) bool {
if _, ok := mmap[key]; ok {
return true
}
return false
}
124 changes: 124 additions & 0 deletions common/util/net_util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package util

import (
"fmt"
"runtime"

"github.com/go-check/check"
Expand All @@ -39,3 +40,126 @@ func (suite *UtilSuite) TestNetLimit(c *check.C) {
c.Assert(speed, check.Equals, "20M")
}
}

func (suite *UtilSuite) TestFilterURLParam(c *check.C) {
var cases = []struct {
url string
filter []string
expected string
}{
{
url: "http://www.a.b.com",
filter: nil,
expected: "http://www.a.b.com",
},
{
url: "http://www.a.b.com?key1=value1",
filter: nil,
expected: "http://www.a.b.com?key1=value1",
},
{
url: "http://www.a.b.com?key1=value1",
filter: []string{"key1"},
expected: "http://www.a.b.com",
},
{
url: "http://www.a.b.com?key1=value1",
filter: []string{"key2"},
expected: "http://www.a.b.com?key1=value1",
},
{
url: "http://www.a.b.com?key1=value1&key2=value2",
filter: []string{"key2"},
expected: "http://www.a.b.com?key1=value1",
},
{
url: "http://www.a.b.com?key1=value1&key2=value2&key3=value3",
filter: []string{"key2"},
expected: "http://www.a.b.com?key1=value1&key3=value3",
},
{
url: "http://www.a.b.com?key1=value1&key2=value2&key3=value3",
filter: []string{"key2", "key3"},
expected: "http://www.a.b.com?key1=value1",
},
{
url: "http://www.a.b.com?key1=value1&key2=value2&key3=value3",
filter: []string{"key2 ", "key3"},
expected: "http://www.a.b.com?key1=value1&key2=value2",
},
{
url: "http://www.a.b.com?key1=value1&key2=value2&key1=value3",
filter: []string{"key1"},
expected: "http://www.a.b.com?key2=value2",
},
}
for _, v := range cases {
result := FilterURLParam(v.url, v.filter)
c.Assert(result, check.Equals, v.expected)
}
}

func (suite *UtilSuite) TestIsValidURL(c *check.C) {
var cases = map[string]bool{
"": false,
"abcdefg": false,
"////a//": false,
"a////a//": false,
"a.com////a//": true,
"a:b@a.com": true,
"a:b@127.0.0.1": true,
"a:b@127.0.0.1?a=b": true,
"a:b@127.0.0.1?a=b&c=d": true,
"127.0.0.1": true,
"127.0.0.1?a=b": true,
"127.0.0.1:": true,
"127.0.0.1:8080": true,
"127.0.0.1:8080/我": true,
"127.0.0.1:8080/我?x=1": true,
"a.b": true,
"www.taobao.com": true,
"http:/www.a.b.com": false,
"https://github.com/dragonflyoss/Dragonfly/issues?" +
"q=is%3Aissue+is%3Aclosed": true,
}

for k, v := range cases {
for _, scheme := range []string{"http", "https", "HTTP", "HTTPS"} {
url := fmt.Sprintf("%s://%s", scheme, k)
result := IsValidURL(url)
c.Assert(result, check.Equals, v)
}
}
}

func (suite *UtilSuite) TestIsValidIP(c *check.C) {
var cases = []struct {
ip string
expected bool
}{
{
ip: "192.168.1.1",
expected: true,
},
{
ip: "0.0.0.0",
expected: true,
},
{
ip: "255.255.255.255",
expected: true,
},
{
ip: "256.255.255.255",
expected: false,
},
{
ip: "aaa.255.255.255",
expected: false,
},
}
for _, v := range cases {
result := IsValidIP(v.ip)
c.Assert(result, check.Equals, v.expected)
}
}
Loading

0 comments on commit f64fe80

Please sign in to comment.