422 Unprocessable Entity response when POSTing file upload in Clojure

1.6k views Asked by At

I am trying to emulate this curl request

curl "https://{subdomain}.zendesk.com/api/v2/uploads.json?filename=myfile.dat&token={optional_token}" \
  -v -u {email_address}:{password} \
  -H "Content-Type: application/binary" \
  --data-binary @file.dat -X POST

with the following code

  (POST "/uploads" request
    (let [filename (get-in request [:params "file" :filename])
          file (get-in request [:params "file" :tempfile])
          url (str "https://REDACTED.zendesk.com/api/v2/uploads.json?filename=" filename)]
        (clj-http.client/post url {:headers {"Content-Type" “application/binary”}
                                   :multipart-params [{:name "file"
                                                       :content file
                                                       :mime-type "application/binary”}]})

but I am getting a ‘422 Unprocessable Entity’ response from Zendesk. The file/tempfile is coming in as #object[java.io.File 0x3768306f "/var/folders/l3/7by17gp51sx2gb2ggykwl9zc0000gn/T/ring-multipart-6501654841068837352.tmp"] on the request.

I have played with clojure.java.io coercions (like clojure.java.io/output-stream) as mentioned at Saving an image form clj-http request to file, but that didn't help.

(PS. I’m fairly certain I don’t need to auth because I can get the direct upload to Zendesk to work through Postman.)

1

There are 1 answers

0
sansovich On BEST ANSWER

After revisiting this, the solution was simple. Zendesk expects the request body to be binary (as the curl request indicates). So, in this case, I passed the image to my server as base64 encoded data (just as JSON).

I then used this library to convert the base64 string to a byte array: https://github.com/xsc/base64-clj

(defn byte-array-from-base64
  [base64-string]
  (base64/decode-bytes (.getBytes base64-string)))

Finally, you can simple pass the byte array to Zendesk as the body of the clj-http library request.

(client/post
  "https://REDACTED.zendesk.com/api/v2/uploads.jsonfilename=filename.jpg"
  {:headers {"Authorization" "Basic AUTHORIZATION_TOKEN"
             "Content-Type" "application/binary"}
   :body (byte-array-from-base64 base64-string)})