aboutsummaryrefslogtreecommitdiffstats
path: root/client/go/internal/curl
diff options
context:
space:
mode:
authorMartin Polden <mpolden@mpolden.no>2023-02-03 15:20:23 +0100
committerMartin Polden <mpolden@mpolden.no>2023-02-03 15:35:25 +0100
commite1e94812425a487069bf33f781bec987e9e49874 (patch)
tree4a892c3b5c0a7dee2cb76f9971e538cb4aba8a16 /client/go/internal/curl
parenta08ae588d6035b69f0961dff596fc871fd1c4e58 (diff)
Re-organize Go code
Diffstat (limited to 'client/go/internal/curl')
-rw-r--r--client/go/internal/curl/curl.go131
-rw-r--r--client/go/internal/curl/curl_test.go45
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())
+}