Skip to content

Commit 16ceff3

Browse files
committed
experimental objectbox client
1 parent fe5b51e commit 16ceff3

File tree

3 files changed

+302
-0
lines changed

3 files changed

+302
-0
lines changed

objectbox/objectbox.go

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// Package objectbox provides a client for accessing Objectbox services.
2+
package objectbox
3+
4+
import (
5+
"encoding/json"
6+
"io"
7+
"net/http"
8+
"net/url"
9+
"time"
10+
11+
"github.com/machinebox/sdk-go/boxutil"
12+
"github.com/pkg/errors"
13+
)
14+
15+
type Object struct {
16+
Rect Rect `json:"rect"`
17+
Score float64 `json:"score"`
18+
}
19+
20+
type Rect struct {
21+
Top int `json:"top"`
22+
Left int `json:"left"`
23+
Width int `json:"width"`
24+
Height int `json:"height"`
25+
}
26+
27+
// Client is an HTTP client that can make requests to the box.
28+
type Client struct {
29+
addr string
30+
31+
// HTTPClient is the http.Client that will be used to
32+
// make requests.
33+
HTTPClient *http.Client
34+
}
35+
36+
// make sure the Client implements boxutil.Box
37+
var _ boxutil.Box = (*Client)(nil)
38+
39+
// New makes a new Client for the box at the specified address.
40+
func New(addr string) *Client {
41+
return &Client{
42+
addr: addr,
43+
HTTPClient: &http.Client{
44+
Timeout: 1 * time.Minute,
45+
},
46+
}
47+
}
48+
49+
// Info gets the details about the box.
50+
func (c *Client) Info() (*boxutil.Info, error) {
51+
var info boxutil.Info
52+
u, err := url.Parse(c.addr + "/info")
53+
if err != nil {
54+
return nil, err
55+
}
56+
if !u.IsAbs() {
57+
return nil, errors.New("box address must be absolute")
58+
}
59+
req, err := http.NewRequest("GET", u.String(), nil)
60+
if err != nil {
61+
return nil, err
62+
}
63+
req.Header.Set("Accept", "application/json; charset=utf-8")
64+
resp, err := c.HTTPClient.Do(req)
65+
if err != nil {
66+
return nil, err
67+
}
68+
defer resp.Body.Close()
69+
if err := json.NewDecoder(resp.Body).Decode(&info); err != nil {
70+
return nil, err
71+
}
72+
return &info, nil
73+
}
74+
75+
// ErrObjectbox represents an error from Objectbox.
76+
type ErrObjectbox string
77+
78+
func (e ErrObjectbox) Error() string {
79+
return "objectbox: " + string(e)
80+
}
81+
82+
// CheckResponse is all the data from /check request to objectbox
83+
type CheckResponse struct {
84+
Detectors []CheckDetectorResponse `json:"detectors"`
85+
}
86+
87+
type CheckDetectorResponse struct {
88+
ID string `json:"id"`
89+
Name string `json:"name"`
90+
Objects []Object `json:"objects"`
91+
}
92+
93+
func (c *Client) parseResponse(r io.Reader) error {
94+
var response struct {
95+
Success bool
96+
Error string
97+
}
98+
if err := json.NewDecoder(r).Decode(&response); err != nil {
99+
return errors.Wrap(err, "decoding response")
100+
}
101+
if !response.Success {
102+
return ErrObjectbox(response.Error)
103+
}
104+
return nil
105+
}

