cljsrn

hadils 2023-02-22T16:47:44.434389Z

Hi @gax. That is what I was referring to. You can use Expo in your app, just like React Native. The krell_index.js file is the major difference to make Expo work.

👍🏻 1
Charles Suggs 2023-02-22T18:32:48.089559Z

Hi all. Is anyone around with familiarity with uploading files via cljs-ajax? I've followed the docs and other examples, tried with (POST ..., and with ajax-request . I am using FormData and setting that as the request body. I have tried setting the Content-Type header to multipart/form-data, and not. I keep getting a Request Failed error along with Failure: Failed. My code...

Charles Suggs 2023-02-23T14:39:49.765419Z

Hi @joshmiller thanks for the input. I make many other http requests, post and get, with this API in the app. Only the file upload fails. For local dev the app is running in an expo-dev-client

Charles Suggs 2023-02-22T18:37:42.253759Z

This also shows a few different things I've tried with some lines commented out...

(defn build-images-form-data []
  (let [data (js/FormData.)
        images @post-images]
    (prn "images in build form data" images)
    (doseq [k (range (count images))]
      (.append data "images" (nth images k) (:uri (nth images k))))
    data))

;; The map passed to :http-xhrio in the re-frame event handler
{:headers {:Cookie (:cookie session)
               :Content-Type "multipart/form-data"}
     :method :post
     :uri uri
     :body images
     ;; :format (ajax/json-request-format)
     ;; :response-format (ajax/raw-response-format)
     :response-format (ajax/json-response-format)
     :timeout 100
     :on-request [:api/request-telemetry]
     :on-failure [:api/error-upload-post-images post]
     :on-success [:posts/images-uploaded post images]}

;; and using the simple POST api:
(POST uri {:headers {:Cookie (:cookie (:user-session db))
                          :Content-Type "multipart/form-data"}
                :body images
                ;; :api (js/XMLHttpRequest.)
                ;; :response-format (ajax/raw-response-format)
                :timeout 100})

Charles Suggs 2023-02-22T18:38:58.782939Z

The server never registers a request, so it looks like the request is failing within cljs-ajax or one of its deps before attempting to contact the remote server.

Charles Suggs 2023-02-22T19:19:55.109769Z

I also tried with js/XMLHttpRequest directly:

