Open Bug 1675646 Opened 4 years ago Updated 4 months ago

Cross-Domain XHR DELETE requests from JavaScript write "undefined" HTTP-version when withCredentials=true

Categories

(DevTools :: Netmonitor, defect, P3)

Firefox 82
defect

Tracking

(Not tracked)

ASSIGNED

People

(Reporter: admin, Assigned: bomsy, NeedInfo)

References

(Blocks 1 open bug)

Details

Attachments

(2 files)

User Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:82.0) Gecko/20100101 Firefox/82.0

Steps to reproduce:

** Using an API that provides cookies during login which are required for authorization of requests (such as session tokens) **

  1. In JavaScript, create an XHR DELETE request to a cross-domain URL that provides a valid CORS response which authorizes DELETE in the Access-Control-Allow-Methods response header.
  2. Set "withCredentials = true" on XHR request.
  3. Send XHR request.

Example code, pure JavaScript (irrelevant code redacted):

   var xhr = new XMLHttpRequest();
   xhr.open("DELETE", url, true);
   xhr.withCredentials = true;
   xhr.onload = function () {
   var response = JSON.parse(xhr.responseText);
   if (xhr.readyState == 4 && xhr.status == "200") {
        success_fxn(response);
   } else {
        error_fxn(response);
   }
}
xhr.send(null);

Example code, jQuery (irrelevant code redacted):

const delete_cmd = {
  type: "DELETE",
  crossDomain: true,
  xhrFields: {
    withCredentials: true
  },
  url: url,
  success: function(jsonData, textStatus, _jqxhr) {
    success_fxn(jsonData);
  },
  error: function(_jqxhr, textStatus, error) {
    error_fxn(error);
  }
};
$.ajax(delete_cmd);

*** Important Notes ***

  • If the failed request is selected in the Developer Tools - Network tab and resent using the "Send/Edit and Resend" dropdown, it correctly sends the request as expected.
  • This problem is definitely not happening with GET or POST requests but I have not tested with any other HTTP methods.

Actual results:

The request-line contains the correct method and request-target but an invalid HTTP-version, "undefined".

Example headers sent (partially redacted):

DELETE /gallery/3/images/5 undefined
Host: (redacted)
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:82.0) Gecko/20100101 Firefox/82.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Origin: (redacted)
Connection: keep-alive
Referer: (redacted)
Cookie: session=(redacted)

Expected results:

The request-line should contain a valid HTTP-version as defined in RFC 7230 (https://tools.ietf.org/html/rfc7230#section-3.1.1). In this case, the HTTP-version should have read "HTTP/1.1" and not "undefined".

Example headers that should have been sent (partially redacted):

DELETE /gallery/3/images/5 HTTP/1.1
Host: (redacted)
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:82.0) Gecko/20100101 Firefox/82.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Origin: (redacted)
Connection: keep-alive
Referer: (redacted)
Cookie: session=(redacted)
Pragma: no-cache
Cache-Control: no-cache

Hi,

I don't have the technical skills to reproduce this issue on my end, but I'll add "Core - DOM: Web Autentication" as product and component in the hope someone from their team can take a look at this and advice.

Regards,
Virginia

Component: Untriaged → DOM: Web Authentication
Product: Firefox → Core

The severity field is not set for this bug.
:jcj, could you have a look please?

For more information, please visit auto_nag documentation.

Flags: needinfo?(jc)

moving to DOM Security for their triage

Component: DOM: Web Authentication → DOM: Security
Flags: needinfo?(jc)

I don't know why withCredentials would matter, either way this is going to require a CORS preflight check because of the DELETE method, right?

All the Fetch code lives in networking these days.

Component: DOM: Security → Networking: HTTP
Flags: needinfo?(annevk)

Why does it fail if the server allows these requests? Because you don't have the relevant cookie or some such?

In any event, this sounds like something going wrong in Developer Tools, not with fetching itself.

Component: Networking: HTTP → Netmonitor
Flags: needinfo?(annevk) → needinfo?(admin)
Product: Core → DevTools

Hi Mark,
Thanks for reporting.
This looks like a netmonitor issue.

Please can you give us an online link or a PHP file which we can use to reproduce the issue.

Thanks.

Apologies for the delayed response. I was digging into this more and wanted to have it clear in my mind before responding back.

You can see this bug at this URL but it is a bit different than originally thought:
https://pge.mark-christensen.com/bug-1675646

