Use stable identifiers to fetch XWiki pages

We now have two ways to fetch page infos from XWiki:

* using the canonical identifier (but through a new endpoint that will resolve stable identifiers as well)
* using the stable identifier

Since we want to store the stable identifier, the stable version is the one exposed through the XWiki registry.
The canonical form is required to fully resolve some list queries from XWiki properly.
This commit is contained in:
Jan Sandbrink
2026-06-04 11:03:45 +02:00
parent 7f650bf1c4
commit 1ba2bf95ce
19 changed files with 612 additions and 127 deletions
@@ -51,6 +51,10 @@ module Wikis
spaces_path = spaces.map { "/spaces/#{CGI.escapeURIComponent(it)}" }.join
"/wikis/#{CGI.escapeURIComponent(wiki)}#{spaces_path}/pages/#{CGI.escapeURIComponent(page)}"
end
def to_s
"#{wiki}:#{spaces.join('.')}.#{page}"
end
end
end
end
@@ -0,0 +1,76 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
module Wikis
module Adapters
module Providers
module XWiki
module Queries
# Fetch page information using a canonical XWiki identifier
class CanonicalPageInfo < BaseQuery
include Concerns::XWikiQuery
def call(input_data:, auth_strategy:)
ref = CanonicalPageReference.parse(input_data.identifier)
return failure(code: :not_found) unless ref
perform_request(ref, auth_strategy:) do |data|
success(
Results::PageInfo.new(
identifier: StablePageReference.parse(data.fetch("id")).to_s,
title: data.fetch("title"),
href: data.fetch("xwikiAbsoluteUrl"),
provider:
)
)
end
end
def perform_request(reference, auth_strategy:, &)
authenticated(auth_strategy) do |http|
handle_response(
# This query is implemented as a PUT on the XWiki side, because it dynamically creates the
# stable identifier that it returns. Passing an empty JSON body is also required for the
# endpoint to not raise an error 🤷
http.with(headers: { "Content-Type": "application/json" })
.put(
rest_url("openproject/documents", query: { docRef: reference.to_s }),
body: "{}"
),
&
)
end
end
end
end
end
end
end
end
@@ -47,7 +47,7 @@ module Wikis
json.fetch("searchResults")
.uniq { |r| r.fetch("id") }
.map do |r|
result = page_info(identifier: r.fetch("id"), auth_strategy:)
result = canonical_page_info(identifier: r.fetch("id"), auth_strategy:)
return result if result.failure?
result.value!
@@ -62,6 +62,12 @@ module Wikis
def escape_quotes(string)
string.gsub("\\", "\\\\").gsub('"', '\"')
end
def canonical_page_info(identifier:, auth_strategy:)
Input::PageInfo.build(identifier:).bind do |input_data|
CanonicalPageInfo.new(model: provider).call(input_data:, auth_strategy:)
end
end
end
end
end
@@ -33,20 +33,21 @@ module Wikis
module Providers
module XWiki
module Queries
class PageInfo < BaseQuery
# Fetch page information using a stable XWiki identifier
class StablePageInfo < BaseQuery
include Concerns::XWikiQuery
def call(input_data:, auth_strategy:)
ref = CanonicalPageReference.parse(input_data.identifier)
ref = StablePageReference.parse(input_data.identifier)
return failure(code: :not_found) unless ref
authenticated(auth_strategy) do |http|
handle_response(http.get(rest_url(ref.rest_path))) do |data|
success(
Results::PageInfo.new(
identifier: input_data.identifier,
title: data["title"],
href: data["xwikiAbsoluteUrl"],
identifier: ref.to_s,
title: data.fetch("title"),
href: data.fetch("xwikiAbsoluteUrl"),
provider:
)
)
@@ -61,7 +61,7 @@ module Wikis
namespace("queries") do
register(:user, Queries::User)
register(:page_info, Queries::PageInfo)
register(:page_info, Queries::StablePageInfo)
register(:referencing_pages, Queries::ReferencingPages)
register(:relation_page_links, Queries::RelationPageLinks)
register(:search_pages, Queries::SearchPages)
@@ -0,0 +1,60 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
module Wikis
module Adapters
module Providers
module XWiki
# Represents an XWiki page identifier using the "stable" page identifier format: e.g. 0b89a
StablePageReference = Data.define(:uid) do
class << self
private :new
def parse(uid)
return nil if uid.nil?
new(uid:)
end
end
# Maps the reference to the REST API path, excluding the `/rest` prefix, e.g.
# /openproject/documents/0b89a
def rest_path
"/openproject/documents/#{CGI.escapeURIComponent(uid)}"
end
def to_s
uid
end
end
end
end
end
end
@@ -168,10 +168,10 @@ RSpec.describe "API v3 wiki page links resource", content_type: :json do
def stub_provider_queries
internal_class = class_double(Wikis::Adapters::Providers::Internal::Queries::PageInfo)
xwiki_class = class_double(Wikis::Adapters::Providers::XWiki::Queries::PageInfo)
xwiki_class = class_double(Wikis::Adapters::Providers::XWiki::Queries::StablePageInfo)
internal_query = instance_double(Wikis::Adapters::Providers::Internal::Queries::PageInfo)
xwiki_query = instance_double(Wikis::Adapters::Providers::XWiki::Queries::PageInfo)
xwiki_query = instance_double(Wikis::Adapters::Providers::XWiki::Queries::StablePageInfo)
Wikis::Adapters::Registry.stub("internal.queries.page_info", internal_class)
Wikis::Adapters::Registry.stub("xwiki.queries.page_info", xwiki_class)
@@ -87,4 +87,24 @@ RSpec.describe Wikis::Adapters::Providers::XWiki::CanonicalPageReference do
it { is_expected.to eq("/wikis/xwiki/spaces/My%20Space/pages/My%20Page") }
end
end
describe "#to_s" do
subject { described_class.parse(identifier).to_s }
context "with a standard identifier" do
let(:identifier) { "xwiki:Main.WebHome" }
it "roundtrips" do
expect(subject).to eq(identifier)
end
end
context "with a nested space identifier" do
let(:identifier) { "xwiki:MySpace.SubSpace.PageName" }
it "roundtrips" do
expect(subject).to eq(identifier)
end
end
end
end
@@ -31,52 +31,46 @@
require "spec_helper"
require_module_spec_helper
RSpec.describe Wikis::Adapters::Providers::XWiki::Queries::PageInfo, :webmock do
it "is registered" do
expect(Wikis::Adapters::Registry.resolve("xwiki.queries.page_info")).to eq(described_class)
RSpec.describe Wikis::Adapters::Providers::XWiki::Queries::CanonicalPageInfo, :webmock do
it "is not registered" do
expect(Wikis::Adapters::Registry.resolve("xwiki.queries.page_info")).not_to eq(described_class)
end
describe "#call" do
let(:user) { create(:user) }
let(:wiki_provider) { create(:xwiki_provider, :with_connected_user, url: "https://xwiki.example.com/", connected_user: user) }
let(:wiki_provider) { create(:xwiki_provider, :for_local_connection, connected_user: user) }
let(:identifier) { "xwiki:Main.WebHome" }
let(:page_url) { "https://xwiki.example.com/rest/wikis/xwiki/spaces/Main/pages/WebHome" }
let(:page_url) { "https://xwiki.local/rest/openproject/documents?docRef=xwiki:Main.WebHome" }
let(:auth_strategy) { Wikis::Adapters::Input::AuthStrategy.build(key: :bearer_token, user:, provider: wiki_provider).value! }
let(:input_data) { Wikis::Adapters::Input::PageInfo.build(identifier:).value! }
let(:query) { described_class.new(model: wiki_provider) }
subject(:result) { query.call(input_data:, auth_strategy:) }
context "when the page exists" do
let(:page_response) do
{ "title" => "Home", "xwikiAbsoluteUrl" => "https://xwiki.example.com/bin/view/Main/" }.to_json
end
before do
stub_request(:get, page_url)
.with(headers: { "Authorization" => "Bearer user-bearer-token" })
.to_return(status: 200, body: page_response, headers: { "Content-Type" => "application/json" })
end
context "when the page exists", vcr: "xwiki/canonical_page_info" do
# Set the expected identifier according to the stable identifier returned by XWiki (or update the VCR cassette accordingly)
let(:expected_identifier) { "484f4" }
it "returns Success with title and href" do
expect(result).to be_success
expect(result.value!).to have_attributes(
identifier:,
identifier: expected_identifier,
title: "Home",
href: "https://xwiki.example.com/bin/view/Main/"
href: "https://xwiki.local/bin/view/Main/"
)
end
end
context "with a nested space identifier" do
let(:identifier) { "xwiki:MySpace.SubSpace.PageName" }
let(:page_url) { "https://xwiki.example.com/rest/wikis/xwiki/spaces/MySpace/spaces/SubSpace/pages/PageName" }
let(:absolute_url) { "https://xwiki.example.com/bin/view/MySpace/SubSpace/PageName" }
let(:page_url) do
"https://xwiki.local/rest/openproject/documents?docRef=xwiki:MySpace.SubSpace.PageName"
end
let(:absolute_url) { "https://xwiki.local/bin/view/MySpace/SubSpace/PageName" }
before do
stub_request(:get, page_url)
.to_return(status: 200, body: { "title" => "Nested Page",
"xwikiAbsoluteUrl" => absolute_url }.to_json,
stub_request(:put, page_url)
.to_return(status: 200, body: { id: "foo", title: "Nested Page", xwikiAbsoluteUrl: absolute_url }.to_json,
headers: { "Content-Type" => "application/json" })
end
@@ -93,44 +87,44 @@ RSpec.describe Wikis::Adapters::Providers::XWiki::Queries::PageInfo, :webmock do
end
context "when no OAuth token exists for the user" do
let(:wiki_provider) { create(:xwiki_provider, :with_oauth_client, url: "https://xwiki.example.com/") }
let(:wiki_provider) { create(:xwiki_provider, :with_oauth_client, url: "https://xwiki.local/") }
it { is_expected.to be_failure.and have_attributes(failure: have_attributes(code: :missing_token)) }
end
context "when the page is not found" do
before { stub_request(:get, page_url).to_return(status: 404, body: "") }
before { stub_request(:put, page_url).to_return(status: 404, body: "") }
it { is_expected.to be_failure.and have_attributes(failure: have_attributes(code: :not_found)) }
end
context "when access is unauthorized" do
before { stub_request(:get, page_url).to_return(status: 401, body: "") }
before { stub_request(:put, page_url).to_return(status: 401, body: "") }
it { is_expected.to be_failure.and have_attributes(failure: have_attributes(code: :unauthorized)) }
end
context "when access is forbidden" do
before { stub_request(:get, page_url).to_return(status: 403, body: "") }
before { stub_request(:put, page_url).to_return(status: 403, body: "") }
it { is_expected.to be_failure.and have_attributes(failure: have_attributes(code: :unauthorized)) }
end
context "when XWiki returns a non-2xx status" do
before { stub_request(:get, page_url).to_return(status: 500, body: "Internal Server Error") }
before { stub_request(:put, page_url).to_return(status: 500, body: "Internal Server Error") }
it { is_expected.to be_failure.and have_attributes(failure: have_attributes(code: :request_failed)) }
end
context "when a network error occurs" do
before { stub_request(:get, page_url).to_timeout }
before { stub_request(:put, page_url).to_timeout }
it { is_expected.to be_failure.and have_attributes(failure: have_attributes(code: :connection_error)) }
end
context "when the response body is not valid JSON" do
before do
stub_request(:get, page_url)
stub_request(:put, page_url)
.to_return(status: 200, body: "not json", headers: { "Content-Type" => "application/json" })
end
@@ -53,6 +53,13 @@ RSpec.describe Wikis::Adapters::Providers::XWiki::Queries::SearchPages, :disable
expect(subject.value!.first.title).to eq("Test Page for RSpec")
end
it "returns a complete PageInfo result" do
page_info = subject.value!.first
page_info.to_h.each do |attribute, value|
expect(value).not_to be_nil, "#{attribute} was expected to be non-nil, but was nil"
end
end
it "returns no other random results" do
expect(subject.value!.count).to eq(1)
end
@@ -0,0 +1,110 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
require "spec_helper"
require_module_spec_helper
RSpec.describe Wikis::Adapters::Providers::XWiki::Queries::StablePageInfo, :webmock do
it "is registered" do
expect(Wikis::Adapters::Registry.resolve("xwiki.queries.page_info")).to eq(described_class)
end
describe "#call" do
let(:user) { create(:user) }
let(:wiki_provider) { create(:xwiki_provider, :for_local_connection, connected_user: user) }
let(:identifier) { "123abc" }
let(:page_url) { "https://xwiki.local/rest/openproject/documents/123abc" }
let(:auth_strategy) { Wikis::Adapters::Input::AuthStrategy.build(key: :bearer_token, user:, provider: wiki_provider).value! }
let(:input_data) { Wikis::Adapters::Input::PageInfo.build(identifier:).value! }
let(:query) { described_class.new(model: wiki_provider) }
subject(:result) { query.call(input_data:, auth_strategy:) }
context "when the page exists", vcr: "xwiki/stable_page_info" do
# Before recording cassette make sure a wiki page with title "Test Page for RSpec" exists
# Set the according identifier of that test page below
let(:identifier) { "d70f1" }
it "returns Success with title and href" do
expect(result).to be_success
expect(result.value!).to have_attributes(
identifier: "d70f1",
title: "Test Page for RSpec",
href: "https://xwiki.local/bin/view/Test%20Page/"
)
end
end
context "when no OAuth token exists for the user" do
let(:wiki_provider) { create(:xwiki_provider, :with_oauth_client, url: "https://xwiki.local/") }
it { is_expected.to be_failure.and have_attributes(failure: have_attributes(code: :missing_token)) }
end
context "when the page is not found" do
before { stub_request(:get, page_url).to_return(status: 404, body: "") }
it { is_expected.to be_failure.and have_attributes(failure: have_attributes(code: :not_found)) }
end
context "when access is unauthorized" do
before { stub_request(:get, page_url).to_return(status: 401, body: "") }
it { is_expected.to be_failure.and have_attributes(failure: have_attributes(code: :unauthorized)) }
end
context "when access is forbidden" do
before { stub_request(:get, page_url).to_return(status: 403, body: "") }
it { is_expected.to be_failure.and have_attributes(failure: have_attributes(code: :unauthorized)) }
end
context "when XWiki returns a non-2xx status" do
before { stub_request(:get, page_url).to_return(status: 500, body: "Internal Server Error") }
it { is_expected.to be_failure.and have_attributes(failure: have_attributes(code: :request_failed)) }
end
context "when a network error occurs" do
before { stub_request(:get, page_url).to_timeout }
it { is_expected.to be_failure.and have_attributes(failure: have_attributes(code: :connection_error)) }
end
context "when the response body is not valid JSON" do
before do
stub_request(:get, page_url)
.to_return(status: 200, body: "not json", headers: { "Content-Type" => "application/json" })
end
it { is_expected.to be_failure.and have_attributes(failure: have_attributes(code: :invalid_response)) }
end
end
end
@@ -0,0 +1,66 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
require "spec_helper"
require_module_spec_helper
RSpec.describe Wikis::Adapters::Providers::XWiki::StablePageReference do
describe ".parse" do
subject { described_class.parse(identifier) }
let(:identifier) { "123abc" }
it { is_expected.to have_attributes(uid: "123abc") }
context "when passing nil" do
let(:identifier) { nil }
it { is_expected.to be_nil }
end
end
describe "#rest_path" do
subject { described_class.parse(identifier).rest_path }
let(:identifier) { "123abc" }
it { is_expected.to eq("/openproject/documents/123abc") }
end
describe "#to_s" do
subject { described_class.parse(identifier).to_s }
let(:identifier) { "123abc" }
it "roundtrips" do
expect(subject).to eq(identifier)
end
end
end
File diff suppressed because one or more lines are too long
@@ -27,29 +27,29 @@ http_interactions:
Content-Type:
- application/json;charset=UTF-8
Date:
- Tue, 02 Jun 2026 08:17:22 GMT
- Fri, 05 Jun 2026 06:39:19 GMT
Set-Cookie:
- JSESSIONID=A90934AE8F68AA76D0E0970863A314F8; Path=/; HttpOnly
- JSESSIONID=EF2A09F6E0681B4B0B3E44D639CB89D9; Path=/; HttpOnly
Xwiki-Form-Token:
- 2XZUUfWArYhRgLYx4nHjhQ
- ON8xsHlEpixyujzpUPNupg
Xwiki-User:
- xwiki:XWiki.admin
Xwiki-Version:
- 18.3.0
Content-Length:
- '790'
- '789'
body:
encoding: UTF-8
string: '{"links":[],"searchResults":[{"links":[{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/Test%20Page/pages/WebHome","rel":"http://www.xwiki.org/rel/page","type":null,"hrefLang":null}],"type":"page","id":"xwiki:Test
Page.WebHome","pageFullName":"Test Page.WebHome","title":"Test Page for RSpec","wiki":"xwiki","space":"Test
Page","pageName":"WebHome","modified":1780386902000,"author":"xwiki:XWiki.admin","authorName":null,"version":"4.1","language":null,"className":null,"objectNumber":null,"filename":null,"score":30.283539,"object":null,"hierarchy":null}],"template":"https://xwiki.local/rest/?q={solrquery}(&number={number})(&start={start})(&orderField={fieldname}(&order={asc|desc}))(&distinct=1)(&prettyNames={false|true})(&wikis={wikis})(&className={classname})"}'
recorded_at: Tue, 02 Jun 2026 08:17:22 GMT
Page","pageName":"WebHome","modified":1780386902000,"author":"xwiki:XWiki.admin","authorName":null,"version":"4.1","language":null,"className":null,"objectNumber":null,"filename":null,"score":32.03692,"object":null,"hierarchy":null}],"template":"https://xwiki.local/rest/?q={solrquery}(&number={number})(&start={start})(&orderField={fieldname}(&order={asc|desc}))(&distinct=1)(&prettyNames={false|true})(&wikis={wikis})(&className={classname})"}'
recorded_at: Fri, 05 Jun 2026 06:39:19 GMT
- request:
method: get
uri: https://xwiki.local/rest/wikis/xwiki/spaces/Test%20Page/pages/WebHome
method: put
uri: https://xwiki.local/rest/openproject/documents?docRef=xwiki:Test%20Page.WebHome
body:
encoding: US-ASCII
string: ''
encoding: UTF-8
string: "{}"
headers:
User-Agent:
- OpenProject 17.6.0 HTTPX Client
@@ -57,12 +57,16 @@ http_interactions:
- application/json
Accept-Encoding:
- gzip, deflate
Content-Type:
- application/json
Content-Length:
- '2'
Authorization:
- Bearer <SECRET>
response:
status:
code: 200
message: OK
code: 202
message: Accepted
headers:
Content-Language:
- en
@@ -71,24 +75,24 @@ http_interactions:
Content-Type:
- application/json;charset=UTF-8
Date:
- Tue, 02 Jun 2026 08:17:22 GMT
- Fri, 05 Jun 2026 06:39:19 GMT
Set-Cookie:
- JSESSIONID=6D38F35499AE562F0EEE91795F9951CF; Path=/; HttpOnly
- JSESSIONID=CD75D58F42FA2FF29480F0AA679975CB; Path=/; HttpOnly
Xwiki-Form-Token:
- 2XZUUfWArYhRgLYx4nHjhQ
- ON8xsHlEpixyujzpUPNupg
Xwiki-User:
- xwiki:XWiki.admin
Xwiki-Version:
- 18.3.0
Content-Length:
- '2224'
- '2372'
body:
encoding: UTF-8
string: '{"links":[{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/Test%20Page","rel":"http://www.xwiki.org/rel/space","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/Test%20Page/pages/WebHome","rel":"http://www.xwiki.org/rel/parent","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/Test%20Page/pages/WebHome/history","rel":"http://www.xwiki.org/rel/history","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/syntaxes","rel":"http://www.xwiki.org/rel/syntaxes","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/Test%20Page/pages/WebHome","rel":"self","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/classes/Test%20Page.WebHome","rel":"http://www.xwiki.org/rel/class","type":null,"hrefLang":null}],"id":"xwiki:Test
Page.WebHome","fullName":"Test Page.WebHome","wiki":"xwiki","space":"Test
Page","name":"WebHome","title":"Test Page for RSpec","rawTitle":"Test Page
for RSpec","parent":"Main.WebHome","parentId":"xwiki:Main.WebHome","version":"4.1","author":"XWiki.admin","authorName":null,"xwikiRelativeUrl":"https://xwiki.local/bin/view/Test%20Page/","xwikiAbsoluteUrl":"https://xwiki.local/bin/view/Test%20Page/","translations":{"links":[],"translations":[],"default":"en"},"syntax":"xwiki/2.1","language":"","majorVersion":4,"minorVersion":1,"hidden":false,"enforceRequiredRights":false,"created":1780383689000,"creator":"XWiki.admin","creatorName":null,"modified":1780386902000,"modifier":"XWiki.admin","modifierName":null,"originalMetadataAuthor":"xwiki:XWiki.admin","originalMetadataAuthorName":null,"comment":"","content":"This
is a test page that I created with my own hands.","clazz":null,"objects":null,"attachments":null,"hierarchy":{"items":[{"label":"xwiki","name":"xwiki","type":"wiki","url":"https://xwiki.local/bin/view/Main/"},{"label":"Test
string: '{"links":[{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/Test%20Page","rel":"http://www.xwiki.org/rel/space","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/Test%20Page/pages/WebHome","rel":"http://www.xwiki.org/rel/parent","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/Test%20Page/pages/WebHome/history","rel":"http://www.xwiki.org/rel/history","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/Test%20Page/pages/WebHome/objects","rel":"http://www.xwiki.org/rel/objects","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/syntaxes","rel":"http://www.xwiki.org/rel/syntaxes","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/openproject/documents","rel":"self","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/classes/Test%20Page.WebHome","rel":"http://www.xwiki.org/rel/class","type":null,"hrefLang":null}],"id":"d70f1","fullName":"Test
Page.WebHome","wiki":"xwiki","space":"Test Page","name":"WebHome","title":"Test
Page for RSpec","rawTitle":"Test Page for RSpec","parent":"Main.WebHome","parentId":"xwiki:Main.WebHome","version":"4.1","author":"XWiki.admin","authorName":null,"xwikiRelativeUrl":"https://xwiki.local/bin/view/Test%20Page/","xwikiAbsoluteUrl":"https://xwiki.local/bin/view/Test%20Page/","translations":{"links":[],"translations":[],"default":"en"},"syntax":"xwiki/2.1","language":"","majorVersion":4,"minorVersion":1,"hidden":false,"enforceRequiredRights":false,"created":1780383689000,"creator":"XWiki.admin","creatorName":null,"modified":1780386902000,"modifier":"XWiki.admin","modifierName":null,"originalMetadataAuthor":"xwiki:XWiki.admin","originalMetadataAuthorName":null,"comment":"Created
URL Shortener.","content":"This is a test page that I created with my own
hands.","clazz":null,"objects":null,"attachments":null,"hierarchy":{"items":[{"label":"xwiki","name":"xwiki","type":"wiki","url":"https://xwiki.local/bin/view/Main/"},{"label":"Test
Page","name":"Test Page","type":"space","url":"https://xwiki.local/bin/view/Test%20Page/"},{"label":"WebHome","name":"WebHome","type":"document","url":"https://xwiki.local/bin/view/Test%20Page/"}]},"rights":[],"renderedContent":null}'
recorded_at: Tue, 02 Jun 2026 08:17:22 GMT
recorded_at: Fri, 05 Jun 2026 06:39:19 GMT
recorded_with: VCR 6.4.0
@@ -27,11 +27,11 @@ http_interactions:
Content-Type:
- application/json;charset=UTF-8
Date:
- Tue, 02 Jun 2026 08:17:23 GMT
- Fri, 05 Jun 2026 06:39:20 GMT
Set-Cookie:
- JSESSIONID=9D417B4F0A9D4C117C903A54394DAD6C; Path=/; HttpOnly
- JSESSIONID=D1B7C7CFA5520362BCB9E2DB63EFCE00; Path=/; HttpOnly
Xwiki-Form-Token:
- 2XZUUfWArYhRgLYx4nHjhQ
- ON8xsHlEpixyujzpUPNupg
Xwiki-User:
- xwiki:XWiki.admin
Xwiki-Version:
@@ -41,5 +41,5 @@ http_interactions:
body:
encoding: UTF-8
string: '{"links":[],"searchResults":[],"template":"https://xwiki.local/rest/?q={solrquery}(&number={number})(&start={start})(&orderField={fieldname}(&order={asc|desc}))(&distinct=1)(&prettyNames={false|true})(&wikis={wikis})(&className={classname})"}'
recorded_at: Tue, 02 Jun 2026 08:17:23 GMT
recorded_at: Fri, 05 Jun 2026 06:39:20 GMT
recorded_with: VCR 6.4.0
@@ -27,11 +27,11 @@ http_interactions:
Content-Type:
- application/json;charset=UTF-8
Date:
- Tue, 02 Jun 2026 08:17:22 GMT
- Fri, 05 Jun 2026 06:39:19 GMT
Set-Cookie:
- JSESSIONID=4570EBB986F92482503F494102024098; Path=/; HttpOnly
- JSESSIONID=689FB3235B4E5A8C46683A1331BD9EB2; Path=/; HttpOnly
Xwiki-Form-Token:
- 2XZUUfWArYhRgLYx4nHjhQ
- ON8xsHlEpixyujzpUPNupg
Xwiki-User:
- xwiki:XWiki.admin
Xwiki-Version:
@@ -42,14 +42,14 @@ http_interactions:
encoding: UTF-8
string: '{"links":[],"searchResults":[{"links":[{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/Test%20Page/pages/WebHome","rel":"http://www.xwiki.org/rel/page","type":null,"hrefLang":null}],"type":"page","id":"xwiki:Test
Page.WebHome","pageFullName":"Test Page.WebHome","title":"Test Page for RSpec","wiki":"xwiki","space":"Test
Page","pageName":"WebHome","modified":1780386902000,"author":"xwiki:XWiki.admin","authorName":null,"version":"4.1","language":null,"className":null,"objectNumber":null,"filename":null,"score":14.608791,"object":null,"hierarchy":null}],"template":"https://xwiki.local/rest/?q={solrquery}(&number={number})(&start={start})(&orderField={fieldname}(&order={asc|desc}))(&distinct=1)(&prettyNames={false|true})(&wikis={wikis})(&className={classname})"}'
recorded_at: Tue, 02 Jun 2026 08:17:22 GMT
Page","pageName":"WebHome","modified":1780386902000,"author":"xwiki:XWiki.admin","authorName":null,"version":"4.1","language":null,"className":null,"objectNumber":null,"filename":null,"score":14.085169,"object":null,"hierarchy":null}],"template":"https://xwiki.local/rest/?q={solrquery}(&number={number})(&start={start})(&orderField={fieldname}(&order={asc|desc}))(&distinct=1)(&prettyNames={false|true})(&wikis={wikis})(&className={classname})"}'
recorded_at: Fri, 05 Jun 2026 06:39:19 GMT
- request:
method: get
uri: https://xwiki.local/rest/wikis/xwiki/spaces/Test%20Page/pages/WebHome
method: put
uri: https://xwiki.local/rest/openproject/documents?docRef=xwiki:Test%20Page.WebHome
body:
encoding: US-ASCII
string: ''
encoding: UTF-8
string: "{}"
headers:
User-Agent:
- OpenProject 17.6.0 HTTPX Client
@@ -57,12 +57,16 @@ http_interactions:
- application/json
Accept-Encoding:
- gzip, deflate
Content-Type:
- application/json
Content-Length:
- '2'
Authorization:
- Bearer <SECRET>
response:
status:
code: 200
message: OK
code: 202
message: Accepted
headers:
Content-Language:
- en
@@ -71,24 +75,24 @@ http_interactions:
Content-Type:
- application/json;charset=UTF-8
Date:
- Tue, 02 Jun 2026 08:17:22 GMT
- Fri, 05 Jun 2026 06:39:19 GMT
Set-Cookie:
- JSESSIONID=36828A84C85C858E144AA581B1A1F138; Path=/; HttpOnly
- JSESSIONID=41BB94B7774F3AAF5872EC50FF78C37B; Path=/; HttpOnly
Xwiki-Form-Token:
- 2XZUUfWArYhRgLYx4nHjhQ
- ON8xsHlEpixyujzpUPNupg
Xwiki-User:
- xwiki:XWiki.admin
Xwiki-Version:
- 18.3.0
Content-Length:
- '2224'
- '2372'
body:
encoding: UTF-8
string: '{"links":[{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/Test%20Page","rel":"http://www.xwiki.org/rel/space","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/Test%20Page/pages/WebHome","rel":"http://www.xwiki.org/rel/parent","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/Test%20Page/pages/WebHome/history","rel":"http://www.xwiki.org/rel/history","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/syntaxes","rel":"http://www.xwiki.org/rel/syntaxes","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/Test%20Page/pages/WebHome","rel":"self","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/classes/Test%20Page.WebHome","rel":"http://www.xwiki.org/rel/class","type":null,"hrefLang":null}],"id":"xwiki:Test
Page.WebHome","fullName":"Test Page.WebHome","wiki":"xwiki","space":"Test
Page","name":"WebHome","title":"Test Page for RSpec","rawTitle":"Test Page
for RSpec","parent":"Main.WebHome","parentId":"xwiki:Main.WebHome","version":"4.1","author":"XWiki.admin","authorName":null,"xwikiRelativeUrl":"https://xwiki.local/bin/view/Test%20Page/","xwikiAbsoluteUrl":"https://xwiki.local/bin/view/Test%20Page/","translations":{"links":[],"translations":[],"default":"en"},"syntax":"xwiki/2.1","language":"","majorVersion":4,"minorVersion":1,"hidden":false,"enforceRequiredRights":false,"created":1780383689000,"creator":"XWiki.admin","creatorName":null,"modified":1780386902000,"modifier":"XWiki.admin","modifierName":null,"originalMetadataAuthor":"xwiki:XWiki.admin","originalMetadataAuthorName":null,"comment":"","content":"This
is a test page that I created with my own hands.","clazz":null,"objects":null,"attachments":null,"hierarchy":{"items":[{"label":"xwiki","name":"xwiki","type":"wiki","url":"https://xwiki.local/bin/view/Main/"},{"label":"Test
string: '{"links":[{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/Test%20Page","rel":"http://www.xwiki.org/rel/space","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/Test%20Page/pages/WebHome","rel":"http://www.xwiki.org/rel/parent","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/Test%20Page/pages/WebHome/history","rel":"http://www.xwiki.org/rel/history","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/Test%20Page/pages/WebHome/objects","rel":"http://www.xwiki.org/rel/objects","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/syntaxes","rel":"http://www.xwiki.org/rel/syntaxes","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/openproject/documents","rel":"self","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/classes/Test%20Page.WebHome","rel":"http://www.xwiki.org/rel/class","type":null,"hrefLang":null}],"id":"d70f1","fullName":"Test
Page.WebHome","wiki":"xwiki","space":"Test Page","name":"WebHome","title":"Test
Page for RSpec","rawTitle":"Test Page for RSpec","parent":"Main.WebHome","parentId":"xwiki:Main.WebHome","version":"4.1","author":"XWiki.admin","authorName":null,"xwikiRelativeUrl":"https://xwiki.local/bin/view/Test%20Page/","xwikiAbsoluteUrl":"https://xwiki.local/bin/view/Test%20Page/","translations":{"links":[],"translations":[],"default":"en"},"syntax":"xwiki/2.1","language":"","majorVersion":4,"minorVersion":1,"hidden":false,"enforceRequiredRights":false,"created":1780383689000,"creator":"XWiki.admin","creatorName":null,"modified":1780386902000,"modifier":"XWiki.admin","modifierName":null,"originalMetadataAuthor":"xwiki:XWiki.admin","originalMetadataAuthorName":null,"comment":"Created
URL Shortener.","content":"This is a test page that I created with my own
hands.","clazz":null,"objects":null,"attachments":null,"hierarchy":{"items":[{"label":"xwiki","name":"xwiki","type":"wiki","url":"https://xwiki.local/bin/view/Main/"},{"label":"Test
Page","name":"Test Page","type":"space","url":"https://xwiki.local/bin/view/Test%20Page/"},{"label":"WebHome","name":"WebHome","type":"document","url":"https://xwiki.local/bin/view/Test%20Page/"}]},"rights":[],"renderedContent":null}'
recorded_at: Tue, 02 Jun 2026 08:17:22 GMT
recorded_at: Fri, 05 Jun 2026 06:39:19 GMT
recorded_with: VCR 6.4.0
@@ -27,11 +27,11 @@ http_interactions:
Content-Type:
- application/json;charset=UTF-8
Date:
- Tue, 02 Jun 2026 08:17:22 GMT
- Fri, 05 Jun 2026 06:39:20 GMT
Set-Cookie:
- JSESSIONID=C28E0999BF663CA702569EE1C5C696E2; Path=/; HttpOnly
- JSESSIONID=A1B5B0EFF5FD5E7B4F6E4CB0D185B065; Path=/; HttpOnly
Xwiki-Form-Token:
- 2XZUUfWArYhRgLYx4nHjhQ
- ON8xsHlEpixyujzpUPNupg
Xwiki-User:
- xwiki:XWiki.admin
Xwiki-Version:
@@ -42,14 +42,14 @@ http_interactions:
encoding: UTF-8
string: '{"links":[],"searchResults":[{"links":[{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/%22Quoted%22%20pages%20can%20be%20tricky/pages/WebHome","rel":"http://www.xwiki.org/rel/page","type":null,"hrefLang":null}],"type":"page","id":"xwiki:\"Quoted\"
pages can be tricky.WebHome","pageFullName":"\"Quoted\" pages can be tricky.WebHome","title":"\"Quoted\"
pages can be tricky","wiki":"xwiki","space":"\"Quoted\" pages can be tricky","pageName":"WebHome","modified":1780387197000,"author":"xwiki:XWiki.admin","authorName":null,"version":"1.1","language":null,"className":null,"objectNumber":null,"filename":null,"score":42.605682,"object":null,"hierarchy":null}],"template":"https://xwiki.local/rest/?q={solrquery}(&number={number})(&start={start})(&orderField={fieldname}(&order={asc|desc}))(&distinct=1)(&prettyNames={false|true})(&wikis={wikis})(&className={classname})"}'
recorded_at: Tue, 02 Jun 2026 08:17:22 GMT
pages can be tricky","wiki":"xwiki","space":"\"Quoted\" pages can be tricky","pageName":"WebHome","modified":1780387197000,"author":"xwiki:XWiki.admin","authorName":null,"version":"1.1","language":null,"className":null,"objectNumber":null,"filename":null,"score":41.692856,"object":null,"hierarchy":null}],"template":"https://xwiki.local/rest/?q={solrquery}(&number={number})(&start={start})(&orderField={fieldname}(&order={asc|desc}))(&distinct=1)(&prettyNames={false|true})(&wikis={wikis})(&className={classname})"}'
recorded_at: Fri, 05 Jun 2026 06:39:20 GMT
- request:
method: get
uri: https://xwiki.local/rest/wikis/xwiki/spaces/%22Quoted%22%20pages%20can%20be%20tricky/pages/WebHome
method: put
uri: https://xwiki.local/rest/openproject/documents?docRef=xwiki:%22Quoted%22%20pages%20can%20be%20tricky.WebHome
body:
encoding: US-ASCII
string: ''
encoding: UTF-8
string: "{}"
headers:
User-Agent:
- OpenProject 17.6.0 HTTPX Client
@@ -57,12 +57,16 @@ http_interactions:
- application/json
Accept-Encoding:
- gzip, deflate
Content-Type:
- application/json
Content-Length:
- '2'
Authorization:
- Bearer <SECRET>
response:
status:
code: 200
message: OK
code: 202
message: Accepted
headers:
Content-Language:
- en
@@ -71,24 +75,25 @@ http_interactions:
Content-Type:
- application/json;charset=UTF-8
Date:
- Tue, 02 Jun 2026 08:17:22 GMT
- Fri, 05 Jun 2026 06:39:20 GMT
Set-Cookie:
- JSESSIONID=EC142E0079C91196143B051273FDA2FD; Path=/; HttpOnly
- JSESSIONID=9F577E6A3744F626EDDD3668B5F9EE9D; Path=/; HttpOnly
Xwiki-Form-Token:
- 2XZUUfWArYhRgLYx4nHjhQ
- ON8xsHlEpixyujzpUPNupg
Xwiki-User:
- xwiki:XWiki.admin
Xwiki-Version:
- 18.3.0
Content-Length:
- '2642'
- '2769'
body:
encoding: UTF-8
string: '{"links":[{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/%22Quoted%22%20pages%20can%20be%20tricky","rel":"http://www.xwiki.org/rel/space","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/%22Quoted%22%20pages%20can%20be%20tricky/pages/WebHome","rel":"http://www.xwiki.org/rel/parent","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/%22Quoted%22%20pages%20can%20be%20tricky/pages/WebHome/history","rel":"http://www.xwiki.org/rel/history","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/syntaxes","rel":"http://www.xwiki.org/rel/syntaxes","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/%22Quoted%22%20pages%20can%20be%20tricky/pages/WebHome","rel":"self","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/classes/%22Quoted%22%20pages%20can%20be%20tricky.WebHome","rel":"http://www.xwiki.org/rel/class","type":null,"hrefLang":null}],"id":"xwiki:\"Quoted\"
pages can be tricky.WebHome","fullName":"\"Quoted\" pages can be tricky.WebHome","wiki":"xwiki","space":"\"Quoted\"
pages can be tricky","name":"WebHome","title":"\"Quoted\" pages can be tricky","rawTitle":"\"Quoted\"
pages can be tricky","parent":"Main.WebHome","parentId":"xwiki:Main.WebHome","version":"1.1","author":"XWiki.admin","authorName":null,"xwikiRelativeUrl":"https://xwiki.local/bin/view/%22Quoted%22%20pages%20can%20be%20tricky/","xwikiAbsoluteUrl":"https://xwiki.local/bin/view/%22Quoted%22%20pages%20can%20be%20tricky/","translations":{"links":[],"translations":[],"default":"en"},"syntax":"xwiki/2.1","language":"","majorVersion":1,"minorVersion":1,"hidden":false,"enforceRequiredRights":false,"created":1780387197000,"creator":"XWiki.admin","creatorName":null,"modified":1780387197000,"modifier":"XWiki.admin","modifierName":null,"originalMetadataAuthor":"xwiki:XWiki.admin","originalMetadataAuthorName":null,"comment":"","content":"When
the page title contains quotes, it''s harder to exactly match their page title.","clazz":null,"objects":null,"attachments":null,"hierarchy":{"items":[{"label":"xwiki","name":"xwiki","type":"wiki","url":"https://xwiki.local/bin/view/Main/"},{"label":"\"Quoted\"
string: '{"links":[{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/%22Quoted%22%20pages%20can%20be%20tricky","rel":"http://www.xwiki.org/rel/space","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/%22Quoted%22%20pages%20can%20be%20tricky/pages/WebHome","rel":"http://www.xwiki.org/rel/parent","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/%22Quoted%22%20pages%20can%20be%20tricky/pages/WebHome/history","rel":"http://www.xwiki.org/rel/history","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/%22Quoted%22%20pages%20can%20be%20tricky/pages/WebHome/objects","rel":"http://www.xwiki.org/rel/objects","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/syntaxes","rel":"http://www.xwiki.org/rel/syntaxes","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/openproject/documents","rel":"self","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/classes/%22Quoted%22%20pages%20can%20be%20tricky.WebHome","rel":"http://www.xwiki.org/rel/class","type":null,"hrefLang":null}],"id":"1a013","fullName":"\"Quoted\"
pages can be tricky.WebHome","wiki":"xwiki","space":"\"Quoted\" pages can
be tricky","name":"WebHome","title":"\"Quoted\" pages can be tricky","rawTitle":"\"Quoted\"
pages can be tricky","parent":"Main.WebHome","parentId":"xwiki:Main.WebHome","version":"1.1","author":"XWiki.admin","authorName":null,"xwikiRelativeUrl":"https://xwiki.local/bin/view/%22Quoted%22%20pages%20can%20be%20tricky/","xwikiAbsoluteUrl":"https://xwiki.local/bin/view/%22Quoted%22%20pages%20can%20be%20tricky/","translations":{"links":[],"translations":[],"default":"en"},"syntax":"xwiki/2.1","language":"","majorVersion":1,"minorVersion":1,"hidden":false,"enforceRequiredRights":false,"created":1780387197000,"creator":"XWiki.admin","creatorName":null,"modified":1780387197000,"modifier":"XWiki.admin","modifierName":null,"originalMetadataAuthor":"xwiki:XWiki.admin","originalMetadataAuthorName":null,"comment":"Created
URL Shortener.","content":"When the page title contains quotes, it''s harder
to exactly match their page title.","clazz":null,"objects":null,"attachments":null,"hierarchy":{"items":[{"label":"xwiki","name":"xwiki","type":"wiki","url":"https://xwiki.local/bin/view/Main/"},{"label":"\"Quoted\"
pages can be tricky","name":"\"Quoted\" pages can be tricky","type":"space","url":"https://xwiki.local/bin/view/%22Quoted%22%20pages%20can%20be%20tricky/"},{"label":"WebHome","name":"WebHome","type":"document","url":"https://xwiki.local/bin/view/%22Quoted%22%20pages%20can%20be%20tricky/"}]},"rights":[],"renderedContent":null}'
recorded_at: Tue, 02 Jun 2026 08:17:22 GMT
recorded_at: Fri, 05 Jun 2026 06:39:20 GMT
recorded_with: VCR 6.4.0
@@ -27,11 +27,11 @@ http_interactions:
Content-Type:
- application/json;charset=UTF-8
Date:
- Tue, 02 Jun 2026 08:17:23 GMT
- Fri, 05 Jun 2026 06:39:20 GMT
Set-Cookie:
- JSESSIONID=10D557C0A4C7D3C599B80C2FA01F5FF5; Path=/; HttpOnly
- JSESSIONID=B47446E1E06E6D2A73FC512CEAB8083D; Path=/; HttpOnly
Xwiki-Form-Token:
- 2XZUUfWArYhRgLYx4nHjhQ
- ON8xsHlEpixyujzpUPNupg
Xwiki-User:
- xwiki:XWiki.admin
Xwiki-Version:
@@ -42,14 +42,14 @@ http_interactions:
encoding: UTF-8
string: '{"links":[],"searchResults":[{"links":[{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/%22Quoted%22%20pages%20can%20be%20tricky/pages/WebHome","rel":"http://www.xwiki.org/rel/page","type":null,"hrefLang":null}],"type":"page","id":"xwiki:\"Quoted\"
pages can be tricky.WebHome","pageFullName":"\"Quoted\" pages can be tricky.WebHome","title":"\"Quoted\"
pages can be tricky","wiki":"xwiki","space":"\"Quoted\" pages can be tricky","pageName":"WebHome","modified":1780387197000,"author":"xwiki:XWiki.admin","authorName":null,"version":"1.1","language":null,"className":null,"objectNumber":null,"filename":null,"score":42.605682,"object":null,"hierarchy":null}],"template":"https://xwiki.local/rest/?q={solrquery}(&number={number})(&start={start})(&orderField={fieldname}(&order={asc|desc}))(&distinct=1)(&prettyNames={false|true})(&wikis={wikis})(&className={classname})"}'
recorded_at: Tue, 02 Jun 2026 08:17:23 GMT
pages can be tricky","wiki":"xwiki","space":"\"Quoted\" pages can be tricky","pageName":"WebHome","modified":1780387197000,"author":"xwiki:XWiki.admin","authorName":null,"version":"1.1","language":null,"className":null,"objectNumber":null,"filename":null,"score":41.692856,"object":null,"hierarchy":null}],"template":"https://xwiki.local/rest/?q={solrquery}(&number={number})(&start={start})(&orderField={fieldname}(&order={asc|desc}))(&distinct=1)(&prettyNames={false|true})(&wikis={wikis})(&className={classname})"}'
recorded_at: Fri, 05 Jun 2026 06:39:20 GMT
- request:
method: get
uri: https://xwiki.local/rest/wikis/xwiki/spaces/%22Quoted%22%20pages%20can%20be%20tricky/pages/WebHome
method: put
uri: https://xwiki.local/rest/openproject/documents?docRef=xwiki:%22Quoted%22%20pages%20can%20be%20tricky.WebHome
body:
encoding: US-ASCII
string: ''
encoding: UTF-8
string: "{}"
headers:
User-Agent:
- OpenProject 17.6.0 HTTPX Client
@@ -57,12 +57,16 @@ http_interactions:
- application/json
Accept-Encoding:
- gzip, deflate
Content-Type:
- application/json
Content-Length:
- '2'
Authorization:
- Bearer <SECRET>
response:
status:
code: 200
message: OK
code: 202
message: Accepted
headers:
Content-Language:
- en
@@ -71,24 +75,25 @@ http_interactions:
Content-Type:
- application/json;charset=UTF-8
Date:
- Tue, 02 Jun 2026 08:17:23 GMT
- Fri, 05 Jun 2026 06:39:20 GMT
Set-Cookie:
- JSESSIONID=85112D2673FA7F3B99AEC6BF0A182372; Path=/; HttpOnly
- JSESSIONID=2B1297828F8D8887496627F7356421D5; Path=/; HttpOnly
Xwiki-Form-Token:
- 2XZUUfWArYhRgLYx4nHjhQ
- ON8xsHlEpixyujzpUPNupg
Xwiki-User:
- xwiki:XWiki.admin
Xwiki-Version:
- 18.3.0
Content-Length:
- '2642'
- '2769'
body:
encoding: UTF-8
string: '{"links":[{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/%22Quoted%22%20pages%20can%20be%20tricky","rel":"http://www.xwiki.org/rel/space","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/%22Quoted%22%20pages%20can%20be%20tricky/pages/WebHome","rel":"http://www.xwiki.org/rel/parent","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/%22Quoted%22%20pages%20can%20be%20tricky/pages/WebHome/history","rel":"http://www.xwiki.org/rel/history","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/syntaxes","rel":"http://www.xwiki.org/rel/syntaxes","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/%22Quoted%22%20pages%20can%20be%20tricky/pages/WebHome","rel":"self","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/classes/%22Quoted%22%20pages%20can%20be%20tricky.WebHome","rel":"http://www.xwiki.org/rel/class","type":null,"hrefLang":null}],"id":"xwiki:\"Quoted\"
pages can be tricky.WebHome","fullName":"\"Quoted\" pages can be tricky.WebHome","wiki":"xwiki","space":"\"Quoted\"
pages can be tricky","name":"WebHome","title":"\"Quoted\" pages can be tricky","rawTitle":"\"Quoted\"
pages can be tricky","parent":"Main.WebHome","parentId":"xwiki:Main.WebHome","version":"1.1","author":"XWiki.admin","authorName":null,"xwikiRelativeUrl":"https://xwiki.local/bin/view/%22Quoted%22%20pages%20can%20be%20tricky/","xwikiAbsoluteUrl":"https://xwiki.local/bin/view/%22Quoted%22%20pages%20can%20be%20tricky/","translations":{"links":[],"translations":[],"default":"en"},"syntax":"xwiki/2.1","language":"","majorVersion":1,"minorVersion":1,"hidden":false,"enforceRequiredRights":false,"created":1780387197000,"creator":"XWiki.admin","creatorName":null,"modified":1780387197000,"modifier":"XWiki.admin","modifierName":null,"originalMetadataAuthor":"xwiki:XWiki.admin","originalMetadataAuthorName":null,"comment":"","content":"When
the page title contains quotes, it''s harder to exactly match their page title.","clazz":null,"objects":null,"attachments":null,"hierarchy":{"items":[{"label":"xwiki","name":"xwiki","type":"wiki","url":"https://xwiki.local/bin/view/Main/"},{"label":"\"Quoted\"
string: '{"links":[{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/%22Quoted%22%20pages%20can%20be%20tricky","rel":"http://www.xwiki.org/rel/space","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/%22Quoted%22%20pages%20can%20be%20tricky/pages/WebHome","rel":"http://www.xwiki.org/rel/parent","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/%22Quoted%22%20pages%20can%20be%20tricky/pages/WebHome/history","rel":"http://www.xwiki.org/rel/history","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/%22Quoted%22%20pages%20can%20be%20tricky/pages/WebHome/objects","rel":"http://www.xwiki.org/rel/objects","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/syntaxes","rel":"http://www.xwiki.org/rel/syntaxes","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/openproject/documents","rel":"self","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/classes/%22Quoted%22%20pages%20can%20be%20tricky.WebHome","rel":"http://www.xwiki.org/rel/class","type":null,"hrefLang":null}],"id":"1a013","fullName":"\"Quoted\"
pages can be tricky.WebHome","wiki":"xwiki","space":"\"Quoted\" pages can
be tricky","name":"WebHome","title":"\"Quoted\" pages can be tricky","rawTitle":"\"Quoted\"
pages can be tricky","parent":"Main.WebHome","parentId":"xwiki:Main.WebHome","version":"1.1","author":"XWiki.admin","authorName":null,"xwikiRelativeUrl":"https://xwiki.local/bin/view/%22Quoted%22%20pages%20can%20be%20tricky/","xwikiAbsoluteUrl":"https://xwiki.local/bin/view/%22Quoted%22%20pages%20can%20be%20tricky/","translations":{"links":[],"translations":[],"default":"en"},"syntax":"xwiki/2.1","language":"","majorVersion":1,"minorVersion":1,"hidden":false,"enforceRequiredRights":false,"created":1780387197000,"creator":"XWiki.admin","creatorName":null,"modified":1780387197000,"modifier":"XWiki.admin","modifierName":null,"originalMetadataAuthor":"xwiki:XWiki.admin","originalMetadataAuthorName":null,"comment":"Created
URL Shortener.","content":"When the page title contains quotes, it''s harder
to exactly match their page title.","clazz":null,"objects":null,"attachments":null,"hierarchy":{"items":[{"label":"xwiki","name":"xwiki","type":"wiki","url":"https://xwiki.local/bin/view/Main/"},{"label":"\"Quoted\"
pages can be tricky","name":"\"Quoted\" pages can be tricky","type":"space","url":"https://xwiki.local/bin/view/%22Quoted%22%20pages%20can%20be%20tricky/"},{"label":"WebHome","name":"WebHome","type":"document","url":"https://xwiki.local/bin/view/%22Quoted%22%20pages%20can%20be%20tricky/"}]},"rights":[],"renderedContent":null}'
recorded_at: Tue, 02 Jun 2026 08:17:23 GMT
recorded_at: Fri, 05 Jun 2026 06:39:20 GMT
recorded_with: VCR 6.4.0
@@ -0,0 +1,50 @@
---
http_interactions:
- request:
method: get
uri: https://xwiki.local/rest/openproject/documents/d70f1
body:
encoding: US-ASCII
string: ''
headers:
User-Agent:
- OpenProject 17.6.0 HTTPX Client
Accept:
- application/json
Accept-Encoding:
- gzip, deflate
Authorization:
- Bearer <SECRET>
response:
status:
code: 200
message: OK
headers:
Content-Language:
- en
Content-Script-Type:
- text/javascript
Content-Type:
- application/json;charset=UTF-8
Date:
- Fri, 05 Jun 2026 06:33:33 GMT
Set-Cookie:
- JSESSIONID=20FFAE29A62BFE6CEC0152BB7FC0ADB6; Path=/; HttpOnly
Xwiki-Form-Token:
- ON8xsHlEpixyujzpUPNupg
Xwiki-User:
- xwiki:XWiki.admin
Xwiki-Version:
- 18.3.0
Content-Length:
- '2378'
body:
encoding: UTF-8
string: '{"links":[{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/Test%20Page","rel":"http://www.xwiki.org/rel/space","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/Test%20Page/pages/WebHome","rel":"http://www.xwiki.org/rel/parent","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/Test%20Page/pages/WebHome/history","rel":"http://www.xwiki.org/rel/history","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/spaces/Test%20Page/pages/WebHome/objects","rel":"http://www.xwiki.org/rel/objects","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/syntaxes","rel":"http://www.xwiki.org/rel/syntaxes","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/openproject/documents/d70f1","rel":"self","type":null,"hrefLang":null},{"href":"https://xwiki.local/rest/wikis/xwiki/classes/Test%20Page.WebHome","rel":"http://www.xwiki.org/rel/class","type":null,"hrefLang":null}],"id":"d70f1","fullName":"Test
Page.WebHome","wiki":"xwiki","space":"Test Page","name":"WebHome","title":"Test
Page for RSpec","rawTitle":"Test Page for RSpec","parent":"Main.WebHome","parentId":"xwiki:Main.WebHome","version":"4.1","author":"XWiki.admin","authorName":null,"xwikiRelativeUrl":"https://xwiki.local/bin/view/Test%20Page/","xwikiAbsoluteUrl":"https://xwiki.local/bin/view/Test%20Page/","translations":{"links":[],"translations":[],"default":"en"},"syntax":"xwiki/2.1","language":"","majorVersion":4,"minorVersion":1,"hidden":false,"enforceRequiredRights":false,"created":1780383689000,"creator":"XWiki.admin","creatorName":null,"modified":1780386902000,"modifier":"XWiki.admin","modifierName":null,"originalMetadataAuthor":"xwiki:XWiki.admin","originalMetadataAuthorName":null,"comment":"Created
URL Shortener.","content":"This is a test page that I created with my own
hands.","clazz":null,"objects":null,"attachments":null,"hierarchy":{"items":[{"label":"xwiki","name":"xwiki","type":"wiki","url":"https://xwiki.local/bin/view/Main/"},{"label":"Test
Page","name":"Test Page","type":"space","url":"https://xwiki.local/bin/view/Test%20Page/"},{"label":"WebHome","name":"WebHome","type":"document","url":"https://xwiki.local/bin/view/Test%20Page/"}]},"rights":[],"renderedContent":null}'
recorded_at: Fri, 05 Jun 2026 06:33:33 GMT
recorded_with: VCR 6.4.0