(defn send-file [{:keys [path token session body]
                  :as params}]
  (let [request (js/XMLHttpRequest.)
        uri (join [(get-api-base) path])]
    (try
      (.open request "POST" uri true)
      (.setRequestHeader request "Cookie" (:cookie session))
      (set! request -onreadystatechange (fn []
                                          (if (and (= (.-readyState request) (.-DONE js/XMLHttpRequest))
                                                   (= (.-status request) 200))
                                            (prn "request is done")
                                            (prn "request not done" request))))
      (.addEventListener request "error" #(prn "xhr error" (.-isTrusted %)))
      (.send request body)
      (catch :default e
        (prn "failed to setup request" request params e)
        (throw e)))
    {}))

joshmiller 2023-02-23T00:44:47.190359Z

@charles946 Is it possible you have network security settings in your iOS or Android build that are preventing you from reaching the server? On iOS at least it will silently fail if you don’t have the remote server whitelisted.

Charles Suggs 2023-02-28T15:40:08.567879Z

This is also rather interesting: https://stackoverflow.com/questions/60987459/react-native-with-expo-fetch-with-formdata-network-error-on-android-only I just appended the file suffix, like png, to the type prop as described, but that hasn't made a difference. I'm still using fetch like I setup yesterday. May try XMLHttpRequest again with the change to the type value, and if that doesn't do it may need to see if modifying the API is possible to accept an image upload in a different way than with FormData.

Charles Suggs 2023-02-28T15:42:26.327349Z

And the file I'm testing with is < 1MB

Charles Suggs 2023-02-28T18:58:54.347979Z

Sending an empty map (object) does work to send a request to the server, but not FormData so far.

Charles Suggs 2023-02-28T20:31:35.402019Z

ok it looks like I have it working now using XMLHttpRequest directly.

🙌 1
Charles Suggs 2023-02-27T19:44:23.080589Z

More updates. I got this working in iOS, but Android still fails to even make the request.

joshmiller 2023-02-27T19:45:02.734289Z

What did you change to get it going in iOS?

Charles Suggs 2023-02-27T19:53:51.093439Z

heh, I had the URL wrong. I needed to append an ID to the path for uploading the file, which I thought I was doing, but I wasn't.

😬 1
Charles Suggs 2023-02-27T19:54:40.896669Z

Here is the request that works with iOS:

(POST (:uri params) {:headers {:Accept "application/json"
                                        :Authorization (str "Bearer " access-token)
                                        :Cookie (:cookie (:user-session db))
                                        :Content-Type "multipart/form-data"}
                              :body (:body params)
                              ;; :response-format (ajax/raw-response-format)
                              :success-handler (fn [r] (prn "upload success" r))
                              :error-handler (fn [e] (prn "upload errorrrs" e))
                              :timeout {:timeout params}})

👍 1
Charles Suggs 2023-02-27T19:55:07.320769Z

but no clue why it just fails in Android

Charles Suggs 2023-02-27T19:55:45.309299Z

but I wonder if this might be related since the message I see is "Request failed" https://github.com/JulianBirch/cljs-ajax/issues/276

joshmiller 2023-02-27T19:56:26.438649Z

You could try using js/fetch directly, it’s a decent enough API

Charles Suggs 2023-02-27T19:57:15.536589Z

yeah, I was thinking my next step is to use that of XMLHttpRequest directly.

Charles Suggs 2023-02-27T19:57:34.713709Z

Here's what the error handler prints for Android:

joshmiller 2023-02-27T19:58:08.066559Z

Yeah, I think it’s possible that’s the issue. Probably worth trying the JS API and seeing what you get.

Charles Suggs 2023-02-27T19:58:14.197169Z

agreed

Charles Suggs 2023-02-27T19:58:22.717329Z

I'll follow-up here with the results

👍 1
Charles Suggs 2023-02-27T23:06:22.988639Z

I had to go take care of some other things. Just returned to this. Fetch fails on Android with "Network request failed", but works on iOS. I wonder what it is about Android. Here is the code I used:

(-> (js/fetch (:uri params) (clj->js {:method "POST"
                                               :headers {:Accept "application/json"
                                                         :Authorization (str "Bearer " access-token)
                                                         :Cookie (:cookie (:user-session db))
                                                         :Content-Type "multipart/form-data"}
                                               :body (:body params)}))
             (.then (fn [response]
                      (prn "type" (.-type response))
                      (prn "status" (.-status response))
                      (prn "ok" (.-ok response))
                      (prn "statusText" (.-statusText response))))
             (.catch (fn [error]
                       (let [e (js->clj error :keywordize-keys true)]
                         (prn "network error uploading image: " e
                              (.-sourceURL  error) (.-line error) (.-column error))))))

Charles Suggs 2023-02-27T23:30:49.319639Z

I read in https://github.com/facebook/react-native/issues/5308 that some folks were having related issues and had to drop the Content-type header for Android, or that the file URI lacked the proper file:/// prefix. I've ruled both of those out just now.

joshmiller 2023-02-28T00:22:32.461319Z

Hm, interesting. So seems like it’s a RN-but-not-CLJS-on-Android issue? Unfortunately I’ve mostly been concentrated on iOS so haven’t had to dig too deeply on Android problems.

Galaux 2023-02-22T07:09:56.287849Z

@hadilsabbagh18 Ah thank you very much.

Galaux 2023-02-22T07:15:42.048799Z

> Read the Krell documentation. Apart from the github page https://github.com/vouch-opensource/krell that mentions "Integrating with tools like https://expo.dev, and https://storybook.js.org require providing a custom index.js file." and https://github.com/vouch-opensource/krell/wiki, I don't see much documentation re Expo. Any resource I would have missed?