fix: don't use deprecated url/parse

This commit is contained in:
Tienson Qin
2026-02-12 23:53:29 +08:00
committed by rcmerci
parent 103d9fd079
commit 39f7006559
2 changed files with 127 additions and 94 deletions

View File

@@ -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)]

View File

@@ -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"