As :dveditz pointed out, the connection with withCredentials was key to finding more information about what might be going wrong here.

What I hadn't noticed before filing this bug was that the CORS preflight was complaining that Access-Control-Allow-Credentials was missing. The CORS headers were fine but that one was missing. The reason I missed that was because I have POST requests going through the same API (same Nginx location block with same CORS OPTIONS response) which were not complaining despite having withCredentials set.

The real bug(s) does seem to be an issue with devtools in the way the blocked DELETE request is displayed. After the CORS preflight fails, the DELETE request is queued under the devtools Network tab with the invalid HTTP version string (as described above). It isn't clear if it is being sent and rejected or if the devtools is simply showing what the site was trying to send.

Particularly confusing is that I can select this invalid, (maybe?) blocked DELETE request and choose "Resend" after which it sends fine (with the correct HTTP version string). [[Note: if you are trying this using the example above, upon resending the failed request, you should get a 404 response from the server.]] For comparison, if I do the (more or less) equivalent action in Chrome devtools by right-clicking the failed request and selecting "Replay XHR" then it fails in an identical way to the original request; it does not resend successfully like in Firefox. That suggests to me that choosing "Resend" in Firefox is not actually using the same XHR parameters as the original request.

I have confirmed that fixing the CORS header does cause it to generate a valid DELETE request with the correct HTTP version string and so this issue is not as serious as I had originally thought. There does still seem to be an issue or two related to the display and user experience around requests that fail due to CORS.

Flags: needinfo?(admin)

Oops !

I failed to mention in my last response that I really appreciate y'all looking into this. Thanks for your efforts so far and in the future !

Cheers.

Attached image image.png

If I understand correctly this bug is about showing "undefined" instead of HTTP version number for request headers.

STR:

  1. Load https://pge.mark-christensen.com/bug-1675646
  2. Open DevTools Toolbox and select the Network panel
  3. Reload the page and select the DELETE request
  4. Check out the Headers side panel and switch to raw headers (request headers)
  5. The HTTP version info is missing and 'undefined' is displayed instead -> BUG

See also the attached screenshot.

Honza

Severity: -- → S3
Status: UNCONFIRMED → NEW
Has STR: --- → yes
Ever confirmed: true
Priority: -- → P3
See Also: → 1866249

Did some investigations, the issue is that even though the httpVersion is used to render the raw output for the request headers, the httpVersion is only added to the request information sent to the UI after the response has kicked in
See here https://searchfox.org/mozilla-central/rev/996f5bf0b9a32aa0620a841abb9531625fe916aa/devtools/server/actors/network-monitor/network-event-actor.js#495-496

We should try to sent this earlier.

Duplicate of this bug: 1866249
Duplicate of this bug: 1809031
Assignee: nobody → hmanilla
Status: NEW → ASSIGNED
Pushed by hmanilla@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/07de2cf13c82
[devtools] Make sure the HTTP version is always in the request/response raw header outputs r=devtools-reviewers,nchevobbe

Backed out for causing dt failures on browser_net_http3_request_details.js.

