diff --git a/client.go b/client.go index 59a5f4c..a607682 100644 --- a/client.go +++ b/client.go @@ -10,6 +10,9 @@ import ( "net/url" "strconv" "strings" + "mime/multipart" + "os" + "io" ) // Configurations @@ -88,6 +91,8 @@ func (client *Client) commonHTTPRequest(jsonBody interface{}, endpoint, verb str jsonBody = struct{}{} } + // + body, err := json.Marshal(jsonBody) if err != nil { @@ -110,6 +115,11 @@ func (client *Client) commonHTTPRequest(jsonBody interface{}, endpoint, verb str if err != nil { return nil, err } + return client.retrieveResponse(res, req, jsonBody, endpoint, verb, retry) + +} + +func (client *Client) retrieveResponse(res *http.Response, req *http.Request, jsonBody interface{}, endpoint string, verb string, retry bool) ([]byte, error){ switch res.StatusCode { case 200, 201: @@ -125,7 +135,12 @@ func (client *Client) commonHTTPRequest(jsonBody interface{}, endpoint, verb str if err != nil { return nil, err } - return client.commonHTTPRequest(jsonBody, endpoint, verb, true) + if req.Header.Get("Content-Type") == "application/json" { + return client.commonHTTPRequest(jsonBody, endpoint, "POST", true) + }else { + jsonBody := jsonBody.(TagRequest) + return client.fileHTTPRequest(jsonBody, endpoint, "", true) + } } return nil, errors.New("TOKEN_INVALID") case 429: @@ -140,6 +155,57 @@ func (client *Client) commonHTTPRequest(jsonBody interface{}, endpoint, verb str } } +func (client *Client) fileHTTPRequest(jsonBody TagRequest, endpoint string, verb string, retry bool) ([]byte, error) { + + body := &bytes.Buffer{} + writer := multipart.NewWriter(body) + + for idx, file := range jsonBody.Files { + // don't share file name information + fileWriter, err := writer.CreateFormFile("encoded_data", strconv.Itoa(idx)) + if err != nil { + return nil, err + } + fp, err := os.Open(file) + + if err != nil { + return nil, err + } + _, err = io.Copy(fileWriter, fp) + + if err != nil { + return nil, err + } + } + + err := writer.WriteField("op", endpoint) + + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", client.buildURL(endpoint), body) + + if err != nil { + return nil, err + } + + + req.Header.Set("Authorization", "Bearer "+client.AccessToken) + req.Header.Set("Content-Type", writer.FormDataContentType()) + + httpClient := &http.Client{} + res, err := httpClient.Do(req) + + if err != nil { + return nil, err + } + + return client.retrieveResponse(res, req, jsonBody, endpoint, verb, retry) +} + + + // Helper function to build URLs func (client *Client) buildURL(endpoint string) string { parts := []string{client.APIRoot, version, endpoint} diff --git a/requests.go b/requests.go index 22fdb06..8a23a4a 100644 --- a/requests.go +++ b/requests.go @@ -29,6 +29,7 @@ type InfoResp struct { // TagRequest represents a JSON request for /tag/ type TagRequest struct { URLs []string `json:"url"` + Files []string `json:"files,omitempty"` LocalIDs []string `json:"local_ids,omitempty"` Model string `json:"model,omitempty"` } @@ -113,6 +114,24 @@ func (client *Client) Tag(req TagRequest) (*TagResp, error) { return tagres, err } +// Tag allows the client to request tag data on a single, or multiple photos +func (client *Client) TagLocalFile(req TagRequest) (*TagResp, error) { + if len(req.Files) < 1 { + return nil, errors.New("Requires at least one file") + } + + res, err := client.fileHTTPRequest(req, "tag", "", false) + + if err != nil { + return nil, err + } + + tagres := new(TagResp) + err = json.Unmarshal(res, tagres) + + return tagres, err +} + // Feedback allows the user to provide contextual feedback to Clarifai in order to improve their results func (client *Client) Feedback(form FeedbackForm) (*FeedbackResp, error) { if form.DocIDs == nil && form.URLs == nil {