diff --git a/src/clj/metafacture_playground/server.clj b/src/clj/metafacture_playground/server.clj index 91469e7..1aacdae 100644 --- a/src/clj/metafacture_playground/server.clj +++ b/src/clj/metafacture_playground/server.clj @@ -7,4 +7,4 @@ (defn -main [& _args] (let [port (or (env :port) 3000)] (println "Start server with port " port) - (run-jetty #'handler {:port port :join? false}))) + (run-jetty #'handler {:port port :join? false :request-header-size 65536}))) diff --git a/src/cljs/metafacture_playground/events.cljs b/src/cljs/metafacture_playground/events.cljs index 0e9b809..eeb3776 100644 --- a/src/cljs/metafacture_playground/events.cljs +++ b/src/cljs/metafacture_playground/events.cljs @@ -6,7 +6,7 @@ [re-frame.core :as re-frame] [day8.re-frame.fetch-fx] [jtk-dvlp.re-frame.readfile-fx] - [lambdaisland.uri :refer [uri join assoc-query* query-encode]] + [lambdaisland.uri :refer [uri join assoc-query*]] [com.degel.re-frame.storage] [clojure.string :as clj-str] [clojure.walk :as walk] @@ -263,61 +263,60 @@ data-in-flux? (merge {:data data}))) {})) -(defn- count-query-string [params] - (reduce - (fn [result [k v]] - (if v - (+ result - (-> k name count) - 2 ;; '&' before key + '=' after key - (-> v query-encode count)) - result)) - 0 - params)) - -(defn- query-string-too-long? [params maximum] - (try - (> (count-query-string params) - maximum) - (catch js/RangeError _ - true))) +(def max-url-string 65536) ; maximum displayable URL length in Firefox + +(defn- url-too-long? [url] + (if-not (:error url) + (> (count url) max-url-string) + true)) (defn generate-link [url path query-params] (let [inputs (-> query-params (dissoc :active-editor) vals)] (when-not (every? clj-str/blank? inputs) - (-> (uri url) - (join path) - (assoc-query* query-params) - str)))) + (try + (-> (uri url) + (join path) + (assoc-query* query-params) + str) + (catch js/Error _ + {:error true}))))) + +(defn add-error-message [result name url] + (if (:error url) + (conj result (str "It occured an JS Error generating the " name".")) + (conj result (str "The " name " is " + (- max-url-string (count url)) + " characters too long (Maximum: " max-url-string ")")))) + +(defn firefox-used? [] + (> (-> js/navigator .-userAgent (.indexOf "Firefox")) + -1)) (defn generate-links [{db :db} [_ url data flux fix morph active-editor]] - (let [max-query-string 1536 - max-url-string 2048 - api-call-params (when flux + (let [api-call-params (when flux (merge {:flux flux} (get-used-params flux fix morph data))) workflow-params (merge api-call-params (when active-editor {:active-editor (name active-editor)})) - api-call-query-string-too-long? (query-string-too-long? api-call-params max-query-string) - workflow-query-string-too-long? (query-string-too-long? workflow-params max-query-string) - api-call-link (when (and api-call-params (not api-call-query-string-too-long?)) - (generate-link url "./process" api-call-params)) - workflow-link (when (and workflow-params (not workflow-query-string-too-long?)) - (generate-link url "" workflow-params)) - url-string-too-long? (or (> (count api-call-link) max-url-string) - (> (count workflow-link) max-url-string)) - message (when (or api-call-query-string-too-long? workflow-query-string-too-long? url-string-too-long?) - {:content "Share links for large workflows are not supported yet" + api-call-link (when api-call-params (generate-link url "./process" api-call-params)) + workflow-link (when workflow-params (generate-link url "" workflow-params)) + api-call-link-too-long? (url-too-long? api-call-link) + workflow-link-too-long? (url-too-long? workflow-link) + message (when (or api-call-link-too-long? workflow-link-too-long?) + {:content (cond-> ["There was a problem generating the share links:"] + api-call-link-too-long? (add-error-message "api call link" api-call-link) + workflow-link-too-long? (add-error-message "workflow link" workflow-link) + (not (firefox-used?)) (conj "Consider using Firefox.")) :type :warning})] {:db (-> db (assoc :message message) - (assoc-in [:links :api-call] (when-not url-string-too-long? api-call-link)) - (assoc-in [:links :workflow] (when-not url-string-too-long? workflow-link)))})) + (assoc-in [:links :api-call] (when-not api-call-link-too-long? api-call-link)) + (assoc-in [:links :workflow] (when-not workflow-link-too-long? workflow-link)))})) (re-frame/reg-event-fx ::generate-links diff --git a/test/cljs/metafacture_playground/event_handler_test.cljs b/test/cljs/metafacture_playground/event_handler_test.cljs index 4b1b775..3204fdf 100644 --- a/test/cljs/metafacture_playground/event_handler_test.cljs +++ b/test/cljs/metafacture_playground/event_handler_test.cljs @@ -174,23 +174,12 @@ (is (= (-> workflow-link :query query-string->map :morph) morph)) (is (= (:path workflow-link) "/playground/"))))) - (testing "Test not generating links if parameters are too long" - (let [db' (-> empty-db - (events/edit-value [:edit-value :flux (generate-random-string 1537)])) - flux (get-in db' [:db :input-fields :flux :content]) - db'' (-> db' - (events/generate-links [:generate-links "http://test.metafacture.org/playground/" nil flux nil nil :fix]) - :db)] - (and (is (= (get-in db'' [:message :content]) "Share links for large workflows are not supported yet")) - (is (nil? (get-in db'' [:links :api-call]))) - (is (nil? (get-in db'' [:links :workflow])))))) - (testing "Test not generating links if url is too long" - (let [extra-long-test-url (str "http://test.metafacture.org/playground/" (generate-random-string 1671) "/") + (let [extra-long-test-url (str "http://test.metafacture.org/playground/" (generate-random-string 66000) "/") db'' (-> empty-db (events/generate-links [:generate-links extra-long-test-url (:data sample-data) (:flux sample-data) (:fix sample-data) "" :fix]) :db)] - (and (is (= (get-in db'' [:message :content]) "Share links for large workflows are not supported yet")) + (and (is (get-in db'' [:message :content])) (is (nil? (get-in db'' [:links :api-call]))) (is (nil? (get-in db'' [:links :workflow])))))))