objectbox/objectbox_check.go

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package objectbox
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"io"
7+
"mime/multipart"
8+
"net/http"
9+
"net/url"
10+
"strings"
11+
12+
"github.com/pkg/errors"
13+
)
14+
15+
// Check gets the objects for the image data provided.
16+
func (c *Client) Check(image io.Reader) (CheckResponse, error) {
17+
var buf bytes.Buffer
18+
w := multipart.NewWriter(&buf)
19+
fw, err := w.CreateFormFile("file", "image.dat")
20+
if err != nil {
21+
return CheckResponse{}, err
22+
}
23+
_, err = io.Copy(fw, image)
24+
if err != nil {
25+
return CheckResponse{}, err
26+
}
27+
if err = w.Close(); err != nil {
28+
return CheckResponse{}, err
29+
}
30+
u, err := url.Parse(c.addr + "/objectbox/check")
31+
if err != nil {
32+
return CheckResponse{}, err
33+
}
34+
if !u.IsAbs() {
35+
return CheckResponse{}, errors.New("box address must be absolute")
36+
}
37+
req, err := http.NewRequest("POST", u.String(), &buf)
38+
if err != nil {
39+
return CheckResponse{}, err
40+
}
41+
req.Header.Set("Accept", "application/json; charset=utf-8")
42+
req.Header.Set("Content-Type", w.FormDataContentType())
43+
resp, err := c.HTTPClient.Do(req)
44+
if err != nil {
45+
return CheckResponse{}, err
46+
}
47+
return c.parseCheckResponse(resp.Body)
48+
}
49+
50+
// CheckURL gets the tags for the image at the specified URL.
51+
func (c *Client) CheckURL(imageURL *url.URL) (CheckResponse, error) {
52+
u, err := url.Parse(c.addr + "/objectbox/check")
53+
if err != nil {
54+
return CheckResponse{}, err
55+
}
56+
if !u.IsAbs() {
57+
return CheckResponse{}, errors.New("box address must be absolute")
58+
}
59+
if !imageURL.IsAbs() {
60+
return CheckResponse{}, errors.New("url must be absolute")
61+
}
62+
form := url.Values{}
63+
form.Set("url", imageURL.String())
64+
req, err := http.NewRequest("POST", u.String(), strings.NewReader(form.Encode()))
65+
if err != nil {
66+
return CheckResponse{}, err
67+
}
68+
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
69+
req.Header.Set("Accept", "application/json; charset=utf-8")
70+
resp, err := c.HTTPClient.Do(req)
71+
if err != nil {
72+
return CheckResponse{}, err
73+
}
74+
defer resp.Body.Close()
75+
return c.parseCheckResponse(resp.Body)
76+
}
77+
78+
// CheckBase64 gets the tags for the image in the encoded Base64 data string.
79+
func (c *Client) CheckBase64(data string) (CheckResponse, error) {
80+
u, err := url.Parse(c.addr + "/objectbox/check")
81+
if err != nil {
82+
return CheckResponse{}, err
83+
}
84+
if !u.IsAbs() {
85+
return CheckResponse{}, errors.New("box address must be absolute")
86+
}
87+
form := url.Values{}
88+
form.Set("base64", data)
89+
req, err := http.NewRequest("POST", u.String(), strings.NewReader(form.Encode()))
90+
if err != nil {
91+
return CheckResponse{}, err
92+
}
93+
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
94+
req.Header.Set("Accept", "application/json; charset=utf-8")
95+
resp, err := c.HTTPClient.Do(req)
96+
if err != nil {
97+
return CheckResponse{}, err
98+
}
99+
defer resp.Body.Close()
100+
return c.parseCheckResponse(resp.Body)
101+
}
102+
103+
// parseCheckResponse parses the check response data.
104+
func (c *Client) parseCheckResponse(r io.Reader) (CheckResponse, error) {
105+
var resp struct {
106+
Success bool
107+
Error string
108+
CheckResponse
109+
}
110+
if err := json.NewDecoder(r).Decode(&resp); err != nil {
111+
return CheckResponse{}, errors.Wrap(err, "decoding response")
112+
}
113+
if !resp.Success {
114+
return CheckResponse{}, ErrObjectbox(resp.Error)
115+
}
116+
return resp.CheckResponse, nil
117+
}

objectbox/objectbox_state.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package objectbox
2+
3+
import (
4+
"bytes"
5+
"errors"
6+
"io"
7+
"mime/multipart"
8+
"net/http"
9+
"net/url"
10+
"strings"
11+
)
12+
13+
// PostState uploads new state data.
14+
func (c *Client) PostState(r io.Reader) error {
15+
var buf bytes.Buffer
16+
w := multipart.NewWriter(&buf)
17+
fw, err := w.CreateFormFile("file", "image.dat")
18+
if err != nil {
19+
return err
20+
}
21+
_, err = io.Copy(fw, r)
22+
if err != nil {
23+
return err
24+
}
25+
if err = w.Close(); err != nil {
26+
return err
27+
}
28+
u, err := url.Parse(c.addr + "/objectbox/state")
29+
if err != nil {
30+
return err
31+
}
32+
if !u.IsAbs() {
33+
return errors.New("box address must be absolute")
34+
}
35+
req, err := http.NewRequest("POST", u.String(), &buf)
36+
if err != nil {
37+
return err
38+
}
39+
req.Header.Set("Accept", "application/json; charset=utf-8")
40+
req.Header.Set("Content-Type", w.FormDataContentType())
41+
resp, err := c.HTTPClient.Do(req)
42+
if err != nil {
43+
return err
44+
}
45+
defer resp.Body.Close()
46+
return c.parseResponse(resp.Body)
47+
}
48+
49+
// PostStateURL tells objectbox to download the state file specified
50+
// by the URL.
51+
func (c *Client) PostStateURL(stateURL *url.URL) error {
52+
u, err := url.Parse(c.addr + "/objectbox/state")
53+
if err != nil {
54+
return err
55+
}
56+
if !u.IsAbs() {
57+
return errors.New("box address must be absolute")
58+
}
59+
if !stateURL.IsAbs() {
60+
return errors.New("url must be absolute")
61+
}
62+
form := url.Values{}
63+
form.Set("url", stateURL.String())
64+
req, err := http.NewRequest("POST", u.String(), strings.NewReader(form.Encode()))
65+
if err != nil {
66+
return err
67+
}
68+
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
69+
req.Header.Set("Accept", "application/json; charset=utf-8")
70+
resp, err := c.HTTPClient.Do(req)
71+
if err != nil {
72+
return err
73+
}
74+
defer resp.Body.Close()
75+
err = c.parseResponse(resp.Body)
76+
if err != nil {
77+
return err
78+
}
79+
return nil
80+
}

0 commit comments

Comments
 (0)