github.com/cayleygraph/cayley@v0.7.7/client/client.go (about) 1 package client 2 3 import ( 4 "fmt" 5 "io" 6 "net/http" 7 "net/url" 8 9 "github.com/cayleygraph/quad" 10 "github.com/cayleygraph/quad/pquads" 11 ) 12 13 func New(addr string) *Client { 14 return &Client{addr: addr, cli: http.DefaultClient} 15 } 16 17 type Client struct { 18 addr string 19 cli *http.Client 20 } 21 22 func (c *Client) SetHttpClient(cli *http.Client) { 23 c.cli = cli 24 } 25 func (c *Client) url(s string, q map[string]string) string { 26 addr := c.addr + s 27 if len(q) != 0 { 28 p := make(url.Values, len(q)) 29 for k, v := range q { 30 p.Set(k, v) 31 } 32 addr += "?" + p.Encode() 33 } 34 return addr 35 } 36 37 type errRequestFailed struct { 38 Status string 39 StatusCode int 40 } 41 42 func (e errRequestFailed) Error() string { 43 return fmt.Sprintf("request failed: %d %v", e.StatusCode, e.Status) 44 } 45 func (c *Client) QuadReader() (quad.ReadCloser, error) { 46 resp, err := http.Get(c.url("/api/v2/read", map[string]string{ 47 "format": "pquads", 48 })) 49 if err != nil { 50 return nil, err 51 } 52 if resp.StatusCode != http.StatusOK { 53 resp.Body.Close() 54 return nil, errRequestFailed{StatusCode: resp.StatusCode, Status: resp.Status} 55 } 56 r := pquads.NewReader(resp.Body, 10*1024*1024) 57 r.SetCloser(resp.Body) 58 return r, nil 59 } 60 61 type funcCloser struct { 62 f func() error 63 closed bool 64 } 65 66 func (c funcCloser) Close() error { 67 if c.closed { 68 return nil 69 } 70 c.closed = true 71 return c.f() 72 } 73 func (c *Client) QuadWriter() (quad.WriteCloser, error) { 74 pr, pw := io.Pipe() 75 req, err := http.NewRequest("POST", c.url("/api/v2/write", nil), pr) 76 if err != nil { 77 return nil, err 78 } 79 req.Header.Set("Content-Type", pquads.ContentType) 80 errc := make(chan error, 1) 81 go func() { 82 defer func() { 83 close(errc) 84 pr.Close() 85 }() 86 resp, err := c.cli.Do(req) 87 if resp != nil && resp.Body != nil { 88 defer resp.Body.Close() 89 } 90 if err == nil && resp.StatusCode != http.StatusOK { 91 err = errRequestFailed{StatusCode: resp.StatusCode, Status: resp.Status} 92 } 93 errc <- err 94 }() 95 qw := pquads.NewWriter(pw, &pquads.Options{ 96 Full: false, 97 Strict: false, 98 }) 99 qw.SetCloser(funcCloser{f: func() error { 100 pw.Close() 101 return <-errc 102 }}) 103 return qw, nil 104 }