mirror of
https://github.com/logseq/logseq.git
synced 2026-06-01 19:01:22 +00:00
fix: don't use deprecated url/parse
This commit is contained in:
@@ -1,15 +1,14 @@
|
||||
(ns logseq.cli.transport
|
||||
"HTTP transport for communicating with db-worker-node."
|
||||
(:require [cljs.reader :as reader]
|
||||
[clojure.string :as string]
|
||||
[logseq.db :as ldb]
|
||||
[logseq.cli.log :as cli-log]
|
||||
[lambdaisland.glogi :as log]
|
||||
[promesa.core :as p]
|
||||
["fs" :as fs]
|
||||
(:require ["fs" :as fs]
|
||||
["http" :as http]
|
||||
["https" :as https]
|
||||
["url" :as url]))
|
||||
[cljs.reader :as reader]
|
||||
[clojure.string :as string]
|
||||
[lambdaisland.glogi :as log]
|
||||
[logseq.cli.log :as cli-log]
|
||||
[logseq.db :as ldb]
|
||||
[promesa.core :as p]))
|
||||
|
||||
(defn- request-module
|
||||
[^js parsed]
|
||||
@@ -22,18 +21,25 @@
|
||||
{"Content-Type" "application/json"
|
||||
"Accept" "application/json"})
|
||||
|
||||
(defn- request-port
|
||||
[^js parsed]
|
||||
(let [port (.-port parsed)]
|
||||
(if (seq port)
|
||||
port
|
||||
(if (= "https:" (.-protocol parsed)) 443 80))))
|
||||
|
||||
(defn- <raw-request
|
||||
[{:keys [method url headers body timeout-ms]}]
|
||||
(p/create
|
||||
(fn [resolve reject]
|
||||
(let [parsed (url/parse url)
|
||||
(let [parsed (js/URL. url)
|
||||
module (request-module parsed)
|
||||
timeout-ms (or timeout-ms 10000)
|
||||
req (.request
|
||||
module
|
||||
#js {:method method
|
||||
:hostname (.-hostname parsed)
|
||||
:port (or (.-port parsed) (if (= "https:" (.-protocol parsed)) 443 80))
|
||||
:port (request-port parsed)
|
||||
:path (str (.-pathname parsed) (.-search parsed))
|
||||
:headers (clj->js headers)}
|
||||
(fn [^js res]
|
||||
@@ -50,13 +56,13 @@
|
||||
(reject (ex-info "request timeout" {:code :timeout})))
|
||||
timeout-ms)]
|
||||
(.on req "error" (fn [err]
|
||||
(js/clearTimeout timeout-id)
|
||||
(reject err)))
|
||||
(js/clearTimeout timeout-id)
|
||||
(reject err)))
|
||||
(when body
|
||||
(.write req body))
|
||||
(.end req)
|
||||
(.on req "response" (fn [_]
|
||||
(js/clearTimeout timeout-id)))))))
|
||||
(js/clearTimeout timeout-id)))))))
|
||||
|
||||
(defn request
|
||||
[{:keys [method url headers body timeout-ms]}]
|
||||
@@ -97,10 +103,10 @@
|
||||
:args args-preview
|
||||
:url url)
|
||||
(p/let [{:keys [body]} (request {:method "POST"
|
||||
:url url
|
||||
:headers (base-headers)
|
||||
:body body
|
||||
:timeout-ms timeout-ms})
|
||||
:url url
|
||||
:headers (base-headers)
|
||||
:body body
|
||||
:timeout-ms timeout-ms})
|
||||
{:keys [result resultTransit]} (js->clj (js/JSON.parse body) :keywordize-keys true)]
|
||||
(if direct-pass?
|
||||
(let [response-preview (cli-log/truncate-preview result)]
|
||||
|
||||
@@ -29,94 +29,121 @@
|
||||
(resolve {:url (str "http://127.0.0.1:" port)
|
||||
:stop! stop!}))))))))
|
||||
|
||||
(deftest test-request-avoids-deprecated-url-parse
|
||||
(async done
|
||||
(let [url-module (js/require "url")
|
||||
original-parse (.-parse url-module)
|
||||
parse-calls (atom 0)]
|
||||
(set! (.-parse url-module)
|
||||
(fn [& args]
|
||||
(swap! parse-calls inc)
|
||||
(.apply original-parse url-module (to-array args))))
|
||||
(-> (p/let [{:keys [url stop!]} (start-server
|
||||
(fn [_req ^js res]
|
||||
(.writeHead res 200 #js {"Content-Type" "text/plain"})
|
||||
(.end res "ok")))]
|
||||
(p/let [response (transport/request {:method "GET"
|
||||
:url (str url "/status")
|
||||
:timeout-ms 1000})]
|
||||
(is (= 200 (:status response)))
|
||||
(is (= 0 @parse-calls))
|
||||
(p/let [_ (stop!)] true)))
|
||||
(p/then (fn [_]
|
||||
(set! (.-parse url-module) original-parse)
|
||||
(done)))
|
||||
(p/catch (fn [e]
|
||||
(set! (.-parse url-module) original-parse)
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
|
||||
(deftest test-request-does-not-retry
|
||||
(async done
|
||||
(let [calls (atom 0)]
|
||||
(-> (p/let [{:keys [url stop!]} (start-server
|
||||
(fn [_req ^js res]
|
||||
(let [attempt (swap! calls inc)]
|
||||
(if (= attempt 1)
|
||||
(do
|
||||
(.writeHead res 500 #js {"Content-Type" "text/plain"})
|
||||
(.end res "boom"))
|
||||
(do
|
||||
(.writeHead res 200 #js {"Content-Type" "text/plain"})
|
||||
(.end res "ok"))))))]
|
||||
(p/catch
|
||||
(transport/request {:method "GET"
|
||||
:url (str url "/retry")
|
||||
:timeout-ms 1000})
|
||||
(fn [e]
|
||||
(is (= :http-error (-> (ex-data e) :code)))
|
||||
(is (= 500 (-> (ex-data e) :status)))))
|
||||
(is (= 1 @calls))
|
||||
(p/let [_ (stop!)] true))
|
||||
(p/then (fn [_] (done)))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
(let [calls (atom 0)]
|
||||
(-> (p/let [{:keys [url stop!]} (start-server
|
||||
(fn [_req ^js res]
|
||||
(let [attempt (swap! calls inc)]
|
||||
(if (= attempt 1)
|
||||
(do
|
||||
(.writeHead res 500 #js {"Content-Type" "text/plain"})
|
||||
(.end res "boom"))
|
||||
(do
|
||||
(.writeHead res 200 #js {"Content-Type" "text/plain"})
|
||||
(.end res "ok"))))))]
|
||||
(p/catch
|
||||
(transport/request {:method "GET"
|
||||
:url (str url "/retry")
|
||||
:timeout-ms 1000})
|
||||
(fn [e]
|
||||
(is (= :http-error (-> (ex-data e) :code)))
|
||||
(is (= 500 (-> (ex-data e) :status)))))
|
||||
(is (= 1 @calls))
|
||||
(p/let [_ (stop!)] true))
|
||||
(p/then (fn [_] (done)))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
|
||||
(deftest test-request-timeout
|
||||
(async done
|
||||
(-> (p/let [{:keys [url stop!]} (start-server
|
||||
(fn [_req _res]
|
||||
nil))]
|
||||
(p/catch
|
||||
(transport/request {:method "GET"
|
||||
:url (str url "/hang")
|
||||
:timeout-ms 10})
|
||||
(fn [e]
|
||||
(is (= :timeout (-> (ex-data e) :code)))
|
||||
(p/let [_ (stop!)] true))))
|
||||
(p/then (fn [_] (done)))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done))))))
|
||||
(-> (p/let [{:keys [url stop!]} (start-server
|
||||
(fn [_req _res]
|
||||
nil))]
|
||||
(p/catch
|
||||
(transport/request {:method "GET"
|
||||
:url (str url "/hang")
|
||||
:timeout-ms 10})
|
||||
(fn [e]
|
||||
(is (= :timeout (-> (ex-data e) :code)))
|
||||
(p/let [_ (stop!)] true))))
|
||||
(p/then (fn [_] (done)))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done))))))
|
||||
|
||||
(deftest test-invoke-accepts-keyword-method
|
||||
(async done
|
||||
(let [received (atom nil)]
|
||||
(-> (p/let [{:keys [url stop!]} (start-server
|
||||
(fn [^js req ^js res]
|
||||
(let [chunks (array)]
|
||||
(.on req "data" (fn [chunk] (.push chunks chunk)))
|
||||
(.on req "end" (fn []
|
||||
(let [buf (js/Buffer.concat chunks)
|
||||
payload (js/JSON.parse (.toString buf "utf8"))]
|
||||
(reset! received (js->clj payload :keywordize-keys true))
|
||||
(.writeHead res 200 #js {"Content-Type" "application/json"})
|
||||
(.end res (js/JSON.stringify #js {:result "ok"}))))))))]
|
||||
(p/let [result (transport/invoke {:base-url url} :thread-api/pull true ["repo" [:block/title]])]
|
||||
(is (= "ok" result))
|
||||
(is (= "thread-api/pull" (:method @received)))
|
||||
(is (= true (:directPass @received)))
|
||||
(p/let [_ (stop!)] true)))
|
||||
(p/then (fn [_] (done)))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
(let [received (atom nil)]
|
||||
(-> (p/let [{:keys [url stop!]} (start-server
|
||||
(fn [^js req ^js res]
|
||||
(let [chunks (array)]
|
||||
(.on req "data" (fn [chunk] (.push chunks chunk)))
|
||||
(.on req "end" (fn []
|
||||
(let [buf (js/Buffer.concat chunks)
|
||||
payload (js/JSON.parse (.toString buf "utf8"))]
|
||||
(reset! received (js->clj payload :keywordize-keys true))
|
||||
(.writeHead res 200 #js {"Content-Type" "application/json"})
|
||||
(.end res (js/JSON.stringify #js {:result "ok"}))))))))]
|
||||
(p/let [result (transport/invoke {:base-url url} :thread-api/pull true ["repo" [:block/title]])]
|
||||
(is (= "ok" result))
|
||||
(is (= "thread-api/pull" (:method @received)))
|
||||
(is (= true (:directPass @received)))
|
||||
(p/let [_ (stop!)] true)))
|
||||
(p/then (fn [_] (done)))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
|
||||
(deftest test-invoke-does-not-send-auth-header
|
||||
(async done
|
||||
(let [auth-header (atom :unset)]
|
||||
(-> (p/let [{:keys [url stop!]} (start-server
|
||||
(fn [^js req ^js res]
|
||||
(let [headers (.-headers req)]
|
||||
(reset! auth-header (aget headers "authorization")))
|
||||
(.writeHead res 200 #js {"Content-Type" "application/json"})
|
||||
(.end res (js/JSON.stringify #js {:result "ok"}))))]
|
||||
(p/let [result (transport/invoke {:base-url url
|
||||
:auth-token "secret"}
|
||||
:thread-api/pull
|
||||
true
|
||||
["repo" [:block/title]])]
|
||||
(is (= "ok" result))
|
||||
(is (nil? @auth-header))
|
||||
(p/let [_ (stop!)] true)))
|
||||
(p/then (fn [_] (done)))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
(let [auth-header (atom :unset)]
|
||||
(-> (p/let [{:keys [url stop!]} (start-server
|
||||
(fn [^js req ^js res]
|
||||
(let [headers (.-headers req)]
|
||||
(reset! auth-header (aget headers "authorization")))
|
||||
(.writeHead res 200 #js {"Content-Type" "application/json"})
|
||||
(.end res (js/JSON.stringify #js {:result "ok"}))))]
|
||||
(p/let [result (transport/invoke {:base-url url
|
||||
:auth-token "secret"}
|
||||
:thread-api/pull
|
||||
true
|
||||
["repo" [:block/title]])]
|
||||
(is (= "ok" result))
|
||||
(is (nil? @auth-header))
|
||||
(p/let [_ (stop!)] true)))
|
||||
(p/then (fn [_] (done)))
|
||||
(p/catch (fn [e]
|
||||
(is false (str "unexpected error: " e))
|
||||
(done)))))))
|
||||
|
||||
(deftest test-read-input
|
||||
(testing "reads edn input"
|
||||
|
||||
Reference in New Issue
Block a user