diff --git a/internal/client/client.go b/internal/client/client.go index 1d20aed4..6f042876 100644 --- a/internal/client/client.go +++ b/internal/client/client.go @@ -164,6 +164,11 @@ func shouldAppendJSONSuffix(path string) bool { if strings.HasSuffix(path, ".json") { return false } + // Wiki open endpoints are served by gateway.gitlink.org.cn which does not + // accept the .json suffix used by the www.gitlink.org.cn API convention. + if strings.Contains(path, "/wiki/open/") { + return false + } parts := strings.Split(strings.Trim(path, "/"), "/") for i, part := range parts { if part == "raw" && i >= 2 && i+2 < len(parts) { diff --git a/shortcuts/wiki/wiki.go b/shortcuts/wiki/wiki.go index a65594d8..c432001e 100644 --- a/shortcuts/wiki/wiki.go +++ b/shortcuts/wiki/wiki.go @@ -219,12 +219,26 @@ func runWrite(method, path string, contentRequired bool) func(ctx *common.Runtim } } -// prepare resolves owner/repo and the numeric project ID for wiki requests. +// prepare resolves owner/repo and the numeric project ID for wiki requests, +// and switches the API base URL to the gateway endpoint that hosts wiki APIs. func prepare(ctx *common.RuntimeContext) (int64, error) { if err := ctx.ResolveOwnerRepo(); err != nil { return 0, err } - return resolveProjectID(ctx) + // Resolve project ID first (requires www base URL for /owner/repo endpoint). + projectID, err := resolveProjectID(ctx) + if err != nil { + return 0, err + } + // Switch to gateway for wiki API calls (/wiki/open/* only available there). + switchToGateway(ctx) + return projectID, nil +} + +// switchToGateway replaces the www subdomain with gateway in the API base URL. +// Wiki endpoints (/wiki/open/*) are only available on gateway.gitlink.org.cn. +func switchToGateway(ctx *common.RuntimeContext) { + ctx.Client.BaseURL = strings.Replace(ctx.Client.BaseURL, "www.gitlink.org.cn", "gateway.gitlink.org.cn", 1) } // baseQuery returns the owner/repo/projectId query shared by read endpoints. diff --git a/shortcuts/wiki/wiki_test.go b/shortcuts/wiki/wiki_test.go index 2451b7b0..99013d63 100644 --- a/shortcuts/wiki/wiki_test.go +++ b/shortcuts/wiki/wiki_test.go @@ -64,7 +64,7 @@ func TestWikiListResolvesProjectID(t *testing.T) { case "/alice/demo.json": sawRepo = true writeJSON(w, map[string]interface{}{"id": float64(4242)}) - case "/wiki/open/wikiPages.json": + case "/wiki/open/wikiPages": sawList = true if got := r.URL.Query().Get("projectId"); got != "4242" { t.Fatalf("projectId = %q, want 4242", got) @@ -89,7 +89,7 @@ func TestWikiListResolvesProjectID(t *testing.T) { func TestWikiViewExplicitProjectID(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.URL.Path != "/wiki/open/getWiki.json" { + if r.URL.Path != "/wiki/open/getWiki" { t.Fatalf("unexpected path: %s", r.URL.Path) } if got := r.URL.Query().Get("pageName"); got != "Home" { @@ -123,7 +123,7 @@ func TestWikiViewMissingPage(t *testing.T) { func TestWikiCreateEncodesContent(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.URL.Path != "/wiki/open/createWiki.json" { + if r.URL.Path != "/wiki/open/createWiki" { t.Fatalf("unexpected path: %s", r.URL.Path) } body := decodeBody(t, r) @@ -185,7 +185,7 @@ func TestWikiCreateContentFile(t *testing.T) { func TestWikiUpdateWithoutContent(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.URL.Path != "/wiki/open/updateWiki.json" { + if r.URL.Path != "/wiki/open/updateWiki" { t.Fatalf("unexpected path: %s", r.URL.Path) } body := decodeBody(t, r) @@ -221,7 +221,7 @@ func TestWikiDeleteDryRun(t *testing.T) { func TestWikiDelete(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.URL.Path != "/wiki/open/deleteWiki.json" { + if r.URL.Path != "/wiki/open/deleteWiki" { t.Fatalf("unexpected path: %s", r.URL.Path) } if r.Method != http.MethodDelete {