diff options
Diffstat (limited to 'client/go/internal/curl')
-rw-r--r-- | client/go/internal/curl/curl.go | 131 | ||||
-rw-r--r-- | client/go/internal/curl/curl_test.go | 45 |
2 files changed, 176 insertions, 0 deletions
diff --git a/client/go/internal/curl/curl.go b/client/go/internal/curl/curl.go new file mode 100644 index 00000000000..b70e0f824a3 --- /dev/null +++ b/client/go/internal/curl/curl.go @@ -0,0 +1,131 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package curl + +import ( + "io" + "net/url" + "os/exec" + "runtime" + + "github.com/kballard/go-shellquote" + "github.com/vespa-engine/vespa/client/go/internal/util" +) + +type header struct { + key string + value string +} + +type Command struct { + Path string + Method string + PrivateKey string + CaCertificate string + Certificate string + bodyFile string + bodyInput io.Reader + url *url.URL + headers []header + rawArgs []string +} + +func (c *Command) GetUrlPrefix() string { + return c.url.Scheme + "://" + c.url.Host +} + +func (c *Command) WithBodyFile(fn string) { + if c.bodyInput != nil { + util.JustExitMsg("cannot use both WithBodyFile and WithBodyInput") + } + c.bodyFile = fn +} + +func (c *Command) WithBodyInput(r io.Reader) { + if c.bodyFile != "" { + util.JustExitMsg("cannot use both WithBodyFile and WithBodyInput") + } + c.bodyInput = r +} + +func (c *Command) Args() []string { + var args []string + if c.PrivateKey != "" { + args = append(args, "--key", c.PrivateKey) + } + if c.Certificate != "" { + args = append(args, "--cert", c.Certificate) + } + if c.CaCertificate != "" { + args = append(args, "--cacert", c.CaCertificate) + } + if c.Method != "" { + args = append(args, "-X", c.Method) + } + for _, header := range c.headers { + args = append(args, "-H", header.key+": "+header.value) + } + if c.bodyFile != "" { + args = append(args, "--data-binary", "@"+c.bodyFile) + } else if c.bodyInput != nil { + args = append(args, "--data-binary", "@-") + } + args = append(args, c.rawArgs...) + args = append(args, c.url.String()) + return args +} + +func (c *Command) String() string { + args := []string{c.Path} + args = append(args, c.Args()...) + return shellquote.Join(args...) +} + +func (c *Command) Header(key, value string) { + c.headers = append(c.headers, header{key: key, value: value}) +} + +func (c *Command) Param(key, value string) { + query := c.url.Query() + query.Set(key, value) + c.url.RawQuery = query.Encode() +} + +func (c *Command) Run(stdout, stderr io.Writer) error { + cmd := exec.Command(c.Path, c.Args()...) + cmd.Stdout = stdout + cmd.Stderr = stderr + cmd.Stdin = c.bodyInput + if err := cmd.Start(); err != nil { + return err + } + return cmd.Wait() +} + +func Post(url string) (*Command, error) { return curl("POST", url) } + +func Get(url string) (*Command, error) { return curl("", url) } + +func RawArgs(url string, args ...string) (*Command, error) { + c, err := curl("", url) + if err != nil { + return nil, err + } + c.rawArgs = args + return c, nil +} + +func curl(method, rawurl string) (*Command, error) { + path := "curl" + if runtime.GOOS == "windows" { + path = "curl.exe" + } + realURL, err := url.Parse(rawurl) + if err != nil { + return nil, err + } + return &Command{ + Path: path, + Method: method, + url: realURL, + }, nil +} diff --git a/client/go/internal/curl/curl_test.go b/client/go/internal/curl/curl_test.go new file mode 100644 index 00000000000..448e1e5199f --- /dev/null +++ b/client/go/internal/curl/curl_test.go @@ -0,0 +1,45 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package curl + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestPost(t *testing.T) { + c, err := Post("https://example.com") + if err != nil { + t.Fatal(err) + } + c.PrivateKey = "key.pem" + c.Certificate = "cert.pem" + c.WithBodyFile("file.json") + c.Header("Content-Type", "application/json") + + assert.Equal(t, "curl --key key.pem --cert cert.pem -X POST -H 'Content-Type: application/json' --data-binary @file.json https://example.com", c.String()) +} + +func TestGet(t *testing.T) { + c, err := Get("https://example.com") + if err != nil { + t.Fatal(err) + } + c.PrivateKey = "key.pem" + c.Certificate = "cert.pem" + c.Param("yql", "select * from sources * where title contains 'foo';") + c.Param("hits", "5") + + assert.Equal(t, `curl --key key.pem --cert cert.pem https://example.com\?hits=5\&yql=select+%2A+from+sources+%2A+where+title+contains+%27foo%27%3B`, c.String()) +} + +func TestRawArgs(t *testing.T) { + c, err := RawArgs("https://example.com/search", "-v", "-m", "10", "-H", "foo: bar") + if err != nil { + t.Fatal(err) + } + c.PrivateKey = "key.pem" + c.Certificate = "cert.pem" + + assert.Equal(t, `curl --key key.pem --cert cert.pem -v -m 10 -H 'foo: bar' https://example.com/search`, c.String()) +} |