Fork me on GitHub
#cljsrn
<
2023-02-22
>
Galaux07:02:56

@hadilsabbagh18 Ah thank you very much.

Galaux07:02:42

> 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?

hadils16:02:44

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.

2
Charles Suggs18:02:48

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 Suggs18:02:42

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 Suggs18:02:58

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 Suggs19:02:55

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)))
    {}))

joshmiller00:02:47

@U0135ATQM4P 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 Suggs14:02:49

Hi @U0E1JV8GK 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 Suggs19:02:23

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

joshmiller19:02:02

What did you change to get it going in iOS?

Charles Suggs19:02:51

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.

😬 2
Charles Suggs19:02:40

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}})

👍 2
Charles Suggs19:02:07

but no clue why it just fails in Android

Charles Suggs19:02:45

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

joshmiller19:02:26

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

Charles Suggs19:02:15

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

Charles Suggs19:02:34

Here's what the error handler prints for Android:

joshmiller19:02:08

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

Charles Suggs19:02:22

I'll follow-up here with the results

👍 2
Charles Suggs23:02:22

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 Suggs23:02:49

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.

joshmiller00:02:32

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.

Charles Suggs15:02:08

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 Suggs15:02:26

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

Charles Suggs18:02:54

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

Charles Suggs20:02:35

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

🙌 2