Skip to content

Commit 0a66d30

Browse files
authored
fetch: don't set an invalid origin header (#3235)
* don't set an invalid origin header (fetch) * fixup * fixup * fixup
1 parent 71bf81b commit 0a66d30

File tree

5 files changed

+50
-15
lines changed

5 files changed

+50
-15
lines changed

lib/web/fetch/index.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -444,8 +444,7 @@ function fetching ({
444444
// 9. If request’s origin is "client", then set request’s origin to request’s
445445
// client’s origin.
446446
if (request.origin === 'client') {
447-
// TODO: What if request.client is null?
448-
request.origin = request.client?.origin
447+
request.origin = request.client.origin
449448
}
450449

451450
// 10. If all of the following conditions are true:

lib/web/fetch/util.js

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -255,16 +255,23 @@ function appendFetchMetadata (httpRequest) {
255255

256256
// https://fetch.spec.whatwg.org/#append-a-request-origin-header
257257
function appendRequestOriginHeader (request) {
258-
// 1. Let serializedOrigin be the result of byte-serializing a request origin with request.
258+
// 1. Let serializedOrigin be the result of byte-serializing a request origin
259+
// with request.
260+
// TODO: implement "byte-serializing a request origin"
259261
let serializedOrigin = request.origin
260262

261-
// 2. If request’s response tainting is "cors" or request’s mode is "websocket", then append (`Origin`, serializedOrigin) to request’s header list.
262-
if (request.responseTainting === 'cors' || request.mode === 'websocket') {
263-
if (serializedOrigin) {
264-
request.headersList.append('origin', serializedOrigin, true)
265-
}
263+
// "'client' is changed to an origin during fetching."
264+
// This doesn't happen in undici (in most cases) because undici, by default,
265+
// has no concept of origin.
266+
if (serializedOrigin === 'client') {
267+
return
268+
}
266269

270+
// 2. If request’s response tainting is "cors" or request’s mode is "websocket",
271+
// then append (`Origin`, serializedOrigin) to request’s header list.
267272
// 3. Otherwise, if request’s method is neither `GET` nor `HEAD`, then:
273+
if (request.responseTainting === 'cors' || request.mode === 'websocket') {
274+
request.headersList.append('origin', serializedOrigin, true)
268275
} else if (request.method !== 'GET' && request.method !== 'HEAD') {
269276
// 1. Switch on request’s referrer policy:
270277
switch (request.referrerPolicy) {
@@ -275,13 +282,16 @@ function appendRequestOriginHeader (request) {
275282
case 'no-referrer-when-downgrade':
276283
case 'strict-origin':
277284
case 'strict-origin-when-cross-origin':
278-
// If request’s origin is a tuple origin, its scheme is "https", and request’s current URL’s scheme is not "https", then set serializedOrigin to `null`.
285+
// If request’s origin is a tuple origin, its scheme is "https", and
286+
// request’s current URL’s scheme is not "https", then set
287+
// serializedOrigin to `null`.
279288
if (request.origin && urlHasHttpsScheme(request.origin) && !urlHasHttpsScheme(requestCurrentURL(request))) {
280289
serializedOrigin = null
281290
}
282291
break
283292
case 'same-origin':
284-
// If request’s origin is not same origin with request’s current URL’s origin, then set serializedOrigin to `null`.
293+
// If request’s origin is not same origin with request’s current URL’s
294+
// origin, then set serializedOrigin to `null`.
285295
if (!sameOrigin(request, requestCurrentURL(request))) {
286296
serializedOrigin = null
287297
}
@@ -290,10 +300,8 @@ function appendRequestOriginHeader (request) {
290300
// Do nothing.
291301
}
292302

293-
if (serializedOrigin) {
294-
// 2. Append (`Origin`, serializedOrigin) to request’s header list.
295-
request.headersList.append('origin', serializedOrigin, true)
296-
}
303+
// 2. Append (`Origin`, serializedOrigin) to request’s header list.
304+
request.headersList.append('origin', serializedOrigin, true)
297305
}
298306
}
299307

lib/web/websocket/connection.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ try {
3535
* @param {(response: any) => void} onEstablish
3636
* @param {Partial<import('../../types/websocket').WebSocketInit>} options
3737
*/
38-
function establishWebSocketConnection (url, protocols, ws, onEstablish, options) {
38+
function establishWebSocketConnection (url, protocols, client, ws, onEstablish, options) {
3939
// 1. Let requestURL be a copy of url, with its scheme set to "http", if url’s
4040
// scheme is "ws", and to "https" otherwise.
4141
const requestURL = url
@@ -48,6 +48,7 @@ function establishWebSocketConnection (url, protocols, ws, onEstablish, options)
4848
// and redirect mode is "error".
4949
const request = makeRequest({
5050
urlList: [requestURL],
51+
client,
5152
serviceWorkers: 'none',
5253
referrer: 'no-referrer',
5354
mode: 'websocket',

lib/web/websocket/websocket.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ class WebSocket extends EventTarget {
124124
this[kWebSocketURL] = new URL(urlRecord.href)
125125

126126
// 11. Let client be this's relevant settings object.
127+
const client = environmentSettingsObject.settingsObject
127128

128129
// 12. Run this step in parallel:
129130

@@ -132,6 +133,7 @@ class WebSocket extends EventTarget {
132133
this[kController] = establishWebSocketConnection(
133134
urlRecord,
134135
protocols,
136+
client,
135137
this,
136138
(response) => this.#onConnectionEstablished(response),
137139
options

test/fetch/issue-rsshub-15532.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
'use strict'
2+
3+
const { once } = require('node:events')
4+
const { createServer } = require('node:http')
5+
const { test } = require('node:test')
6+
const { fetch } = require('../..')
7+
const { tspl } = require('@matteo.collina/tspl')
8+
9+
// https://github.com/DIYgod/RSSHub/issues/15532
10+
test('An invalid Origin header is not set', async (t) => {
11+
const { deepStrictEqual } = tspl(t, { plan: 1 })
12+
13+
const server = createServer((req, res) => {
14+
deepStrictEqual(req.headers.origin, undefined)
15+
16+
res.end()
17+
}).listen(0)
18+
19+
await once(server, 'listening')
20+
t.after(server.close.bind(server))
21+
22+
await fetch(`http://localhost:${server.address().port}`, {
23+
method: 'POST'
24+
})
25+
})

0 commit comments

Comments
 (0)