Skip to content

Commit

Permalink
Add util
Browse files Browse the repository at this point in the history
  • Loading branch information
asim committed May 30, 2019
1 parent 8618183 commit b487480
Show file tree
Hide file tree
Showing 19 changed files with 687 additions and 8 deletions.
6 changes: 3 additions & 3 deletions broker/http_broker.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ import (
"github.com/micro/go-micro/codec/json"
merr "github.com/micro/go-micro/errors"
"github.com/micro/go-micro/registry"
maddr "github.com/micro/go-micro/util/addr"
mnet "github.com/micro/go-micro/util/net"
mls "github.com/micro/go-micro/util/tls"
"github.com/micro/go-rcache"
maddr "github.com/micro/util/go/lib/addr"
mnet "github.com/micro/util/go/lib/net"
mls "github.com/micro/util/go/lib/tls"
"golang.org/x/net/http2"
)

Expand Down
3 changes: 1 addition & 2 deletions server/rpc_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ import (
"github.com/micro/go-micro/metadata"
"github.com/micro/go-micro/registry"
"github.com/micro/go-micro/transport"

"github.com/micro/util/go/lib/addr"
"github.com/micro/go-micro/util/addr"
)

type rpcServer struct {
Expand Down
6 changes: 3 additions & 3 deletions transport/http_transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import (
"sync"
"time"

maddr "github.com/micro/util/go/lib/addr"
mnet "github.com/micro/util/go/lib/net"
mls "github.com/micro/util/go/lib/tls"
maddr "github.com/micro/go-micro/util/addr"
mnet "github.com/micro/go-micro/util/net"
mls "github.com/micro/go-micro/util/tls"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"
)
Expand Down
126 changes: 126 additions & 0 deletions util/addr/addr.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package addr

import (
"fmt"
"net"
)

var (
privateBlocks []*net.IPNet
)

func init() {
for _, b := range []string{"10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16", "100.64.0.0/10", "fd00::/8"} {
if _, block, err := net.ParseCIDR(b); err == nil {
privateBlocks = append(privateBlocks, block)
}
}
}

func isPrivateIP(ipAddr string) bool {
ip := net.ParseIP(ipAddr)
for _, priv := range privateBlocks {
if priv.Contains(ip) {
return true
}
}
return false
}

// Extract returns a real ip
func Extract(addr string) (string, error) {
// if addr specified then its returned
if len(addr) > 0 && (addr != "0.0.0.0" && addr != "[::]") {
return addr, nil
}

ifaces, err := net.Interfaces()
if err != nil {
return "", fmt.Errorf("Failed to get interfaces! Err: %v", err)
}

var addrs []net.Addr
for _, iface := range ifaces {
ifaceAddrs, err := iface.Addrs()
if err != nil {
// ignore error, interface can dissapear from system
continue
}
addrs = append(addrs, ifaceAddrs...)
}

var ipAddr []byte
var publicIP []byte

for _, rawAddr := range addrs {
var ip net.IP
switch addr := rawAddr.(type) {
case *net.IPAddr:
ip = addr.IP
case *net.IPNet:
ip = addr.IP
default:
continue
}

if !isPrivateIP(ip.String()) {
publicIP = ip
continue
}

ipAddr = ip
break
}

// return private ip
if ipAddr != nil {
return net.IP(ipAddr).String(), nil
}

// return public or virtual ip
if publicIP != nil {
return net.IP(publicIP).String(), nil
}

return "", fmt.Errorf("No IP address found, and explicit IP not provided")
}

// IPs returns all known ips
func IPs() []string {
ifaces, err := net.Interfaces()
if err != nil {
return nil
}

var ipAddrs []string

for _, i := range ifaces {
addrs, err := i.Addrs()
if err != nil {
continue
}

for _, addr := range addrs {
var ip net.IP
switch v := addr.(type) {
case *net.IPNet:
ip = v.IP
case *net.IPAddr:
ip = v.IP
}

if ip == nil {
continue
}

ip = ip.To4()
if ip == nil {
continue
}

ipAddrs = append(ipAddrs, ip.String())
}
}

return ipAddrs
}
38 changes: 38 additions & 0 deletions util/addr/addr_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package addr

import (
"net"
"testing"
)

func TestExtractor(t *testing.T) {
testData := []struct {
addr string
expect string
parse bool
}{
{"127.0.0.1", "127.0.0.1", false},
{"10.0.0.1", "10.0.0.1", false},
{"", "", true},
{"0.0.0.0", "", true},
{"[::]", "", true},
}

for _, d := range testData {
addr, err := Extract(d.addr)
if err != nil {
t.Errorf("Unexpected error %v", err)
}

if d.parse {
ip := net.ParseIP(addr)
if ip == nil {
t.Error("Unexpected nil IP")
}

} else if addr != d.expect {
t.Errorf("Expected %s got %s", d.expect, addr)
}
}

}
14 changes: 14 additions & 0 deletions util/backoff/backoff.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Package backoff provides backoff functionality
package backoff

import (
"math"
"time"
)

func Do(attempts int) time.Duration {
if attempts == 0 {
return time.Duration(0)
}
return time.Duration(math.Pow(10, float64(attempts))) * time.Millisecond
}
18 changes: 18 additions & 0 deletions util/ctx/ctx.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package ctx

import (
"context"
"net/http"
"strings"

"github.com/micro/go-micro/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)
}
41 changes: 41 additions & 0 deletions util/ctx/ctx_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package ctx

import (
"net/http"
"testing"

"github.com/micro/go-micro/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)
}
}
}
}
15 changes: 15 additions & 0 deletions util/file/file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package file

import "os"

// Exists returns true if the path is existing
func Exists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return true, err
}
17 changes: 17 additions & 0 deletions util/file/file_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package file

import (
"testing"
)

func TestExists(t *testing.T) {
ok, err := Exists("/")

if ok {
return
}

if !ok || err != nil {
t.Fatalf("Test Exists fail, %s", err)
}
}
40 changes: 40 additions & 0 deletions util/grpc/grpc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package grpc

import (
"fmt"
"strings"
)

// ServiceMethod converts a gRPC method to a Go method
// Input:
// Foo.Bar, /Foo/Bar, /package.Foo/Bar, /a.package.Foo/Bar
// Output:
// [Foo, Bar]
func ServiceMethod(m string) (string, string, error) {
if len(m) == 0 {
return "", "", fmt.Errorf("malformed method name: %q", m)
}

// grpc method
if m[0] == '/' {
// [ , Foo, Bar]
// [ , package.Foo, Bar]
// [ , a.package.Foo, Bar]
parts := strings.Split(m, "/")
if len(parts) != 3 || len(parts[1]) == 0 || len(parts[2]) == 0 {
return "", "", fmt.Errorf("malformed method name: %q", m)
}
service := strings.Split(parts[1], ".")
return service[len(service)-1], parts[2], nil
}

// non grpc method
parts := strings.Split(m, ".")

// expect [Foo, Bar]
if len(parts) != 2 {
return "", "", fmt.Errorf("malformed method name: %q", m)
}

return parts[0], parts[1], nil
}
Loading

0 comments on commit b487480

Please sign in to comment.