diff --git a/examples/adder/remote/client/main.go b/examples/adder/remote/client/main.go index 461ed79f2460793a527a4a7aee0f2401454f7470..373f1969a3e49e5477360180bcaf5990c67af3d2 100644 --- a/examples/adder/remote/client/main.go +++ b/examples/adder/remote/client/main.go @@ -19,32 +19,20 @@ func main() { panic(err) } + req.Options["encoding"] = cmds.Text + // create http rpc client client := http.NewClient(":6798") - // send request to server - res, err := client.Send(req) - if err != nil { - panic(err) - } - - req.Options["encoding"] = cmds.Text - // create an emitter re, err := cli.NewResponseEmitter(os.Stdout, os.Stderr, req) if err != nil { panic(err) } - // copy received result into cli emitter - if pr, ok := req.Command.PostRun[cmds.CLI]; ok { - err = pr(res, re) - } else { - err = cmds.Copy(re, res) - } + // send request to server + err = client.Execute(req, re, nil) if err != nil { - re.CloseWithError(err) + panic(err) } - - os.Exit(re.Status()) } diff --git a/http/client.go b/http/client.go index d22ee40efb8de9409896ba6dccba0fed2dec827e..3ac2925c4f0e0da4b01e0dc92206077d452d67d4 100644 --- a/http/client.go +++ b/http/client.go @@ -22,16 +22,12 @@ var OptionSkipMap = map[string]bool{ "api": true, } -// Client is the commands HTTP client interface. -type Client interface { - Send(req *cmds.Request) (cmds.Response, error) -} - type client struct { serverAddress string httpClient *http.Client ua string apiPrefix string + fallback cmds.Executor } type ClientOpt func(*client) @@ -48,7 +44,16 @@ func ClientWithAPIPrefix(apiPrefix string) ClientOpt { } } -func NewClient(address string, opts ...ClientOpt) Client { +// ClientWithFallback adds a fallback executor to the client. +// +// Note: This may run the PreRun function twice. +func ClientWithFallback(exe cmds.Executor) ClientOpt { + return func(c *client) { + c.fallback = exe + } +} + +func NewClient(address string, opts ...ClientOpt) cmds.Executor { if !strings.HasPrefix(address, "http://") { address = "http://" + address } @@ -69,6 +74,11 @@ func NewClient(address string, opts ...ClientOpt) Client { func (c *client) Execute(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment) error { cmd := req.Command + err := cmd.CheckArguments(req) + if err != nil { + return err + } + if cmd.PreRun != nil { err := cmd.PreRun(req, env) if err != nil { @@ -76,9 +86,13 @@ func (c *client) Execute(req *cmds.Request, re cmds.ResponseEmitter, env cmds.En } } - res, err := c.Send(req) + res, err := c.send(req) if err != nil { if isConnRefused(err) { + if c.fallback != nil { + // XXX: this runs the PreRun twice + return c.fallback.Execute(req, re, env) + } err = fmt.Errorf("cannot connect to the api. Is the daemon running? To run as a standalone CLI command remove the api file in `$IPFS_PATH/api`") } return err @@ -146,7 +160,7 @@ func (c *client) toHTTPRequest(req *cmds.Request) (*http.Request, error) { return httpReq, nil } -func (c *client) Send(req *cmds.Request) (cmds.Response, error) { +func (c *client) send(req *cmds.Request) (cmds.Response, error) { if req.Context == nil { log.Warningf("no context set in request") req.Context = context.Background() diff --git a/http/client_test.go b/http/client_test.go index 2d4f1e71f5cfd184420e0c79ab00852485e8c6b8..ef714d04919055898a12b38c68f6ded64ac5d5d1 100644 --- a/http/client_test.go +++ b/http/client_test.go @@ -44,7 +44,7 @@ func TestClientUserAgent(t *testing.T) { c := NewClient(tc.host, ClientWithUserAgent(tc.ua)).(*client) c.httpClient = testClient - c.Send(r) + c.send(r) if !called { t.Error("handler has not been called") @@ -84,7 +84,7 @@ func TestClientAPIPrefix(t *testing.T) { c := NewClient(tc.host, ClientWithAPIPrefix(tc.prefix)).(*client) c.httpClient = testClient - c.Send(r) + c.send(r) if !called { t.Error("handler has not been called") diff --git a/http/http_test.go b/http/http_test.go index e1723637940db8f1edd5fc2544d6939d0bb3efb9..850c77fe1b62684eb7d886bb9f7f9c1ac9f70677 100644 --- a/http/http_test.go +++ b/http/http_test.go @@ -99,7 +99,7 @@ func TestHTTP(t *testing.T) { req.Files = tc.file } - res, err := c.Send(req) + res, err := c.(*client).send(req) if tc.sendErr != nil { if err == nil { t.Fatalf("expected error %q but got nil", tc.sendErr)