Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Content-Type gets wrongfully added to GET request after 303 redirects #16508

Merged
merged 1 commit into from
Aug 10, 2023

Conversation

sysrqb
Copy link
Contributor

@sysrqb sysrqb commented Aug 9, 2023

9b8c53b

Content-Type gets wrongfully added to GET request after 303 redirects
https://bugs.webkit.org/show_bug.cgi?id=258720
rdar://111899420

Reviewed by Chris Dumez.

In 252713@main we began copying the Content-Type header from the original
request if we receive a redirect with a 303 response status. However, we may be
handling a subsequent redirect, and in some cases the Content-Type header is
removed from redirect requests. For example, if we transition from a POST to a
GET request, Fetch 4.4.12 [0] says that the Content-Type header should be
deleted. WebKit currently follows this specification, but we re-introduce the
header on a second redirect because we consult the first request instead of the
previous request.

This patch introduces NetworkDataTask::m_previousRequest to keep track of the
previous request. This is duplicate information that is stored in NetworkLoad,
as well, but I'm leaving merging these two copies for a follow-up patch.

[0] https://fetch.spec.whatwg.org/#http-redirect-fetch

* LayoutTests/imported/w3c/web-platform-tests/xhr/resources/redirect.py:
(main):
* LayoutTests/imported/w3c/web-platform-tests/xhr/send-redirect-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/xhr/send-redirect.htm:
* Source/WebCore/platform/network/ResourceHandleInternal.h:
* Source/WebCore/platform/network/mac/ResourceHandleMac.mm:
(WebCore::ResourceHandle::willSendRequest):
* Source/WebKit/NetworkProcess/NetworkDataTask.h:
* Source/WebKit/NetworkProcess/NetworkLoad.h:
* Source/WebKit/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm:
(WebKit::NetworkDataTaskCocoa::willPerformHTTPRedirection):
* Tools/TestWebKitAPI/Tests/WebKitCocoa/Navigation.mm:
(TEST):

Canonical link: https://commits.webkit.org/266761@main

3605a61

Misc iOS, tvOS & watchOS macOS Linux Windows
βœ… πŸ§ͺ style βœ… πŸ›  ios βœ… πŸ›  mac βœ… πŸ›  wpe βœ… πŸ›  wincairo
βœ… πŸ§ͺ bindings βœ… πŸ›  ios-sim βœ… πŸ›  mac-AS-debug   πŸ§ͺ wpe-wk2
βœ… πŸ§ͺ webkitperl βœ… πŸ§ͺ ios-wk2 βœ… πŸ§ͺ api-mac βœ… πŸ›  gtk
βœ… πŸ§ͺ ios-wk2-wpt βœ… πŸ§ͺ mac-wk1 βœ… πŸ§ͺ gtk-wk2
βœ… πŸ§ͺ api-ios βœ… πŸ§ͺ mac-wk2 βœ… πŸ§ͺ api-gtk
βœ… πŸ›  tv βœ… πŸ§ͺ mac-AS-debug-wk2
βœ… πŸ›  tv-sim
βœ… πŸ›  πŸ§ͺ merge βœ… πŸ›  watch
βœ… πŸ›  watch-sim

@sysrqb sysrqb requested a review from cdumez as a code owner August 9, 2023 03:42
@sysrqb sysrqb self-assigned this Aug 9, 2023
@sysrqb sysrqb added the Page Loading For bugs in page loading, including handling of network callbacks. label Aug 9, 2023
Copy link
Contributor

@cdumez cdumez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is breaking compatibility with other browsers in at least some aspects.

Consider this test change:

diff --git a/LayoutTests/imported/w3c/web-platform-tests/xhr/send-redirect.htm b/LayoutTests/imported/w3c/web-platform-tests/xhr/send-redirect.htm
index 16b3231e25b4..6e4ca3d4f89d 100644
--- a/LayoutTests/imported/w3c/web-platform-tests/xhr/send-redirect.htm
+++ b/LayoutTests/imported/w3c/web-platform-tests/xhr/send-redirect.htm
@@ -9,28 +9,45 @@
   <body>
     <div id="log"></div>
     <script>
