summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSzabolcs David <davidsz@inf.u-szeged.hu>2025-10-20 15:21:31 +0200
committerSzabolcs David <davidsz@inf.u-szeged.hu>2025-11-06 15:08:44 +0100
commit48ba78f27354a0252d09410203ce4191d6129d57 (patch)
treee52b59d9f410c60a14085ff169fba2ad22f4a50f
parent2ebb596b43346c5bf93fc9a460e241a812313c0e (diff)
Allow redirecting fetch() to cross origin resources
We use CorsURLLoader since the 124-based Chromium. This performs a safety check on calling CorsURLLoader::OnReceiveRedirect(), since fetch() requests have more strict rules when accessing cross origin resources. This patch extends our dummy response with the Allow-Origin header (only in case of redirects), so the request interceptor API users won't hit this wall. Test case implemented by: Benjamin Terrier Task-number: QTBUG-140889 Change-Id: I7025fb69b5ac9b8763d61cb2bf0880dcc20721cf Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
-rw-r--r--src/core/net/proxying_url_loader_factory_qt.cpp12
-rw-r--r--tests/auto/core/qwebengineurlrequestinterceptor/CMakeLists.txt2
-rw-r--r--tests/auto/core/qwebengineurlrequestinterceptor/resources/cors.html8
-rw-r--r--tests/auto/core/qwebengineurlrequestinterceptor/resources/cors.js17
-rw-r--r--tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp31
5 files changed, 70 insertions, 0 deletions
diff --git a/src/core/net/proxying_url_loader_factory_qt.cpp b/src/core/net/proxying_url_loader_factory_qt.cpp
index 08bcbc394..f9e3498ae 100644
--- a/src/core/net/proxying_url_loader_factory_qt.cpp
+++ b/src/core/net/proxying_url_loader_factory_qt.cpp
@@ -403,6 +403,18 @@ void InterceptedRequest::ContinueAfterIntercept()
if (!current_response_)
current_response_ = createResponse(request_);
current_response_->encoded_data_length = 0;
+
+ if (!current_response_->headers) {
+ current_response_->headers = base::MakeRefCounted<net::HttpResponseHeaders>("");
+ // Assuming that the users of request interceptor API are aware of the security
+ // risks
+ current_response_->headers->AddHeader(
+ network::cors::header_names::kAccessControlAllowOrigin,
+ url::Origin::Create(request_.url).Serialize());
+ current_response_->headers->AddHeader(
+ network::cors::header_names::kAccessControlAllowCredentials, "true");
+ }
+
target_client_->OnReceiveRedirect(redirectInfo, std::move(current_response_));
return;
}
diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/CMakeLists.txt b/tests/auto/core/qwebengineurlrequestinterceptor/CMakeLists.txt
index 76db8b7e2..3219c44b9 100644
--- a/tests/auto/core/qwebengineurlrequestinterceptor/CMakeLists.txt
+++ b/tests/auto/core/qwebengineurlrequestinterceptor/CMakeLists.txt
@@ -19,6 +19,8 @@ set(tst_qwebengineurlrequestinterceptor_resource_files
"resources/content.html"
"resources/content2.html"
"resources/content3.html"
+ "resources/cors.html"
+ "resources/cors.js"
"resources/favicon.html"
"resources/firstparty.html"
"resources/fontawesome.woff"
diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/resources/cors.html b/tests/auto/core/qwebengineurlrequestinterceptor/resources/cors.html
new file mode 100644
index 000000000..b0fb2cfd9
--- /dev/null
+++ b/tests/auto/core/qwebengineurlrequestinterceptor/resources/cors.html
@@ -0,0 +1,8 @@
+<html>
+ <head>
+ <link rel="icon" href="data:," />
+ </head>
+ <script src="http://www.qt.io/cors.js"></script>
+ >
+ <body></body>
+</html>
diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/resources/cors.js b/tests/auto/core/qwebengineurlrequestinterceptor/resources/cors.js
new file mode 100644
index 000000000..edd338415
--- /dev/null
+++ b/tests/auto/core/qwebengineurlrequestinterceptor/resources/cors.js
@@ -0,0 +1,17 @@
+async function getData()
+{
+ const url = "https://qt.io/content.html";
+ try {
+ const response = await fetch(url);
+ if (!response.ok) {
+ throw new Error(`Response status: ${response.status}`);
+ }
+
+ const result = await response.json();
+ console.log(result);
+ } catch (error) {
+ console.error(error.message);
+ }
+}
+
+getData();
diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp
index ad9f91a93..81d654066 100644
--- a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp
+++ b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp
@@ -54,6 +54,7 @@ private Q_SLOTS:
void profilePreventsPageInterception_data();
void profilePreventsPageInterception();
void download();
+ void redirect();
};
tst_QWebEngineUrlRequestInterceptor::tst_QWebEngineUrlRequestInterceptor()
@@ -1143,5 +1144,35 @@ void tst_QWebEngineUrlRequestInterceptor::download()
QCOMPARE(interceptor.requestInfos.at(0).download, true);
}
+void tst_QWebEngineUrlRequestInterceptor::redirect()
+{
+ HttpServer server;
+ server.setResourceDirs({ ":/resources" });
+ QVERIFY(server.start());
+
+ TestRequestInterceptor interceptor;
+ interceptor.onIntercept = [&](QWebEngineUrlRequestInfo &info) {
+ const auto url = server.url(info.requestUrl().path());
+ if (info.requestUrl() != url) {
+ qDebug() << "FROM" << info.requestUrl() << "TO" << url;
+ info.redirect(url);
+ return false;
+ }
+ return true;
+ };
+
+ QWebEnginePage page;
+ page.setUrlRequestInterceptor(&interceptor);
+ QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool)));
+
+ const auto url = QUrl(server.url("/cors.html"));
+ page.load(url);
+ QTRY_COMPARE(loadSpy.size(), 1);
+ // We expect 3 requests: cors.html, cors.js and content.html
+ // redirected requests are not counted
+ // We will only get 2 because the request to fetch content.html will never happen
+ QCOMPARE(interceptor.requestInfos.size(), 3);
+}
+
QTEST_MAIN(tst_QWebEngineUrlRequestInterceptor)
#include "tst_qwebengineurlrequestinterceptor.moc"