func (s *server) proxy() http.Handler { sel := selector.NewSelector( selector.Registry((*cmd.DefaultOptions().Registry)), ) director := func(r *http.Request) { parts := strings.Split(r.URL.Path, "/") if len(parts) < 2 { return } if !re.MatchString(parts[1]) { return } next, err := sel.Select(Namespace + "." + parts[1]) if err != nil { return } r.URL.Scheme = "http" s, err := next() if err != nil { return } r.URL.Host = fmt.Sprintf("%s:%d", s.Address, s.Port) r.URL.Path = "/" + strings.Join(parts[2:], "/") } return &httputil.ReverseProxy{ Director: director, } }
func TestBreaker(t *testing.T) { // setup r := mock.NewRegistry() s := selector.NewSelector(selector.Registry(r)) c := client.NewClient( // set the selector client.Selector(s), // add the breaker wrapper client.Wrap(NewClientWrapper()), ) req := c.NewJsonRequest("test.service", "Test.Method", map[string]string{ "foo": "bar", }) var rsp map[string]interface{} // Force to point of trip for i := 0; i < (hystrix.DefaultVolumeThreshold * 2); i++ { c.Call(context.TODO(), req, rsp) } err := c.Call(context.TODO(), req, rsp) if err == nil { t.Error("Expecting tripped breaker, got nil error") } if err.Error() != "hystrix: circuit open" { t.Errorf("Expecting tripped breaker, got %v", err) } }
// Proxy is a reverse proxy used by the micro web and api func Proxy(ns string, ws bool) http.Handler { return &proxy{ Namespace: ns, Selector: selector.NewSelector( selector.Registry((*cmd.DefaultOptions().Registry)), ), re: regexp.MustCompile("^[a-zA-Z0-9]+$"), ws: ws, } }
func TestGRPCClient(t *testing.T) { l, err := net.Listen("tcp", ":0") if err != nil { t.Fatalf("failed to listen: %v", err) } defer l.Close() s := grpc.NewServer() pb.RegisterGreeterServer(s, &greeterServer{}) go s.Serve(l) defer s.Stop() parts := strings.Split(l.Addr().String(), ":") port, _ := strconv.Atoi(parts[len(parts)-1]) addr := strings.Join(parts[:len(parts)-1], ":") r := mock.NewRegistry() r.Register(®istry.Service{ Name: "test", Version: "test", Nodes: []*registry.Node{ ®istry.Node{ Id: "test-1", Address: addr, Port: port, }, }, }) se := selector.NewSelector( selector.Registry(r), ) c := NewClient( client.Registry(r), client.Selector(se), ) req := c.NewRequest("test", "/helloworld.Greeter/SayHello", &pb.HelloRequest{ Name: "John", }) rsp := pb.HelloReply{} err = c.Call(context.TODO(), req, &rsp) if err != nil { t.Fatal(err) } if rsp.Message != "Hello John" { t.Fatalf("Got unexpected response %v", rsp.Message) } }
func newClient(opts ...client.Option) client.Client { options := client.Options{ CallOptions: client.CallOptions{ Backoff: client.DefaultBackoff, Retry: client.DefaultRetry, Retries: client.DefaultRetries, RequestTimeout: client.DefaultRequestTimeout, DialTimeout: transport.DefaultDialTimeout, }, } for _, o := range opts { o(&options) } if len(options.ContentType) == 0 { options.ContentType = "application/grpc+proto" } if options.Broker == nil { options.Broker = broker.DefaultBroker } if options.Registry == nil { options.Registry = registry.DefaultRegistry } if options.Selector == nil { options.Selector = selector.NewSelector( selector.Registry(options.Registry), ) } rc := &grpcClient{ once: sync.Once{}, opts: options, } c := client.Client(rc) // wrap in reverse for i := len(options.Wrappers); i > 0; i-- { c = options.Wrappers[i-1](c) } return c }
func (s *srv) proxy() http.Handler { sel := selector.NewSelector( selector.Registry((*cmd.DefaultOptions().Registry)), ) director := func(r *http.Request) { kill := func() { r.URL.Host = "" r.URL.Path = "" r.URL.Scheme = "" r.Host = "" r.RequestURI = "" } parts := strings.Split(r.URL.Path, "/") if len(parts) < 2 { kill() return } if !re.MatchString(parts[1]) { kill() return } next, err := sel.Select(Namespace + "." + parts[1]) if err != nil { kill() return } s, err := next() if err != nil { kill() return } r.Header.Set(BasePathHeader, "/"+parts[1]) r.URL.Host = fmt.Sprintf("%s:%d", s.Address, s.Port) r.URL.Path = "/" + strings.Join(parts[2:], "/") r.URL.Scheme = "http" r.Host = r.URL.Host } return &proxy{ Default: &httputil.ReverseProxy{Director: director}, Director: director, } }
func newOptions(options ...Option) Options { opts := Options{ Codecs: make(map[string]codec.NewCodec), CallOptions: CallOptions{ Backoff: DefaultBackoff, Retries: DefaultRetries, RequestTimeout: DefaultRequestTimeout, DialTimeout: transport.DefaultDialTimeout, }, PoolSize: DefaultPoolSize, PoolTTL: DefaultPoolTTL, } for _, o := range options { o(&opts) } if len(opts.ContentType) == 0 { opts.ContentType = defaultContentType } if opts.Broker == nil { opts.Broker = broker.DefaultBroker } if opts.Registry == nil { opts.Registry = registry.DefaultRegistry } if opts.Selector == nil { opts.Selector = selector.NewSelector( selector.Registry(opts.Registry), ) } if opts.Transport == nil { opts.Transport = transport.DefaultTransport } return opts }
func NewSelector(opts ...selector.Option) selector.Selector { return selector.NewSelector(opts...) }
func TestRPCHandler(t *testing.T) { r := rmock.NewRegistry() (*cmd.DefaultOptions().Client).Init( client.Registry(r), client.Selector(selector.NewSelector(selector.Registry(r))), ) (*cmd.DefaultOptions().Server).Init( server.Name("test"), server.Registry(r), ) (*cmd.DefaultOptions().Server).Handle( (*cmd.DefaultOptions().Server).NewHandler(&TestHandler{t, metadata.Metadata{"Foo": "Bar"}}), ) if err := server.Start(); err != nil { t.Fatal(err) } if err := server.Register(); err != nil { t.Fatal(err) } w := httptest.NewRecorder() request := map[string]string{ "service": "test", "method": "TestHandler.Exec", "request": "{}", } rb, err := json.Marshal(request) if err != nil { t.Fatal(err) } b := bytes.NewBuffer(rb) req, err := http.NewRequest("POST", "/rpc", b) if err != nil { t.Fatal(err) } req.Header.Set("Content-Type", "application/json") req.Header.Set("Foo", "Bar") RPC(w, req) if err := server.Deregister(); err != nil { t.Fatal(err) } if err := server.Stop(); err != nil { t.Fatal(err) } if w.Code != 200 { t.Fatalf("Expected 200 response got %d %s", w.Code, w.Body.String()) } }