-      function redirect(code) {
-        var test = async_test(document.title + " (" + code + ")")
+      function redirect(code, method) {
+        var test = async_test(document.title + " (" + code + ", " + method + ")")
         test.step(function() {
           var client = new XMLHttpRequest()
           client.onreadystatechange = function() {
             test.step(function() {
               if(client.readyState == 4) {
-                assert_equals(client.getResponseHeader("x-request-method"), "GET")
-                assert_equals(client.getResponseHeader("x-request-content-type"), "application/x-pony")
+                let expected_method = method;
+                if (method == "POST" && (code == "301" || code == "302" || code == "303"))
+                  expected_method = "GET";
+                assert_equals(client.getResponseHeader("x-request-method"), expected_method)
+                let expected_content_type = "application/x-pony";
+                if (method == "POST" && (code == "301" || code == "302" || code == "303"))
+                  expected_content_type = "NO";
+                assert_equals(client.getResponseHeader("x-request-content-type"), expected_content_type);
                 test.done()
               }
             })
           }
-          client.open("GET", "resources/redirect.py?location=content.py&code=" + code)
+          client.open(method, "resources/redirect.py?location=content.py&code=" + code)
           client.setRequestHeader("Content-Type", "application/x-pony")
           client.send(null)
         })
       }
-      redirect("301")
-      redirect("302")
-      redirect("303")
-      redirect("307")
+      redirect("301", "GET");
+      redirect("302", "GET");
+      redirect("303", "GET");
+      redirect("307", "GET");
+      redirect("308", "GET");
+      redirect("301", "POST");
+      redirect("302", "POST");
+      redirect("303", "POST");
+      redirect("307", "POST");
+      redirect("308", "POST");
+      redirect("301", "HEAD");
+      redirect("302", "HEAD");
+      redirect("303", "HEAD");
+      redirect("307", "HEAD");
+      redirect("308", "HEAD");
     </script>
   </body>
 </html>

This updated test passes in Chrome, Firefox and shipping Safari. However, your patch regresses the XMLHttpRequest: send() - Redirects (basics) (303, GET) subtest.

@webkit-ews-buildbot webkit-ews-buildbot added the merging-blocked Applied to prevent a change from being merged label Aug 9, 2023
@sysrqb sysrqb removed the merging-blocked Applied to prevent a change from being merged label Aug 9, 2023
@sysrqb
Copy link
Contributor Author

sysrqb commented Aug 9, 2023

Thanks, that's a good point. My reasoning for that change was actually wrong because the HTTP Semantics spec talks about sending content in a GET request, it is not talking about the Content-Type header. Therefore, sending the Content-Type header in a GET request is allowed, except where the Fetch spec says we must remove the Content-Type header on redirect.

@sysrqb
Copy link
Contributor Author

sysrqb commented Aug 9, 2023

Your modified test was helpful, and I adapted that in this patch. That may not be the best approach, so I'm happy to get feedback on it (maybe create a new test file?) - and I'll upstream any wpt test changes.

Copy link
Contributor

@cdumez cdumez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@@ -9,20 +9,28 @@
<body>
<div id="log"></div>
<script>
function redirect(code) {
var test = async_test(document.title + " (" + code + ")")
function redirect(code, method="GET", redirectLocation="content.py") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's great, please make sure to upstream to WPT or it will get lost during the next re-sync.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -1798,3 +1798,60 @@ HTTPServer server({
while (navigationToExample)
Util::spinRunLoop();
}

TEST(WKNavigation, Multiple303Redirects)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that in general, we prefer layout tests to API tests whenever possible. This is a case where a layout test was possible I believe.

@sysrqb sysrqb added the merge-queue Applied to send a pull request to merge-queue label Aug 10, 2023
https://bugs.webkit.org/show_bug.cgi?id=258720
rdar://111899420

Reviewed by Chris Dumez.

In 252713@main we began copying the Content-Type header from the original
request if we receive a redirect with a 303 response status. However, we may be
handling a subsequent redirect, and in some cases the Content-Type header is
removed from redirect requests. For example, if we transition from a POST to a
GET request, Fetch 4.4.12 [0] says that the Content-Type header should be
deleted. WebKit currently follows this specification, but we re-introduce the
header on a second redirect because we consult the first request instead of the
previous request.

This patch introduces NetworkDataTask::m_previousRequest to keep track of the
previous request. This is duplicate information that is stored in NetworkLoad,
as well, but I'm leaving merging these two copies for a follow-up patch.

[0] https://fetch.spec.whatwg.org/#http-redirect-fetch

* LayoutTests/imported/w3c/web-platform-tests/xhr/resources/redirect.py:
(main):
* LayoutTests/imported/w3c/web-platform-tests/xhr/send-redirect-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/xhr/send-redirect.htm:
* Source/WebCore/platform/network/ResourceHandleInternal.h:
* Source/WebCore/platform/network/mac/ResourceHandleMac.mm:
(WebCore::ResourceHandle::willSendRequest):
* Source/WebKit/NetworkProcess/NetworkDataTask.h:
* Source/WebKit/NetworkProcess/NetworkLoad.h:
* Source/WebKit/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm:
(WebKit::NetworkDataTaskCocoa::willPerformHTTPRedirection):
* Tools/TestWebKitAPI/Tests/WebKitCocoa/Navigation.mm:
(TEST):

Canonical link: https://commits.webkit.org/266761@main
@webkit-commit-queue
Copy link
Collaborator

Committed 266761@main (9b8c53b): https://commits.webkit.org/266761@main

Reviewed commits have been landed. Closing PR #16508 and removing active labels.

@webkit-commit-queue webkit-commit-queue merged commit 9b8c53b into WebKit:main Aug 10, 2023
@webkit-commit-queue webkit-commit-queue removed the merge-queue Applied to send a pull request to merge-queue label Aug 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Page Loading For bugs in page loading, including handling of network callbacks.
Projects
None yet
5 participants