diff --git a/util/ctx/ctx.go b/util/ctx/ctx.go deleted file mode 100644 index 853be441ca..0000000000 --- a/util/ctx/ctx.go +++ /dev/null @@ -1,18 +0,0 @@ -package ctx - -import ( - "context" - "net/http" - "strings" - - "go-micro.dev/v5/metadata" -) - -func FromRequest(r *http.Request) context.Context { - ctx := context.Background() - md := make(metadata.Metadata) - for k, v := range r.Header { - md[k] = strings.Join(v, ",") - } - return metadata.NewContext(ctx, md) -} diff --git a/util/ctx/ctx_test.go b/util/ctx/ctx_test.go deleted file mode 100644 index e183739b95..0000000000 --- a/util/ctx/ctx_test.go +++ /dev/null @@ -1,41 +0,0 @@ -package ctx - -import ( - "net/http" - "testing" - - "go-micro.dev/v5/metadata" -) - -func TestRequestToContext(t *testing.T) { - testData := []struct { - request *http.Request - expect metadata.Metadata - }{ - { - &http.Request{ - Header: http.Header{ - "Foo1": []string{"bar"}, - "Foo2": []string{"bar", "baz"}, - }, - }, - metadata.Metadata{ - "Foo1": "bar", - "Foo2": "bar,baz", - }, - }, - } - - for _, d := range testData { - ctx := FromRequest(d.request) - md, ok := metadata.FromContext(ctx) - if !ok { - t.Fatalf("Expected metadata for request %+v", d.request) - } - for k, v := range d.expect { - if val := md[k]; val != v { - t.Fatalf("Expected %s for key %s for expected md %+v, got md %+v", v, k, d.expect, md) - } - } - } -} diff --git a/util/io/io.go b/util/io/io.go deleted file mode 100644 index c605d27ce1..0000000000 --- a/util/io/io.go +++ /dev/null @@ -1,40 +0,0 @@ -// Package io is for io management -package io - -import ( - "io" - - "go-micro.dev/v5/transport" -) - -type rwc struct { - socket transport.Socket -} - -func (r *rwc) Read(p []byte) (n int, err error) { - m := new(transport.Message) - if err := r.socket.Recv(m); err != nil { - return 0, err - } - copy(p, m.Body) - return len(m.Body), nil -} - -func (r *rwc) Write(p []byte) (n int, err error) { - err = r.socket.Send(&transport.Message{ - Body: p, - }) - if err != nil { - return 0, err - } - return len(p), nil -} - -func (r *rwc) Close() error { - return r.socket.Close() -} - -// NewRWC returns a new ReadWriteCloser. -func NewRWC(sock transport.Socket) io.ReadWriteCloser { - return &rwc{sock} -} diff --git a/util/pki/certoptions.go b/util/pki/certoptions.go deleted file mode 100644 index abd11d94fb..0000000000 --- a/util/pki/certoptions.go +++ /dev/null @@ -1,86 +0,0 @@ -package pki - -import ( - "crypto/ed25519" - "crypto/x509" - "crypto/x509/pkix" - "math/big" - "net" - "time" -) - -// CertOptions are passed to cert options. -type CertOptions struct { - NotBefore time.Time - NotAfter time.Time - - SerialNumber *big.Int - - Parent *x509.Certificate - Subject pkix.Name - DNSNames []string - IPAddresses []net.IP - Pub ed25519.PublicKey - Priv ed25519.PrivateKey - IsCA bool -} - -// CertOption sets CertOptions. -type CertOption func(c *CertOptions) - -// Subject sets the Subject field. -func Subject(subject pkix.Name) CertOption { - return func(c *CertOptions) { - c.Subject = subject - } -} - -// IsCA states the cert is a CA. -func IsCA() CertOption { - return func(c *CertOptions) { - c.IsCA = true - } -} - -// DNSNames is a list of hosts to sign in to the certificate. -func DNSNames(names ...string) CertOption { - return func(c *CertOptions) { - c.DNSNames = names - } -} - -// IPAddresses is a list of IPs to sign in to the certificate. -func IPAddresses(ips ...net.IP) CertOption { - return func(c *CertOptions) { - c.IPAddresses = ips - } -} - -// KeyPair is the key pair to sign the certificate with. -func KeyPair(pub ed25519.PublicKey, priv ed25519.PrivateKey) CertOption { - return func(c *CertOptions) { - c.Pub = pub - c.Priv = priv - } -} - -// SerialNumber is the Certificate Serial number. -func SerialNumber(serial *big.Int) CertOption { - return func(c *CertOptions) { - c.SerialNumber = serial - } -} - -// NotBefore is the time the certificate is not valid before. -func NotBefore(time time.Time) CertOption { - return func(c *CertOptions) { - c.NotBefore = time - } -} - -// NotAfter is the time the certificate is not valid after. -func NotAfter(time time.Time) CertOption { - return func(c *CertOptions) { - c.NotAfter = time - } -} diff --git a/util/pki/pki.go b/util/pki/pki.go deleted file mode 100644 index 23a0039973..0000000000 --- a/util/pki/pki.go +++ /dev/null @@ -1,164 +0,0 @@ -// Package pki provides PKI all the PKI functions necessary to run micro over an untrusted network -// including a CA -package pki - -import ( - "bytes" - "crypto/ed25519" - "crypto/rand" - "crypto/x509" - "encoding/pem" - - "github.com/pkg/errors" -) - -// GenerateKey returns an ed25519 key. -func GenerateKey() (ed25519.PublicKey, ed25519.PrivateKey, error) { - return ed25519.GenerateKey(rand.Reader) -} - -// CA generates a self signed CA and returns cert, key in PEM format. -func CA(opts ...CertOption) ([]byte, []byte, error) { - opts = append(opts, IsCA()) - options := CertOptions{} - for _, o := range opts { - o(&options) - } - template := &x509.Certificate{ - SignatureAlgorithm: x509.PureEd25519, - Subject: options.Subject, - DNSNames: options.DNSNames, - IPAddresses: options.IPAddresses, - KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - NotBefore: options.NotBefore, - NotAfter: options.NotAfter, - SerialNumber: options.SerialNumber, - BasicConstraintsValid: true, - } - if options.IsCA { - template.IsCA = true - template.KeyUsage |= x509.KeyUsageCertSign - } - x509Cert, err := x509.CreateCertificate(rand.Reader, template, template, options.Pub, options.Priv) - if err != nil { - return nil, nil, err - } - cert, key := &bytes.Buffer{}, &bytes.Buffer{} - if err := pem.Encode(cert, &pem.Block{Type: "CERTIFICATE", Bytes: x509Cert}); err != nil { - return nil, nil, err - } - x509Key, err := x509.MarshalPKCS8PrivateKey(options.Priv) - if err != nil { - return nil, nil, err - } - if err := pem.Encode(key, &pem.Block{Type: "PRIVATE KEY", Bytes: x509Key}); err != nil { - return nil, nil, err - } - - return cert.Bytes(), key.Bytes(), nil -} - -// CSR generates a certificate request in PEM format. -func CSR(opts ...CertOption) ([]byte, error) { - options := CertOptions{} - for _, o := range opts { - o(&options) - } - csrTemplate := &x509.CertificateRequest{ - Subject: options.Subject, - SignatureAlgorithm: x509.PureEd25519, - DNSNames: options.DNSNames, - IPAddresses: options.IPAddresses, - } - out := &bytes.Buffer{} - csr, err := x509.CreateCertificateRequest(rand.Reader, csrTemplate, options.Priv) - if err != nil { - return nil, err - } - if err := pem.Encode(out, &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csr}); err != nil { - return nil, err - } - - return out.Bytes(), nil -} - -// Sign decodes a CSR and signs it with the CA. -func Sign(CACrt, CAKey, CSR []byte, opts ...CertOption) ([]byte, error) { - options := CertOptions{} - for _, o := range opts { - o(&options) - } - asn1CACrt, err := decodePEM(CACrt) - if err != nil { - return nil, errors.Wrap(err, "failed to decode CA Crt PEM") - } - if len(asn1CACrt) != 1 { - return nil, errors.Errorf("expected 1 CA Crt, got %d", len(asn1CACrt)) - } - caCrt, err := x509.ParseCertificate(asn1CACrt[0].Bytes) - if err != nil { - return nil, errors.Wrap(err, "ca is not a valid certificate") - } - asn1CAKey, err := decodePEM(CAKey) - if err != nil { - return nil, errors.Wrap(err, "failed to decode CA Key PEM") - } - if len(asn1CAKey) != 1 { - return nil, errors.Errorf("expected 1 CA Key, got %d", len(asn1CACrt)) - } - caKey, err := x509.ParsePKCS8PrivateKey(asn1CAKey[0].Bytes) - if err != nil { - return nil, errors.Wrap(err, "ca key is not a valid private key") - } - asn1CSR, err := decodePEM(CSR) - if err != nil { - return nil, errors.Wrap(err, "failed to decode CSR PEM") - } - if len(asn1CSR) != 1 { - return nil, errors.Errorf("expected 1 CSR, got %d", len(asn1CSR)) - } - csr, err := x509.ParseCertificateRequest(asn1CSR[0].Bytes) - if err != nil { - return nil, errors.Wrap(err, "csr is invalid") - } - template := &x509.Certificate{ - SignatureAlgorithm: x509.PureEd25519, - Subject: csr.Subject, - DNSNames: csr.DNSNames, - IPAddresses: csr.IPAddresses, - KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - NotBefore: options.NotBefore, - NotAfter: options.NotAfter, - SerialNumber: options.SerialNumber, - BasicConstraintsValid: true, - } - - x509Cert, err := x509.CreateCertificate(rand.Reader, template, caCrt, caCrt.PublicKey, caKey) - if err != nil { - return nil, errors.Wrap(err, "Couldn't sign certificate") - } - out := &bytes.Buffer{} - if err := pem.Encode(out, &pem.Block{Type: "CERTIFICATE", Bytes: x509Cert}); err != nil { - return nil, errors.Wrap(err, "couldn't encode cert") - } - return out.Bytes(), nil -} - -func decodePEM(PEM []byte) ([]*pem.Block, error) { - var blocks []*pem.Block - var asn1 *pem.Block - var rest []byte - for { - asn1, rest = pem.Decode(PEM) - if asn1 == nil { - return nil, errors.New("PEM is not valid") - } - blocks = append(blocks, asn1) - if len(rest) == 0 { - break - } - } - return blocks, nil -} diff --git a/util/pki/pki_test.go b/util/pki/pki_test.go deleted file mode 100644 index 67e81d132d..0000000000 --- a/util/pki/pki_test.go +++ /dev/null @@ -1,90 +0,0 @@ -package pki - -import ( - "crypto/ed25519" - "crypto/rand" - "crypto/x509" - "crypto/x509/pkix" - "encoding/pem" - "math/big" - "net" - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -func TestPrivateKey(t *testing.T) { - _, _, err := GenerateKey() - assert.NoError(t, err) -} - -func TestCA(t *testing.T) { - pub, priv, err := GenerateKey() - assert.NoError(t, err) - - serialNumberMax := new(big.Int).Lsh(big.NewInt(1), 128) - serialNumber, err := rand.Int(rand.Reader, serialNumberMax) - assert.NoError(t, err, "Couldn't generate serial") - - cert, key, err := CA( - KeyPair(pub, priv), - Subject(pkix.Name{ - Organization: []string{"test"}, - }), - DNSNames("localhost"), - IPAddresses(net.ParseIP("127.0.0.1")), - SerialNumber(serialNumber), - NotBefore(time.Now().Add(time.Minute*-1)), - NotAfter(time.Now().Add(time.Minute)), - ) - assert.NoError(t, err, "Couldn't sign CA") - asn1Key, _ := pem.Decode(key) - assert.NotNil(t, asn1Key, "Couldn't decode key") - assert.Equal(t, "PRIVATE KEY", asn1Key.Type) - decodedKey, err := x509.ParsePKCS8PrivateKey(asn1Key.Bytes) - assert.NoError(t, err, "Couldn't decode ASN1 Key") - assert.Equal(t, priv, decodedKey.(ed25519.PrivateKey)) - - pool := x509.NewCertPool() - assert.True(t, pool.AppendCertsFromPEM(cert), "Coudn't parse cert") - - asn1Cert, _ := pem.Decode(cert) - assert.NotNil(t, asn1Cert, "Couldn't parse pem cert") - x509cert, err := x509.ParseCertificate(asn1Cert.Bytes) - assert.NoError(t, err, "Couldn't parse asn1 cert") - chains, err := x509cert.Verify(x509.VerifyOptions{ - Roots: pool, - }) - assert.NoError(t, err, "Cert didn't verify") - assert.Len(t, chains, 1, "CA should have 1 cert in chain") -} - -func TestCSR(t *testing.T) { - pub, priv, err := GenerateKey() - assert.NoError(t, err) - csr, err := CSR( - Subject( - pkix.Name{ - CommonName: "testnode", - Organization: []string{"microtest"}, - OrganizationalUnit: []string{"super-testers"}, - }, - ), - DNSNames("localhost"), - IPAddresses(net.ParseIP("127.0.0.1")), - KeyPair(pub, priv), - ) - assert.NoError(t, err, "CSR couldn't be encoded") - - asn1csr, _ := pem.Decode(csr) - assert.NotNil(t, asn1csr) - decodedcsr, err := x509.ParseCertificateRequest(asn1csr.Bytes) - assert.NoError(t, err) - expected := pkix.Name{ - CommonName: "testnode", - Organization: []string{"microtest"}, - OrganizationalUnit: []string{"super-testers"}, - } - assert.Equal(t, decodedcsr.Subject.String(), expected.String()) -} diff --git a/util/qson/LICENSE b/util/qson/LICENSE deleted file mode 100644 index 3e4ba4f778..0000000000 --- a/util/qson/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020 Jon Calhoun - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/util/qson/README.md b/util/qson/README.md deleted file mode 100644 index ad76ced510..0000000000 --- a/util/qson/README.md +++ /dev/null @@ -1,55 +0,0 @@ -# qson - -This is copy from https://github.com/joncalhoun/qson -As author says he is not acrivelly maintains the repo and not plan to do that. - -## Usage - -You can either turn a URL query param into a JSON byte array, or unmarshal that directly into a Go object. - -Transforming the URL query param into a JSON byte array: - -```go -import "github.com/joncalhoun/qson" - -func main() { - b, err := qson.ToJSON("bar%5Bone%5D%5Btwo%5D=2&bar[one][red]=112") - if err != nil { - panic(err) - } - fmt.Println(string(b)) - // Should output: {"bar":{"one":{"red":112,"two":2}}} -} -``` - -Or unmarshalling directly into a Go object using JSON struct tags: - -```go -import "github.com/joncalhoun/qson" - -type unmarshalT struct { - A string `json:"a"` - B unmarshalB `json:"b"` -} -type unmarshalB struct { - C int `json:"c"` -} - -func main() { - var out unmarshalT - query := "a=xyz&b[c]=456" - err := Unmarshal(&out, query) - if err != nil { - t.Error(err) - } - // out should equal - // unmarshalT{ - // A: "xyz", - // B: unmarshalB{ - // C: 456, - // }, - // } -} -``` - -To get a query string like in the two previous examples you can use the `RawQuery` field on the [net/url.URL](https://golang.org/pkg/net/url/#URL) type. diff --git a/util/qson/merge.go b/util/qson/merge.go deleted file mode 100644 index 7677b489a9..0000000000 --- a/util/qson/merge.go +++ /dev/null @@ -1,35 +0,0 @@ -package qson - -// merge merges a with b if they are either both slices -// or map[string]interface{} types. Otherwise it returns b. -func merge(a interface{}, b interface{}) interface{} { - switch aT := a.(type) { - case map[string]interface{}: - return mergeMap(aT, b.(map[string]interface{})) - case []interface{}: - return mergeSlice(aT, b.([]interface{})) - default: - return b - } -} - -// mergeMap merges a with b, attempting to merge any nested -// values in nested maps but eventually overwriting anything -// in a that can't be merged with whatever is in b. -func mergeMap(a map[string]interface{}, b map[string]interface{}) map[string]interface{} { - for bK, bV := range b { - if _, ok := a[bK]; ok { - a[bK] = merge(a[bK], bV) - } else { - a[bK] = bV - } - } - - return a -} - -// mergeSlice merges a with b and returns the result. -func mergeSlice(a []interface{}, b []interface{}) []interface{} { - a = append(a, b...) - return a -} diff --git a/util/qson/merge_test.go b/util/qson/merge_test.go deleted file mode 100644 index 9a144db8f9..0000000000 --- a/util/qson/merge_test.go +++ /dev/null @@ -1,37 +0,0 @@ -package qson - -import "testing" - -func TestMergeSlice(t *testing.T) { - a := []interface{}{"a"} - b := []interface{}{"b"} - actual := mergeSlice(a, b) - if len(actual) != 2 { - t.Errorf("Expected size to be 2.") - } - if actual[0] != "a" { - t.Errorf("Expected index 0 to have value a. Actual: %s", actual[0]) - } - if actual[1] != "b" { - t.Errorf("Expected index 1 to have value b. Actual: %s", actual[1]) - } -} - -func TestMergeMap(t *testing.T) { - a := map[string]interface{}{ - "a": "b", - } - b := map[string]interface{}{ - "b": "c", - } - actual := mergeMap(a, b) - if len(actual) != 2 { - t.Errorf("Expected size to be 2.") - } - if actual["a"] != "b" { - t.Errorf("Expected key \"a\" to have value b. Actual: %s", actual["a"]) - } - if actual["b"] != "c" { - t.Errorf("Expected key \"b\" to have value c. Actual: %s", actual["b"]) - } -} diff --git a/util/qson/qson.go b/util/qson/qson.go deleted file mode 100644 index 29ce589dd2..0000000000 --- a/util/qson/qson.go +++ /dev/null @@ -1,170 +0,0 @@ -// Package qson implmenets decoding of URL query params -// into JSON and Go values (using JSON struct tags). -// -// See https://golang.org/pkg/encoding/json/ for more -// details on JSON struct tags. -package qson - -import ( - "encoding/json" - "errors" - "net/url" - "regexp" - "strings" -) - -var ( - // ErrInvalidParam is returned when invalid data is provided to the ToJSON or Unmarshal function. - // Specifically, this will be returned when there is no equals sign present in the URL query parameter. - ErrInvalidParam = errors.New("qson: invalid url query param provided") - - bracketSplitter *regexp.Regexp -) - -func init() { - bracketSplitter = regexp.MustCompile(`\[|\]`) -} - -// Unmarshal will take a dest along with URL -// query params and attempt to first turn the query params -// into JSON and then unmarshal those into the dest variable -// -// BUG(joncalhoun): If a URL query param value is something -// like 123 but is expected to be parsed into a string this -// will currently result in an error because the JSON -// transformation will assume this is intended to be an int. -// This should only affect the Unmarshal function and -// could likely be fixed, but someone will need to submit a -// PR if they want that fixed. -func Unmarshal(dst interface{}, query string) error { - b, err := ToJSON(query) - if err != nil { - return err - } - - return json.Unmarshal(b, dst) -} - -// ToJSON will turn a query string like: -// -// cat=1&bar%5Bone%5D%5Btwo%5D=2&bar[one][red]=112 -// -// Into a JSON object with all the data merged as nicely as -// possible. Eg the example above would output: -// -// {"bar":{"one":{"two":2,"red":112}}} -func ToJSON(query string) ([]byte, error) { - var ( - builder interface{} = make(map[string]interface{}) - ) - - params := strings.Split(query, "&") - - for _, part := range params { - tempMap, err := queryToMap(part) - if err != nil { - return nil, err - } - - builder = merge(builder, tempMap) - } - - return json.Marshal(builder) -} - -// queryToMap turns something like a[b][c]=4 into -// -// map[string]interface{}{ -// "a": map[string]interface{}{ -// "b": map[string]interface{}{ -// "c": 4, -// }, -// }, -// } -func queryToMap(param string) (map[string]interface{}, error) { - rawKey, rawValue, err := splitKeyAndValue(param) - if err != nil { - return nil, err - } - - rawValue, err = url.QueryUnescape(rawValue) - if err != nil { - return nil, err - } - - rawKey, err = url.QueryUnescape(rawKey) - if err != nil { - return nil, err - } - - pieces := bracketSplitter.Split(rawKey, -1) - key := pieces[0] - - // If len==1 then rawKey has no [] chars and we can just - // decode this as key=value into {key: value} - if len(pieces) == 1 { - var value interface{} - // First we try parsing it as an int, bool, null, etc - err = json.Unmarshal([]byte(rawValue), &value) - if err != nil { - // If we got an error we try wrapping the value in - // quotes and processing it as a string - err = json.Unmarshal([]byte("\""+rawValue+"\""), &value) - if err != nil { - // If we can't decode as a string we return the err - return nil, err - } - } - - return map[string]interface{}{ - key: value, - }, nil - } - - // If len > 1 then we have something like a[b][c]=2 - // so we need to turn this into {"a": {"b": {"c": 2}}} - // To do this we break our key into two pieces: - // a and b[c] - // and then we set {"a": queryToMap("b[c]", value)} - ret := make(map[string]interface{}, 0) - ret[key], err = queryToMap(buildNewKey(rawKey) + "=" + rawValue) - - if err != nil { - return nil, err - } - - // When URL params have a set of empty brackets (eg a[]=1) - // it is assumed to be an array. This will get us the - // correct value for the array item and return it as an - // []interface{} so that it can be merged properly. - if pieces[1] == "" { - temp := ret[key].(map[string]interface{}) - ret[key] = []interface{}{temp[""]} - } - - return ret, nil -} - -// buildNewKey will take something like: -// origKey = "bar[one][two]" -// pieces = [bar one two ] -// and return "one[two]". -func buildNewKey(origKey string) string { - pieces := bracketSplitter.Split(origKey, -1) - ret := origKey[len(pieces[0])+1:] - ret = ret[:len(pieces[1])] + ret[len(pieces[1])+1:] - - return ret -} - -// splitKeyAndValue splits a URL param at the last equal -// sign and returns the two strings. If no equal sign is -// found, the ErrInvalidParam error is returned. -func splitKeyAndValue(param string) (string, string, error) { - li := strings.LastIndex(param, "=") - if li == -1 { - return "", "", ErrInvalidParam - } - - return param[:li], param[li+1:], nil -} diff --git a/util/qson/qson_test.go b/util/qson/qson_test.go deleted file mode 100644 index 0e791daa5c..0000000000 --- a/util/qson/qson_test.go +++ /dev/null @@ -1,170 +0,0 @@ -package qson - -import ( - "fmt" - "testing" -) - -func ExampleUnmarshal() { - type Ex struct { - A string `json:"a"` - B struct { - C int `json:"c"` - } `json:"b"` - } - var ex Ex - if err := Unmarshal(&ex, "a=xyz&b[c]=456"); err != nil { - panic(err) - } - fmt.Printf("%+v\n", ex) - // Output: {A:xyz B:{C:456}} -} - -type unmarshalT struct { - A string `json:"a"` - B unmarshalB `json:"b"` -} -type unmarshalB struct { - C int `json:"c"` - D string `json:"D"` -} - -func TestUnmarshal(t *testing.T) { - query := "a=xyz&b[c]=456" - expected := unmarshalT{ - A: "xyz", - B: unmarshalB{ - C: 456, - }, - } - var actual unmarshalT - err := Unmarshal(&actual, query) - if err != nil { - t.Error(err) - } - if expected != actual { - t.Errorf("Expected: %+v Actual: %+v", expected, actual) - } -} - -func ExampleToJSON() { - b, err := ToJSON("a=xyz&b[c]=456") - if err != nil { - panic(err) - } - fmt.Print(string(b)) - // Output: {"a":"xyz","b":{"c":456}} -} - -func TestToJSONNested(t *testing.T) { - query := "bar%5Bone%5D%5Btwo%5D=2&bar[one][red]=112" - expected := `{"bar":{"one":{"red":112,"two":2}}}` - actual, err := ToJSON(query) - if err != nil { - t.Error(err) - } - actualStr := string(actual) - if actualStr != expected { - t.Errorf("Expected: %s Actual: %s", expected, actualStr) - } -} - -func TestToJSONPlain(t *testing.T) { - query := "cat=1&dog=2" - expected := `{"cat":1,"dog":2}` - actual, err := ToJSON(query) - if err != nil { - t.Error(err) - } - actualStr := string(actual) - if actualStr != expected { - t.Errorf("Expected: %s Actual: %s", expected, actualStr) - } -} - -func TestToJSONSlice(t *testing.T) { - query := "cat[]=1&cat[]=34" - expected := `{"cat":[1,34]}` - actual, err := ToJSON(query) - if err != nil { - t.Error(err) - } - actualStr := string(actual) - if actualStr != expected { - t.Errorf("Expected: %s Actual: %s", expected, actualStr) - } -} - -func TestToJSONBig(t *testing.T) { - query := "distinct_id=763_1495187301909_3495×tamp=1495187523&event=product_add_cart¶ms%5BproductRefId%5D=8284563078¶ms%5Bapps%5D%5B%5D=precommend¶ms%5Bapps%5D%5B%5D=bsales¶ms%5Bsource%5D=item¶ms%5Boptions%5D%5Bsegment%5D=cart_recommendation¶ms%5Boptions%5D%5Btype%5D=up_sell¶ms%5BtimeExpire%5D=1495187599642¶ms%5Brecommend_system_product_source%5D=item¶ms%5Bproduct_id%5D=8284563078¶ms%5Bvariant_id%5D=27661944134¶ms%5Bsku%5D=00483332%20(black)¶ms%5Bsources%5D%5B%5D=product_recommendation¶ms%5Bcart_token%5D=dc2c336a009edf2762128e65806dfb1d¶ms%5Bquantity%5D=1¶ms%5Bnew_popup_upsell_mobile%5D=false¶ms%5BclientDevice%5D=desktop¶ms%5BclientIsMobile%5D=false¶ms%5BclientIsSmallScreen%5D=false¶ms%5Bnew_popup_crossell_mobile%5D=false&api_key=14c5b7dacea9157029265b174491d340" - expected := `{"api_key":"14c5b7dacea9157029265b174491d340","distinct_id":"763_1495187301909_3495","event":"product_add_cart","params":{"apps":["precommend","bsales"],"cart_token":"dc2c336a009edf2762128e65806dfb1d","clientDevice":"desktop","clientIsMobile":false,"clientIsSmallScreen":false,"new_popup_crossell_mobile":false,"new_popup_upsell_mobile":false,"options":{"segment":"cart_recommendation","type":"up_sell"},"productRefId":8284563078,"product_id":8284563078,"quantity":1,"recommend_system_product_source":"item","sku":"00483332 (black)","source":"item","sources":["product_recommendation"],"timeExpire":1495187599642,"variant_id":27661944134},"timestamp":1495187523}` - actual, err := ToJSON(query) - if err != nil { - t.Error(err) - } - actualStr := string(actual) - if actualStr != expected { - t.Errorf("Expected: %s Actual: %s", expected, actualStr) - } -} - -func TestToJSONDuplicateKey(t *testing.T) { - query := "cat=1&cat=2" - expected := `{"cat":2}` - actual, err := ToJSON(query) - if err != nil { - t.Error(err) - } - actualStr := string(actual) - if actualStr != expected { - t.Errorf("Expected: %s Actual: %s", expected, actualStr) - } -} - -func TestSplitKeyAndValue(t *testing.T) { - param := "a[dog][=cat]=123" - eKey, eValue := "a[dog][=cat]", "123" - aKey, aValue, err := splitKeyAndValue(param) - if err != nil { - t.Error(err) - } - if eKey != aKey { - t.Errorf("Keys do not match. Expected: %s Actual: %s", eKey, aKey) - } - if eValue != aValue { - t.Errorf("Values do not match. Expected: %s Actual: %s", eValue, aValue) - } -} - -func TestEncodedAmpersand(t *testing.T) { - query := "a=xyz&b[d]=ben%26jerry" - expected := unmarshalT{ - A: "xyz", - B: unmarshalB{ - D: "ben&jerry", - }, - } - var actual unmarshalT - err := Unmarshal(&actual, query) - if err != nil { - t.Error(err) - } - if expected != actual { - t.Errorf("Expected: %+v Actual: %+v", expected, actual) - } -} - -func TestEncodedAmpersand2(t *testing.T) { - query := "filter=parent%3Dflow12345%26request%3Dreq12345&meta.limit=20&meta.offset=0" - expected := map[string]interface{}{"filter": "parent=flow12345&request=req12345", "meta.limit": float64(20), "meta.offset": float64(0)} - actual := make(map[string]interface{}) - err := Unmarshal(&actual, query) - if err != nil { - t.Error(err) - } - for k, v := range actual { - if nv, ok := expected[k]; !ok || nv != v { - t.Errorf("Expected: %+v Actual: %+v", expected, actual) - } - } -} diff --git a/util/stream/stream.go b/util/stream/stream.go deleted file mode 100644 index 771d38626b..0000000000 --- a/util/stream/stream.go +++ /dev/null @@ -1,88 +0,0 @@ -// Package stream encapsulates streams within streams -package stream - -import ( - "context" - "sync" - - "go-micro.dev/v5/client" - "go-micro.dev/v5/codec" - "go-micro.dev/v5/metadata" - "go-micro.dev/v5/server" -) - -type Stream interface { - Context() context.Context - SendMsg(interface{}) error - RecvMsg(interface{}) error - Close() error -} - -type stream struct { - Stream - - err error - request *request - - sync.RWMutex -} - -type request struct { - client.Request - context context.Context -} - -func (r *request) Codec() codec.Reader { - return r.Request.Codec().(codec.Reader) -} - -func (r *request) Header() map[string]string { - md, _ := metadata.FromContext(r.context) - return md -} - -func (r *request) Read() ([]byte, error) { - return nil, nil -} - -func (s *stream) Request() server.Request { - return s.request -} - -func (s *stream) Send(v interface{}) error { - err := s.Stream.SendMsg(v) - if err != nil { - s.Lock() - s.err = err - s.Unlock() - } - return err -} - -func (s *stream) Recv(v interface{}) error { - err := s.Stream.RecvMsg(v) - if err != nil { - s.Lock() - s.err = err - s.Unlock() - } - return err -} - -func (s *stream) Error() error { - s.RLock() - defer s.RUnlock() - return s.err -} - -// New returns a new encapsulated stream -// Proto stream within a server.Stream. -func New(service, endpoint string, req interface{}, s Stream) server.Stream { - return &stream{ - Stream: s, - request: &request{ - context: s.Context(), - Request: client.DefaultClient.NewRequest(service, endpoint, req), - }, - } -}