Browse Source

feat(sync): impl proxy support

refactor: use system proxy when possible
chore: update yarn.lock
Andelf 2 years ago
parent
commit
9a4541c7f5

+ 1 - 1
resources/package.json

@@ -37,7 +37,7 @@
     "https-proxy-agent": "5.0.0",
     "@sentry/electron": "2.5.1",
     "posthog-js": "1.10.2",
-    "@logseq/rsapi": "0.0.54",
+    "@logseq/rsapi": "0.0.56",
     "electron-deeplink": "1.0.10",
     "abort-controller": "3.0.0"
   },

+ 1 - 0
src/electron/electron/configs.cljs

@@ -5,6 +5,7 @@
     ["electron" :refer [^js app] :as electron]
     [cljs.reader :as reader]))
 
+;; FIXME: move configs.edn to where it should be
 (defonce dot-root (.join path (.getPath app "home") ".logseq"))
 (defonce cfg-root (.getPath app "userData"))
 (defonce cfg-path (.join path cfg-root "configs.edn"))

+ 2 - 2
src/electron/electron/core.cljs

@@ -2,7 +2,7 @@
   (:require [electron.handler :as handler]
             [electron.search :as search]
             [electron.updater :refer [init-updater] :as updater]
-            [electron.utils :refer [*win mac? linux? dev? get-win-from-sender restore-user-fetch-agent
+            [electron.utils :refer [*win mac? linux? dev? get-win-from-sender
                                     decode-protected-assets-schema-path get-graph-name send-to-renderer]
              :as utils]
             [electron.url :refer [logseq-url-handler]]
@@ -300,7 +300,7 @@
                    _ (reset! *win win)]
                (logger/info (str "Logseq App(" (.getVersion app) ") Starting... "))
 
-               (restore-user-fetch-agent)
+               (utils/<restore-proxy-settings)
 
                (js-utils/disableXFrameOptions win)
 

+ 12 - 8
src/electron/electron/handler.cljs

@@ -357,16 +357,24 @@
 (defmethod handle :getLogseqDotDirRoot []
   (utils/get-ls-dotdir-root))
 
-(defmethod handle :getProxy [^js window]
+(defmethod handle :getSystemProxy [^js window]
   (if-let [sess (.. window -webContents -session)]
     (p/let [proxy (.resolveProxy sess "https://www.google.com")]
       proxy)
     (p/resolved nil)))
 
-(defmethod handle :testProxyUrl [_win [_ url]]
-  (let [start-ms (.getTime (js/Date.))]
+(defmethod handle :setProxy [_win [_ options]]
+  ;; options: {:type "system" | "direct" | "socks5" | "http" | ... }
+  (p/do!
+   (utils/<set-proxy options)
+   (utils/save-proxy-settings options)))
+
+(defmethod handle :testProxyUrl [_win [_ url options]]
+  ;; FIXME: better not to set proxy while testing url
+  (let [_ (utils/<set-proxy options)
+        start-ms (.getTime (js/Date.))]
     (-> (utils/fetch url)
-        (p/timeout 5000)
+        (p/timeout 10000)
         (p/then (fn [resp]
                   (let [code (.-status resp)
                         response-ms (- (.getTime (js/Date.)) start-ms)]
@@ -568,10 +576,6 @@
   (when-let [web-content (.-webContents win)]
     (.reload web-content)))
 
-(defmethod handle :setHttpsAgent [^js _win [_ opts]]
-  (prn ::opts opts)
-  (utils/set-fetch-agent opts))
-
 ;;;;;;;;;;;;;;;;;;;;;;;
 ;; file-sync-rs-apis ;;
 ;;;;;;;;;;;;;;;;;;;;;;;

+ 140 - 14
src/electron/electron/utils.cljs

@@ -1,11 +1,13 @@
 (ns electron.utils
-  (:require [clojure.string :as string]
+  (:require ["@logseq/rsapi" :as rsapi]
+            ["electron" :refer [app BrowserWindow]]
             ["fs-extra" :as fs]
             ["path" :as path]
+            [cljs-bean.core :as bean]
+            [clojure.string :as string]
             [electron.configs :as cfgs]
             [electron.logger :as logger]
-            [cljs-bean.core :as bean]
-            ["electron" :refer [app BrowserWindow]]))
+            [promesa.core :as p]))
 
 (defonce *win (atom nil)) ;; The main window
 
@@ -31,7 +33,6 @@
 (defn fetch
   ([url] (fetch url nil))
   ([url options]
-   (prn ::debug-fetch @*fetchAgent)
    (_fetch url (bean/->js (merge options {:agent @*fetchAgent})))))
 
 (defn get-ls-dotdir-root
@@ -53,18 +54,143 @@
                   (map #(path/join plugins-root (.-name %))))]
     dirs))
 
-(defn set-fetch-agent
-  [{:keys [protocol host port] :as opts}]
-  (prn ::set-fetch-agent opts)
-  (reset! *fetchAgent
-          (when (and protocol host port)
-            (new HttpsProxyAgent (str protocol "://" host ":" port))))
-  (cfgs/set-item! :settings/agent opts))
+(defn- set-fetch-agent-proxy
+  "Set proxy for fetch agent(plugin system)
+  protocol: http | socks5"
+  [{:keys [protocol host port]}]
+  (if (and protocol host port (or (= protocol "http") (= protocol "socks5")))
+    (let [proxy-url (str protocol "://" host ":" port)]
+      (reset! *fetchAgent (new HttpsProxyAgent proxy-url)))
+    (reset! *fetchAgent nil)))
+
+(defn- set-rsapi-proxy
+  "Set proxy for Logseq Sync(rsapi)"
+  [{:keys [protocol host port]}]
+  (if (and protocol host port (or (= protocol "http") (= protocol "socks5")))
+    (let [proxy-url (str protocol "://" host ":" port)]
+      (rsapi/setProxy proxy-url))
+    (rsapi/setProxy nil)))
+
+(defn <set-electron-proxy
+  "Set proxy for electron
+  type: system | direct | socks5 | http"
+  ([{:keys [type host port] :or {type "system"}}]
+   (let [->proxy-rules (fn [type host port]
+                         (cond
+                           (= type "http")
+                           (str "http=" host ":" port ";https=" host ":" port)
+                           (= type "socks5")
+                           (str "http=socks5://" host ":" port ";https=socks5://" host ":" port)
+                           (or (= type "socks") (= type "socks4"))
+                           (str "http=socks://" host ":" port ";https=socks://" host ":" port)
+                           (= type "direct")
+                           "direct://"
+                           :else
+                           nil))
+         config (cond
+                  (= type "system")
+                  #js {:mode "system"}
+
+                  (= type "direct")
+                  #js {:mode "direct"}
+
+                  (or (= type "socks5") (= type "http"))
+                  #js {:mode "fixed_servers"
+                       :proxyRules (->proxy-rules type host port)
+                       :proxyBypassRules "<local>"}
+
+                  :else
+                  #js {:mode "system"})
+         sess (.. ^js @*win -webContents -session)]
+     (if sess
+       (p/do!
+        (.setProxy sess config)
+        (.forceReloadProxyConfig sess))
+       (p/resolved nil)))))
+
+(defn- parse-pac-rule
+  "Parse Proxy Auto Config(PAC) line"
+  [line]
+  (let [parts (string/split line #"[ :]")
+        type (first parts)]
+    (cond
+      (= type "DIRECT")
+      nil
+
+      (and (contains? #{"PROXY" "HTTP" "SOCKS"} type)
+           (>= (count parts) 3))
+      {:protocol (if (= type "SOCKS") "socks5" "http")
+       :host (nth parts 1)
+       :port (nth parts 2)}
+
+      :else
+      (do
+        (logger/warn "Unknown PAC rule:" line)
+        nil))))
 
-(defn restore-user-fetch-agent
+
+(defn <get-system-proxy
+  "Get system proxy for url, requires proxy to be set to system"
+  ([] (<get-system-proxy "https://www.google.com"))
+  ([for-url]
+   (when-let [sess (.. ^js @*win -webContents -session)]
+     (p/let [proxy (.resolveProxy sess for-url)
+             pac-opts (->> (string/split proxy #";")
+                        (map parse-pac-rule)
+                        (remove nil?))]
+       (when (seq pac-opts)
+         (first pac-opts))))))
+
+(defn <set-proxy
+  "Set proxy for electron, fetch, and rsapi"
+  ([{:keys [type host port] :or {type "system"} :as opts}]
+   (logger/info "set proxy to" opts)
+   (cond
+     (= type "system")
+     (p/let [_ (<set-electron-proxy {:type "system"})
+             proxy (<get-system-proxy)]
+       (set-fetch-agent-proxy proxy)
+       (set-rsapi-proxy proxy))
+
+     (= type "direct")
+     (do
+       (<set-electron-proxy {:type "direct"})
+       (set-fetch-agent-proxy nil)
+       (set-rsapi-proxy nil))
+
+     (or (= type "socks5") (= type "http"))
+     (do
+       (<set-electron-proxy {:type type :host host :port port})
+       (set-fetch-agent-proxy {:protocol type :host host :port port})
+       (set-rsapi-proxy {:protocol type :host host :port port}))
+
+     :else
+     (logger/error "Unknown proxy type:" type))))
+
+(defn <restore-proxy-settings
+  "Restore proxy settings from configs.edn"
   []
-  (when-let [agent (cfgs/get-item :settings/agent)]
-    (set-fetch-agent agent)))
+  (let [settings (cfgs/get-item :settings/agent)
+        settings (cond
+                   (:type settings)
+                   settings
+
+                   ;; migration from old config
+                   (not-empty (:protocol settings))
+                   (assoc settings :type (:protocol settings))
+
+                   :else
+                   {:type "system"})]
+    (logger/info "restore proxy settings" settings)
+    (<set-proxy settings)))
+
+(defn save-proxy-settings
+  "Save proxy settings to configs.edn"
+  [{:keys [type host port test] :or {type "system"}}]
+  (if (or (= type "system") (= type "direct"))
+    (cfgs/set-item! :settings/agent {:type type :test test})
+    (cfgs/set-item! :settings/agent {:type type :protocol type :host host :port port :test test})))
+
 
 (defn ignored-path?
   "Ignore given path from file-watcher notification"

+ 11 - 10
src/main/frontend/components/plugins.cljs

@@ -377,19 +377,21 @@
    :target "_blank"))
 
 (rum/defc user-proxy-settings-panel
-  [{:keys [protocol] :as agent-opts}]
-  (let [[opts set-opts!] (rum/use-state agent-opts)
+  [{:keys [protocol type] :as agent-opts}]
+  (let [type (or (not-empty type) (not-empty protocol) "system")
+        [opts set-opts!] (rum/use-state agent-opts)
         [testing? set-testing?!] (rum/use-state false)
         *test-input (rum/create-ref)
-        disabled?   (string/blank? (:protocol opts))]
+        disabled?   (or (= (:type opts) "system") (= (:type opts) "direct"))]
     [:div.cp__settings-network-proxy-panel
      [:h1.mb-2.text-2xl.font-bold (t :settings-page/network-proxy)]
      [:div.p-2
       [:p [:label [:strong (t :type)]
-           (ui/select [{:label "Default" :value "default" :selected disabled?}
-                       {:label "HTTP" :value "http" :selected (= protocol "http")}
-                       {:label "SOCKS5" :value "socks5" :selected (= protocol "socks5")}]
-                      #(set-opts! (assoc opts :protocol (if (= % "default") nil %))))]]
+           (ui/select [{:label "System" :value "system" :selected (= type "system")}
+                       {:label "Direct" :value "direct" :selected (= type "direct")}
+                       {:label "HTTP"   :value "http"   :selected (= type "http")}
+                       {:label "SOCKS5" :value "socks5" :selected (= type "socks5")}]
+                      #(set-opts! (assoc opts :type % :protocol %)))]]
       [:p.flex
        [:label.pr-4
         {:class (if disabled? "opacity-50" nil)}
@@ -430,8 +432,7 @@
                   :on-click #(let [val (util/trim-safe (.-value (rum/deref *test-input)))]
                                (when (and (not testing?) (not (string/blank? val)))
                                  (set-testing?! true)
-                                 (-> (p/let [_ (ipc/ipc :setHttpsAgent opts)
-                                             result (ipc/ipc :testProxyUrl val)]
+                                 (-> (p/let [result (ipc/ipc :testProxyUrl val opts)]
                                        (js->clj result :keywordize-keys true))
                                      (p/then (fn [{:keys [code response-ms]}]
                                                (notification/show! (str "Success! Status " code " in " response-ms "ms.") :success)))
@@ -442,7 +443,7 @@
       [:p.pt-2
        (ui/button (t :save)
                   :on-click (fn []
-                              (p/let [_ (ipc/ipc :setHttpsAgent opts)]
+                              (p/let [_ (ipc/ipc :setProxy opts)]
                                 (state/set-state! [:electron/user-cfgs :settings/agent] opts)
                                 (state/close-sub-modal! :https-proxy-panel))))]]]))
 

+ 7 - 4
src/main/frontend/components/settings.cljs

@@ -524,10 +524,13 @@
              true))
 
 (rum/defc user-proxy-settings
-  [{:keys [protocol host port] :as agent-opts}]
-  (ui/button [:span
-              (when-let [e (and protocol host port (str protocol "://" host ":" port))]
-                [:strong.pr-1 e])
+  [{:keys [type protocol host port] :as agent-opts}]
+  (ui/button [:span.flex.items-center
+              [:strong.pr-1
+               (case type
+                 "system" "System Default"
+                 "direct" "Direct"
+                 (and protocol host port (str protocol "://" host ":" port)))]
               (ui/icon "edit")]
              :small? true
              :on-click #(state/set-sub-modal!

+ 34 - 34
static/yarn.lock

@@ -351,41 +351,41 @@
   resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6"
   integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==
 
-"@logseq/[email protected]4":
-  version "0.0.54"
-  resolved "https://registry.yarnpkg.com/@logseq/rsapi-darwin-arm64/-/rsapi-darwin-arm64-0.0.54.tgz#a6f671c22fa13b86897c987e237626ea5e35b067"
-  integrity sha512-sNPWTeUO/wgogQuS3Dbs0eJMCzkahCvkOtYfj/gOwZ5tOrpg8/ZHr7yVX4tbYBLcWKvIXLZYDG2thCZ7nnwP0w==
-
-"@logseq/[email protected]4":
-  version "0.0.54"
-  resolved "https://registry.yarnpkg.com/@logseq/rsapi-darwin-x64/-/rsapi-darwin-x64-0.0.54.tgz#04867139ff2711c9ce8efa943be6fe7fbb811920"
-  integrity sha512-hd7//syo4SybzWggCXQ26IaExRDFZtE6NCjP4V9WSNVW0NdFHn9XcwK/yPvolaxe2NosNvmMkKnnK0u7LXGgrw==
-
-"@logseq/[email protected]4":
-  version "0.0.54"
-  resolved "https://registry.yarnpkg.com/@logseq/rsapi-linux-arm64-gnu/-/rsapi-linux-arm64-gnu-0.0.54.tgz#d3158381510cec95307fef0459bdbecd29ab4f64"
-  integrity sha512-9Y+a23aWcPyZp+FZqv3yUdYzYMQd6mlCdPHBSmVRBBDSM6rTLNMs4xQEiJjxm2BNgjDQMoqZGzXjhvR0ZlPgbQ==
-
-"@logseq/[email protected]4":
-  version "0.0.54"
-  resolved "https://registry.yarnpkg.com/@logseq/rsapi-linux-x64-gnu/-/rsapi-linux-x64-gnu-0.0.54.tgz#a569a69886d7a4c1416c99cbe6df234ca459fdfb"
-  integrity sha512-wwipWPt/F+MLlBw82nOVusB0bD7Ha5Q+h2fnggHknpCMBuhCnJj9xY2jnwa92AiW8KQIPUYpCG5VmUK4dNH8eg==
-
-"@logseq/[email protected]4":
-  version "0.0.54"
-  resolved "https://registry.yarnpkg.com/@logseq/rsapi-win32-x64-msvc/-/rsapi-win32-x64-msvc-0.0.54.tgz#a6fb15d8d1cdb177a3ae30a37c04335bdcff36e0"
-  integrity sha512-sUKCObHWXrwdJK5Lda0rhYVLQUaE64FBJoC2oPPfRoBRDzJiYdH3dX18SpAj8j1VEoyoJry7OklwQzptbpj0LA==
-
-"@logseq/[email protected]4":
-  version "0.0.54"
-  resolved "https://registry.yarnpkg.com/@logseq/rsapi/-/rsapi-0.0.54.tgz#35eab4b5e07b034f604debac292f9070aa33f2c3"
-  integrity sha512-5m7Nuus9bx/SWM8EN0c4Kc6v+rhiY1bjiymCe6PoYfq/IX1J0NObUSXmUv5r1KpJLKBdO2wyx1300k45Hgu3QA==
+"@logseq/[email protected]6":
+  version "0.0.56"
+  resolved "https://registry.yarnpkg.com/@logseq/rsapi-darwin-arm64/-/rsapi-darwin-arm64-0.0.56.tgz#16d0c8e5760b90ffdc11380b6be1ce469e5eb445"
+  integrity sha512-0JbnQRJyapQABKF7nKrBmAXXuCDygCYZkFKM6bb2/WlkVxjJV2EZle5otmXye6DTPBUm2Ve2PcBXNL8JqMnsgg==
+
+"@logseq/[email protected]6":
+  version "0.0.56"
+  resolved "https://registry.yarnpkg.com/@logseq/rsapi-darwin-x64/-/rsapi-darwin-x64-0.0.56.tgz#16224e6beb5905fe3d2a5e993fc02fe7add596eb"
+  integrity sha512-xGItNcUsNtCa6XU2YEdvhnIXJCwn8+HTY5f3RsYxjhrh1Sk7E6XOAVIif/H/awosD/EScy48ehkV8wkZwSihkA==
+
+"@logseq/[email protected]6":
+  version "0.0.56"
+  resolved "https://registry.yarnpkg.com/@logseq/rsapi-linux-arm64-gnu/-/rsapi-linux-arm64-gnu-0.0.56.tgz#fb0f051ff3f0359efb703c93847d9d1fd2d0f277"
+  integrity sha512-0yeVK6H7aAKfA2Fz+a0nAKoMLHrt3AjThzocFPPLW4Wmskdyb3hpTkhWKHjnlHiaXkgs7ivdqlsqJsaLpnEh8w==
+
+"@logseq/[email protected]6":
+  version "0.0.56"
+  resolved "https://registry.yarnpkg.com/@logseq/rsapi-linux-x64-gnu/-/rsapi-linux-x64-gnu-0.0.56.tgz#5752074d8d51d98d658bd1500e3fbfc2fca4c946"
+  integrity sha512-e7qf93L3BuXyOW/8dxmcHtZxSWCCn7LDxtMaudGrIU+xlpmLYK+WxRei3iHOC2luz/szJpXQsbH0arpSOtrygw==
+
+"@logseq/[email protected]6":
+  version "0.0.56"
+  resolved "https://registry.yarnpkg.com/@logseq/rsapi-win32-x64-msvc/-/rsapi-win32-x64-msvc-0.0.56.tgz#c0327a68090d83066e1207be25ffa41218299292"
+  integrity sha512-hHTwN7EzHYoDR0t1de6br8DyyHTNNpGvUUkBXq7py5OQmGeiZT5JxD6pQRi1oYpBE1WraN215mYfPKNr5ETJ6w==
+
+"@logseq/[email protected]6":
+  version "0.0.56"
+  resolved "https://registry.yarnpkg.com/@logseq/rsapi/-/rsapi-0.0.56.tgz#1f2306dcac194ecba6a196853ebbedccb19928f9"
+  integrity sha512-F97Mdn9xi0kAhpmTKNhTrh+PyToGrxYBDP0fJ38S93CWvowN2nkVK+SwUfAcm4M3GwX9dEtMJQquc+WTkSwGRw==
   optionalDependencies:
-    "@logseq/rsapi-darwin-arm64" "0.0.54"
-    "@logseq/rsapi-darwin-x64" "0.0.54"
-    "@logseq/rsapi-linux-arm64-gnu" "0.0.54"
-    "@logseq/rsapi-linux-x64-gnu" "0.0.54"
-    "@logseq/rsapi-win32-x64-msvc" "0.0.54"
+    "@logseq/rsapi-darwin-arm64" "0.0.56"
+    "@logseq/rsapi-darwin-x64" "0.0.56"
+    "@logseq/rsapi-linux-arm64-gnu" "0.0.56"
+    "@logseq/rsapi-linux-x64-gnu" "0.0.56"
+    "@logseq/rsapi-win32-x64-msvc" "0.0.56"
 
 "@malept/cross-spawn-promise@^1.0.0", "@malept/cross-spawn-promise@^1.1.0":
   version "1.1.1"