fix(publish): keep legacy short/page URL compatibility

This commit is contained in:
Tienson Qin
2026-04-28 16:40:01 +08:00
parent c2c5dbee0c
commit 3a63f09bef
5 changed files with 132 additions and 8 deletions

View File

@@ -1,4 +1,4 @@
{:paths ["src" "../../resources"]
{:paths ["src" "test" "../../resources"]
:deps
{org.clojure/clojure {:mvn/version "1.12.4"}
rum/rum {:git/url "https://github.com/logseq/rum" ;; fork

View File

@@ -9,4 +9,9 @@
PublishMetaDO logseq.publish.worker/PublishMetaDO}}}
:js-options {:js-provider :import}
:closure-defines {shadow.cljs.devtools.client.env/enabled false}
:devtools {:enabled false}}}}
:devtools {:enabled false}}
:publish-test {:target :node-test
:output-to "worker/dist/worker-test.js"
:devtools {:enabled false}
:compiler-options {:static-fns false}
:main logseq.publish.test-runner/main}}}

View File

@@ -606,6 +606,13 @@
(publish-render/render-page-html transit page-uuid refs-json tagged-nodes)
#js {:headers headers}))))))))))))))
(defn- rewrite-request-path
[request new-path]
(let [request-url (js/URL. (.-url request))
new-url (js/URL. (str (.-origin request-url) new-path))]
(set! (.-search new-url) (.-search request-url))
(js/Request. (str new-url) request)))
(defn ^:large-vars/cleanup-todo handle-fetch [request env]
(let [url (js/URL. (.-url request))
path (.-pathname url)
@@ -709,7 +716,9 @@
(js/Response. (.-body object)
#js {:headers headers}))))))))
(and (string/starts-with? path "/p/") (= method "GET"))
(and (or (string/starts-with? path "/p/")
(string/starts-with? path "/s/"))
(= method "GET"))
(let [parts (string/split path #"/")
short-id (nth parts 2 nil)]
(if (string/blank? short-id)
@@ -727,11 +736,9 @@
(publish-common/not-found)
(let [graph-uuid (aget row "graph_uuid")
page-uuid (aget row "page_uuid")
location (str "/page/" graph-uuid "/" page-uuid)]
(js/Response. nil #js {:status 302
:headers (publish-common/merge-headers
#js {"location" location}
(publish-common/cors-headers))})))))))))
page-path (str "/page/" graph-uuid "/" page-uuid)
page-request (rewrite-request-path request page-path)]
(handle-page-html page-request env)))))))))
(and (string/starts-with? path "/u/") (= method "GET"))
(let [parts (string/split path #"/")

View File

@@ -0,0 +1,91 @@
(ns logseq.publish.routes-test
(:require [cljs.test :refer [async deftest is testing]]
[logseq.publish.routes :as routes]
[promesa.core :as p]))
(defn- json-response
[data]
(js/Response.
(js/JSON.stringify data)
#js {:status 200
:headers #js {"content-type" "application/json"}}))
(defn- short-url-env
[]
(let [do-stub #js {:fetch (fn [url _opts]
(cond
(= "https://publish/short/abc123" url)
(js/Promise.resolve
(json-response
#js {:page #js {"graph_uuid" "graph-1"
"page_uuid" "page-1"}}))
(re-matches #"https://publish/pages/[^/]+/[^/]+/password" url)
(js/Promise.resolve (json-response #js {}))
(re-matches #"https://publish/pages/[^/]+/[^/]+" url)
(js/Promise.resolve
(json-response
#js {"content_hash" "etag-1"
"r2_key" "publish/graph-1/page-1.transit"}))
:else
(js/Promise.resolve
(js/Response. "not found" #js {:status 404}))))}
do-ns #js {:idFromName (fn [_name] "index")
:get (fn [_id] do-stub)}
r2 #js {:get (fn [_key]
(js/Promise.resolve
#js {:arrayBuffer (fn []
(let [payload (.encode (js/TextEncoder.) "{}")]
(js/Promise.resolve (.-buffer payload))))}))}]
#js {"PUBLISH_META_DO" do-ns
"PUBLISH_R2" r2}))
(deftest short-url-does-not-redirect-to-uuid-url
(testing "short URL should not redirect to /page/:graph/:page"
(async done
(let [request (js/Request. "https://publish.example/p/abc123?password=s3cr3t")
env (short-url-env)]
(-> (p/let [response (routes/handle-fetch request env)
body (.text response)]
(is (= 200 (.-status response)))
(is (nil? (.get (.-headers response) "location")))
(is (re-find #"<!doctype html>" body))
(is (not (re-find #"Page not found" body)))
(done))
(p/catch (fn [error]
(is nil (str error))
(done))))))))
(deftest legacy-s-short-url-is-supported
(testing "legacy /s/:short-id should render page html"
(async done
(let [request (js/Request. "https://publish.example/s/abc123")
env (short-url-env)]
(-> (p/let [response (routes/handle-fetch request env)
body (.text response)]
(is (= 200 (.-status response)))
(is (nil? (.get (.-headers response) "location")))
(is (re-find #"<!doctype html>" body))
(is (not (re-find #"Page not found" body)))
(done))
(p/catch (fn [error]
(is nil (str error))
(done))))))))
(deftest page-uuid-route-is-still-supported
(testing "legacy /page/:graph-uuid/:page-uuid should still render page html"
(async done
(let [request (js/Request. "https://publish.example/page/3bc00ad3-f421-41e7-8c65-40861c298be5/6954ee2a-506b-4dd9-bd6d-0dc24db9c055")
env (short-url-env)]
(-> (p/let [response (routes/handle-fetch request env)
body (.text response)]
(is (= 200 (.-status response)))
(is (nil? (.get (.-headers response) "location")))
(is (re-find #"<!doctype html>" body))
(is (not (re-find #"Page not found" body)))
(done))
(p/catch (fn [error]
(is nil (str error))
(done))))))))

View File

@@ -0,0 +1,21 @@
(ns logseq.publish.test-runner
(:require [cljs.test :as ct]
[logseq.publish.routes-test]
[shadow.test :as st]
[shadow.test.env :as env]))
(derive ::node ::ct/default)
(defmethod ct/report [::node :end-run-tests] [m]
(if (ct/successful? m)
(js/process.exit 0)
(js/process.exit 1)))
(defn ^:dev/after-load reset-test-data! []
(-> (env/get-test-data)
(env/reset-test-data!)))
(defn main [& _args]
(reset-test-data!)
(let [test-env (ct/empty-env ::node)]
(st/run-all-tests test-env nil)))