mirror of https://github.com/grafana/loki
logcli: introduced QueryStringBuilder utility to clean up query string encoding (#1115)
parent
9a6b5dbf7c
commit
0e718c2275
@ -0,0 +1,55 @@ |
||||
package util |
||||
|
||||
import ( |
||||
"net/url" |
||||
"strconv" |
||||
) |
||||
|
||||
type QueryStringBuilder struct { |
||||
values url.Values |
||||
} |
||||
|
||||
func NewQueryStringBuilder() *QueryStringBuilder { |
||||
return &QueryStringBuilder{ |
||||
values: url.Values{}, |
||||
} |
||||
} |
||||
|
||||
func (b *QueryStringBuilder) SetString(name, value string) { |
||||
b.values.Set(name, value) |
||||
} |
||||
|
||||
func (b *QueryStringBuilder) SetInt(name string, value int64) { |
||||
b.SetString(name, strconv.FormatInt(value, 10)) |
||||
} |
||||
|
||||
func (b *QueryStringBuilder) SetInt32(name string, value int) { |
||||
b.SetString(name, strconv.Itoa(value)) |
||||
} |
||||
|
||||
func (b *QueryStringBuilder) SetFloat(name string, value float64) { |
||||
b.SetString(name, strconv.FormatFloat(value, 'f', -1, 64)) |
||||
} |
||||
|
||||
func (b *QueryStringBuilder) SetFloat32(name string, value float32) { |
||||
b.SetString(name, strconv.FormatFloat(float64(value), 'f', -1, 32)) |
||||
} |
||||
|
||||
// Encode returns the URL-encoded query string based on key-value
|
||||
// parameters added to the builder calling Set functions.
|
||||
func (b *QueryStringBuilder) Encode() string { |
||||
return b.values.Encode() |
||||
} |
||||
|
||||
// Encode returns the URL-encoded query string, prefixing it with the
|
||||
// input URL path.
|
||||
func (b *QueryStringBuilder) EncodeWithPath(path string) string { |
||||
queryString := b.Encode() |
||||
if path == "" { |
||||
return queryString |
||||
} else if queryString == "" { |
||||
return path |
||||
} |
||||
|
||||
return path + "?" + queryString |
||||
} |
@ -0,0 +1,65 @@ |
||||
package util |
||||
|
||||
import ( |
||||
"fmt" |
||||
"testing" |
||||
|
||||
"github.com/stretchr/testify/assert" |
||||
"github.com/stretchr/testify/require" |
||||
) |
||||
|
||||
func TestQueryStringBuilder(t *testing.T) { |
||||
t.Parallel() |
||||
|
||||
tests := map[string]struct { |
||||
input map[string]interface{} |
||||
expectedEncoded string |
||||
expectedPath string |
||||
}{ |
||||
"should return an empty query string on no params": { |
||||
input: map[string]interface{}{}, |
||||
expectedEncoded: "", |
||||
expectedPath: "/test", |
||||
}, |
||||
"should return the URL encoded query string parameters": { |
||||
input: map[string]interface{}{ |
||||
"float32": float32(123.456), |
||||
"float64": float64(123.456), |
||||
"float64int": float64(12345.0), |
||||
"int32": 32, |
||||
"int64": int64(64), |
||||
"string": "foo", |
||||
}, |
||||
expectedEncoded: "float32=123.456&float64=123.456&float64int=12345&int32=32&int64=64&string=foo", |
||||
expectedPath: "/test?float32=123.456&float64=123.456&float64int=12345&int32=32&int64=64&string=foo", |
||||
}, |
||||
} |
||||
|
||||
for testName, testData := range tests { |
||||
testData := testData |
||||
|
||||
t.Run(testName, func(t *testing.T) { |
||||
params := NewQueryStringBuilder() |
||||
|
||||
for name, value := range testData.input { |
||||
switch value := value.(type) { |
||||
case string: |
||||
params.SetString(name, value) |
||||
case float32: |
||||
params.SetFloat32(name, value) |
||||
case float64: |
||||
params.SetFloat(name, value) |
||||
case int: |
||||
params.SetInt32(name, value) |
||||
case int64: |
||||
params.SetInt(name, value) |
||||
default: |
||||
require.Fail(t, fmt.Sprintf("Unknown data type for test fixture with name '%s'", name)) |
||||
} |
||||
} |
||||
|
||||
assert.Equal(t, testData.expectedEncoded, params.Encode()) |
||||
assert.Equal(t, testData.expectedPath, params.EncodeWithPath("/test")) |
||||
}) |
||||
} |
||||
} |
Loading…
Reference in new issue