[task 2023-12-04T23:57:08.091Z] 23:57:08     INFO - TEST-PASS | devtools/client/netmonitor/test/browser_net_http3_request_details.js | The status summary value is incorrect. - 
[task 2023-12-04T23:57:08.092Z] 23:57:08     INFO - Buffered messages finished
[task 2023-12-04T23:57:08.093Z] 23:57:08     INFO - TEST-UNEXPECTED-FAIL | devtools/client/netmonitor/test/browser_net_http3_request_details.js | The HTTP version is incorrect. - Got "HTTP/1.1", expected "HTTP/3"
[task 2023-12-04T23:57:08.094Z] 23:57:08     INFO - Stack trace:
[task 2023-12-04T23:57:08.094Z] 23:57:08     INFO - chrome://mochikit/content/browser-test.js:test_is:1619
[task 2023-12-04T23:57:08.094Z] 23:57:08     INFO - chrome://mochitests/content/browser/devtools/client/netmonitor/test/browser_net_http3_request_details.js:null:57
[task 2023-12-04T23:57:08.095Z] 23:57:08     INFO - chrome://mochikit/content/browser-test.js:handleTask:1138
[task 2023-12-04T23:57:08.095Z] 23:57:08     INFO - chrome://mochikit/content/browser-test.js:_runTaskBasedTest:1210
[task 2023-12-04T23:57:08.095Z] 23:57:08     INFO - chrome://mochikit/content/browser-test.js:Tester_execTest:1352
[task 2023-12-04T23:57:08.095Z] 23:57:08     INFO - chrome://mochikit/content/browser-test.js:nextTest/<:1127
[task 2023-12-04T23:57:08.096Z] 23:57:08     INFO - chrome://mochikit/content/tests/SimpleTest/SimpleTest.js:SimpleTest.waitForFocus/<:1058
[task 2023-12-04T23:57:08.097Z] 23:57:08     INFO - TEST-PASS | devtools/client/netmonitor/test/browser_net_http3_request_details.js | There should be 2 header scopes displayed in this tabpanel. - 
[task 2023-12-04T23:57:08.098Z] 23:57:08     INFO - TEST-PASS | devtools/client/netmonitor/test/browser_net_http3_request_details.js | There should be 25 header values displayed in this tabpanel. - 
[task 2023-12-04T23:57:08.099Z] 23:57:08     INFO - TEST-PASS | devtools/client/netmonitor/test/browser_net_http3_request_details.js | The response header at index 0 name was incorrect. - 
[task 2023-12-04T23:57:08.100Z] 23:57:08     INFO - TEST-PASS | devtools/client/netmonitor/test/browser_net_http3_request_details.js | The response header at index 0 value was incorrect. - 
[task 2023-12-04T23:57:08.100Z] 23:57:08     INFO - TEST-PASS | devtools/client/netmonitor/test/browser_net_http3_request_details.js | The response header at index 1 name was incorrect. - 
[task 2023-12-04T23:57:08.102Z] 23:57:08     INFO - TEST-PASS | devtools/client/netmonitor/test/browser_net_http3_request_details.js | The response header at index 1 value was incorrect. - 
[task 2023-12-04T23:57:08.102Z] 23:57:08     INFO - TEST-PASS | devtools/client/netmonitor/test/browser_net_http3_request_details.js | The response header at index 2 name was incorrect. - 
[task 2023-12-04T23:57:08.103Z] 23:57:08     INFO - TEST-PASS | devtools/client/netmonitor/test/browser_net_http3_request_details.js | The response header at index 2 value was incorrect. - 
[task 2023-12-04T23:57:08.104Z] 23:57:08     INFO - TEST-PASS | devtools/client/netmonitor/test/browser_net_http3_request_details.js | The response header at index 6 name was incorrect. - 
[task 2023-12-04T23:57:08.105Z] 23:57:08     INFO - TEST-PASS | devtools/client/netmonitor/test/browser_net_http3_request_details.js | The response header at index 6 value was incorrect. - 
[task 2023-12-04T23:57:08.106Z] 23:57:08     INFO - Assert the content of the raw headers
[task 2023-12-04T23:57:08.142Z] 23:57:08     INFO - Not taking screenshot here: see the one that was previously logged
[task 2023-12-04T23:57:08.145Z] 23:57:08     INFO - TEST-UNEXPECTED-FAIL | devtools/client/netmonitor/test/browser_net_http3_request_details.js | undefined assertion name - Got "GET /browser/devtools/client/netmonitor/test/sjs_simple-test-server.sjs HTTP/1.1", expected "GET /browser/devtools/client/netmonitor/test/sjs_simple-test-server.sjs HTTP/3"
[task 2023-12-04T23:57:08.146Z] 23:57:08     INFO - Stack trace:
[task 2023-12-04T23:57:08.147Z] 23:57:08     INFO - chrome://mochikit/content/browser-test.js:test_is:1619
[task 2023-12-04T23:57:08.148Z] 23:57:08     INFO - chrome://mochitests/content/browser/devtools/client/netmonitor/test/browser_net_http3_request_details.js:null:135
[task 2023-12-04T23:57:08.149Z] 23:57:08     INFO - chrome://mochikit/content/browser-test.js:handleTask:1138
[task 2023-12-04T23:57:08.149Z] 23:57:08     INFO - chrome://mochikit/content/browser-test.js:_runTaskBasedTest:1210
[task 2023-12-04T23:57:08.150Z] 23:57:08     INFO - chrome://mochikit/content/browser-test.js:Tester_execTest:1352
[task 2023-12-04T23:57:08.150Z] 23:57:08     INFO - chrome://mochikit/content/browser-test.js:nextTest/<:1127
[task 2023-12-04T23:57:08.151Z] 23:57:08     INFO - chrome://mochikit/content/tests/SimpleTest/SimpleTest.js:SimpleTest.waitForFocus/<:1058
[task 2023-12-04T23:57:08.153Z] 23:57:08     INFO - Not taking screenshot here: see the one that was previously logged
[task 2023-12-04T23:57:08.155Z] 23:57:08     INFO - TEST-UNEXPECTED-FAIL | devtools/client/netmonitor/test/browser_net_http3_request_details.js | undefined assertion name - Got "HTTP/1.1 200 ", expected "HTTP/3 200 "
[task 2023-12-04T23:57:08.155Z] 23:57:08     INFO - Stack trace:
[task 2023-12-04T23:57:08.156Z] 23:57:08     INFO - chrome://mochikit/content/browser-test.js:test_is:1619
[task 2023-12-04T23:57:08.156Z] 23:57:08     INFO - chrome://mochitests/content/browser/devtools/client/netmonitor/test/browser_net_http3_request_details.js:null:142
[task 2023-12-04T23:57:08.157Z] 23:57:08     INFO - chrome://mochikit/content/browser-test.js:handleTask:1138
[task 2023-12-04T23:57:08.158Z] 23:57:08     INFO - chrome://mochikit/content/browser-test.js:_runTaskBasedTest:1210
[task 2023-12-04T23:57:08.158Z] 23:57:08     INFO - chrome://mochikit/content/browser-test.js:Tester_execTest:1352
[task 2023-12-04T23:57:08.159Z] 23:57:08     INFO - chrome://mochikit/content/browser-test.js:nextTest/<:1127
[task 2023-12-04T23:57:08.159Z] 23:57:08     INFO - chrome://mochikit/content/tests/SimpleTest/SimpleTest.js:SimpleTest.waitForFocus/<:1058
[task 2023-12-04T23:57:08.160Z] 23:57:08     INFO - Assert the content of the protocol column
[task 2023-12-04T23:57:08.166Z] 23:57:08     INFO - Not taking screenshot here: see the one that was previously logged
[task 2023-12-04T23:57:08.169Z] 23:57:08     INFO - TEST-UNEXPECTED-FAIL | devtools/client/netmonitor/test/browser_net_http3_request_details.js | The displayed protocol is correct. - Got "HTTP/1.1", expected "HTTP/3"
[task 2023-12-04T23:57:08.169Z] 23:57:08     INFO - Stack trace:
[task 2023-12-04T23:57:08.170Z] 23:57:08     INFO - chrome://mochikit/content/browser-test.js:test_is:1619
[task 2023-12-04T23:57:08.171Z] 23:57:08     INFO - chrome://mochitests/content/browser/devtools/client/netmonitor/test/browser_net_http3_request_details.js:null:146
[task 2023-12-04T23:57:08.171Z] 23:57:08     INFO - chrome://mochikit/content/browser-test.js:handleTask:1138
[task 2023-12-04T23:57:08.172Z] 23:57:08     INFO - chrome://mochikit/content/browser-test.js:_runTaskBasedTest:1210
[task 2023-12-04T23:57:08.172Z] 23:57:08     INFO - chrome://mochikit/content/browser-test.js:Tester_execTest:1352
[task 2023-12-04T23:57:08.173Z] 23:57:08     INFO - chrome://mochikit/content/browser-test.js:nextTest/<:1127
[task 2023-12-04T23:57:08.174Z] 23:57:08     INFO - chrome://mochikit/content/tests/SimpleTest/SimpleTest.js:SimpleTest.waitForFocus/<:1058
[task 2023-12-04T23:57:08.175Z] 23:57:08     INFO - Destroying the specified network monitor.
[task 2023-12-04T23:57:08.176Z] 23:57:08     INFO - Wait for completion of all NetworkUpdateEvents packets...
[task 2023-12-04T23:57:08.177Z] 23:57:08     INFO - All pending requests finished.
[task 2023-12-04T23:57:08.326Z] 23:57:08     INFO - GECKO(5808) | [Parent 5808, Main Thread] WARNING: NS_ENSURE_TRUE(!mHasOrHasHadOwnerWindow || mOwnerWindow) failed: file /builds/worker/checkouts/gecko/dom/base/GlobalTeardownObserver.cpp:51
[task 2023-12-04T23:57:08.327Z] 23:57:08     INFO - GECKO(5808) | [Parent 5808, Main Thread] WARNING: NS_ENSURE_TRUE(!mHasOrHasHadOwnerWindow || mOwnerWindow) failed: file /builds/worker/checkouts/gecko/dom/base/GlobalTeardownObserver.cpp:51
[task 2023-12-04T23:57:08.327Z] 23:57:08     INFO - GECKO(5808) | [Parent 5808, Main Thread] WARNING: NS_ENSURE_TRUE(!mHasOrHasHadOwnerWindow || mOwnerWindow) failed: file /builds/worker/checkouts/gecko/dom/base/GlobalTeardownObserver.cpp:51
[task 2023-12-04T23:57:08.328Z] 23:57:08     INFO - GECKO(5808) | [Parent 5808, Main Thread] WARNING: NS_ENSURE_TRUE(!mHasOrHasHadOwnerWindow || mOwnerWindow) failed: file /builds/worker/checkouts/gecko/dom/base/GlobalTeardownObserver.cpp:51
[task 2023-12-04T23:57:09.101Z] 23:57:09     INFO - GECKO(5808) | [Parent 5808: Main Thread]: I/DocShellAndDOMWindowLeak --DOMWINDOW == 18 (7fd6059f0c00) [pid = 5808] [serial = 19] [outer = 0] [url = about:blank]
[task 2023-12-04T23:57:09.105Z] 23:57:09     INFO - GECKO(5808) | [Parent 5808: Main Thread]: I/DocShellAndDOMWindowLeak --DOMWINDOW == 17 (7fd60fdbc400) [pid = 5808] [serial = 17] [outer = 0] [url = about:blank]
[task 2023-12-04T23:57:09.106Z] 23:57:09     INFO - GECKO(5808) | [Parent 5808: Main Thread]: I/DocShellAndDOMWindowLeak --DOMWINDOW == 16 (7fd60a124c00) [pid = 5808] [serial = 15] [outer = 0] [url = about:devtools-toolbox]
[task 2023-12-04T23:57:09.107Z] 23:57:09     INFO - GECKO(5808) | [Parent 5808: Main Thread]: I/DocShellAndDOMWindowLeak --DOMWINDOW == 15 (7fd60edf04c0) [pid = 5808] [serial = 13] [outer = 0] [url = about:devtools-toolbox]
[task 2023-12-04T23:57:09.108Z] 23:57:09     INFO - GECKO(5808) | [Parent 5808: Main Thread]: I/DocShellAndDOMWindowLeak --DOMWINDOW == 14 (7fd60edf02e0) [pid = 5808] [serial = 16] [outer = 0] [url = chrome://devtools/content/netmonitor/index.html]
[task 2023-12-04T23:57:09.127Z] 23:57:09     INFO - Removing tab.
[task 2023-12-04T23:57:09.129Z] 23:57:09     INFO - Waiting for event: 'TabClose' on [object XULElement].
[task 2023-12-04T23:57:09.167Z] 23:57:09     INFO - Got event: 'TabClose' on [object XULElement].
[task 2023-12-04T23:57:09.192Z] 23:57:09     INFO - GECKO(5808) | [Parent 5808, Main Thread] WARNING: '!inner', file /builds/worker/checkouts/gecko/dom/ipc/jsactor/JSWindowActorProtocol.cpp:163
[task 2023-12-04T23:57:09.192Z] 23:57:09     INFO - GECKO(5808) | [Parent 5808, Main Thread] WARNING: '!inner', file /builds/worker/checkouts/gecko/dom/ipc/jsactor/JSWindowActorProtocol.cpp:163
[task 2023-12-04T23:57:09.209Z] 23:57:09     INFO - Tab removed and finished closing
[task 2023-12-04T23:57:09.211Z] 23:57:09     INFO - Leaving test bound 
[task 2023-12-04T23:57:09.243Z] 23:57:09     INFO - GECKO(5808) | JavaScript error: , line 0: NotFoundError: No such JSWindowActor 'DevToolsFrame'
[task 2023-12-04T23:57:09.298Z] 23:57:09     INFO - Console message: [JavaScript Error: "NotFoundError: No such JSWindowActor 'DevToolsFrame'"]
[task 2023-12-04T23:57:09.306Z] 23:57:09     INFO - TEST-PASS | devtools/client/netmonitor/test/browser_net_http3_request_details.js | The main process DevToolsServer has no pending connection when the test ends - 
Flags: needinfo?(hmanilla)
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: