Skip to content

Commit

Permalink
fix(cookies): work with global Headers (nodejs#1850)
Browse files Browse the repository at this point in the history
* fix(cookies): work with global Headers

* lint: Headers is a global
  • Loading branch information
KhafraDev authored and anonrig committed Apr 4, 2023
1 parent f7dccca commit 635248b
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 13 deletions.
15 changes: 7 additions & 8 deletions lib/cookies/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
'use strict'

const { parseSetCookie } = require('./parse')
const { stringify } = require('./util')
const { stringify, getHeadersList } = require('./util')
const { webidl } = require('../fetch/webidl')
const { Headers } = require('../fetch/headers')
const { kHeadersList } = require('../core/symbols')

/**
* @typedef {Object} Cookie
Expand All @@ -27,9 +26,9 @@ const { kHeadersList } = require('../core/symbols')
function getCookies (headers) {
webidl.argumentLengthCheck(arguments, 1, { header: 'getCookies' })

webidl.brandCheck(headers, Headers)
webidl.brandCheck(headers, Headers, { strict: false })

const cookie = headers[kHeadersList].get('cookie')
const cookie = headers.get('cookie')
const out = {}

if (!cookie) {
Expand All @@ -54,7 +53,7 @@ function getCookies (headers) {
function deleteCookie (headers, name, attributes) {
webidl.argumentLengthCheck(arguments, 2, { header: 'deleteCookie' })

webidl.brandCheck(headers, Headers)
webidl.brandCheck(headers, Headers, { strict: false })

name = webidl.converters.DOMString(name)
attributes = webidl.converters.DeleteCookieAttributes(attributes)
Expand All @@ -76,9 +75,9 @@ function deleteCookie (headers, name, attributes) {
function getSetCookies (headers) {
webidl.argumentLengthCheck(arguments, 1, { header: 'getSetCookies' })

webidl.brandCheck(headers, Headers)
webidl.brandCheck(headers, Headers, { strict: false })

const cookies = headers[kHeadersList].cookies
const cookies = getHeadersList(headers).cookies

if (!cookies) {
return []
Expand All @@ -95,7 +94,7 @@ function getSetCookies (headers) {
function setCookie (headers, cookie) {
webidl.argumentLengthCheck(arguments, 2, { header: 'setCookie' })

webidl.brandCheck(headers, Headers)
webidl.brandCheck(headers, Headers, { strict: false })

cookie = webidl.converters.Cookie(cookie)

Expand Down
27 changes: 26 additions & 1 deletion lib/cookies/util.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
'use strict'

const assert = require('assert')
const { kHeadersList } = require('../core/symbols')

function isCTLExcludingHtab (value) {
if (value.length === 0) {
return false
Expand Down Expand Up @@ -260,7 +263,29 @@ function stringify (cookie) {
return out.join('; ')
}

let kHeadersListNode

function getHeadersList (headers) {
if (headers[kHeadersList]) {
return headers[kHeadersList]
}

if (!kHeadersListNode) {
kHeadersListNode = Object.getOwnPropertySymbols(headers).find(
(symbol) => symbol.description === 'headers list'
)

assert(kHeadersListNode, 'Headers cannot be parsed')
}

const headersList = headers[kHeadersListNode]
assert(headersList)

return headersList
}

module.exports = {
isCTLExcludingHtab,
stringify
stringify,
getHeadersList
}
6 changes: 4 additions & 2 deletions lib/fetch/webidl.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,11 @@ webidl.errors.invalidArgument = function (context) {
}

// https://webidl.spec.whatwg.org/#implements
webidl.brandCheck = function (V, I) {
if (!(V instanceof I)) {
webidl.brandCheck = function (V, I, opts = undefined) {
if (opts?.strict !== false && !(V instanceof I)) {
throw new TypeError('Illegal invocation')
} else {
return V?.[Symbol.toStringTag] === I.prototype[Symbol.toStringTag]
}
}

Expand Down
70 changes: 70 additions & 0 deletions test/cookie/global-headers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
'use strict'

const { test, skip } = require('tap')
const {
deleteCookie,
getCookies,
getSetCookies,
setCookie
} = require('../..')
const { getHeadersList } = require('../../lib/cookies/util')

/* global Headers */

if (!globalThis.Headers) {
skip('No global Headers to test')
process.exit(0)
}

test('Using global Headers', (t) => {
t.test('deleteCookies', (t) => {
const headers = new Headers()

t.equal(headers.get('set-cookie'), null)
deleteCookie(headers, 'undici')
t.equal(headers.get('set-cookie'), 'undici=; Expires=Thu, 01 Jan 1970 00:00:00 GMT')

t.end()
})

t.test('getCookies', (t) => {
const headers = new Headers({
cookie: 'get=cookies; and=attributes'
})

t.same(getCookies(headers), { get: 'cookies', and: 'attributes' })
t.end()
})

t.test('getSetCookies', (t) => {
const headers = new Headers({
'set-cookie': 'undici=getSetCookies; Secure'
})

const supportsCookies = getHeadersList(headers).cookies

if (!supportsCookies) {
t.same(getSetCookies(headers), [])
} else {
t.same(getSetCookies(headers), [
{
name: 'undici',
value: 'getSetCookies',
secure: true
}
])
}

t.end()
})

t.test('setCookie', (t) => {
const headers = new Headers()

setCookie(headers, { name: 'undici', value: 'setCookie' })
t.equal(headers.get('Set-Cookie'), 'undici=setCookie')
t.end()
})

t.end()
})
2 changes: 1 addition & 1 deletion types/cookies.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export interface Cookie {
unparsed?: string[]
}

export function deleteCookies (
export function deleteCookie (
headers: Headers,
name: string,
attributes?: { name?: string, domain?: string }
Expand Down
2 changes: 1 addition & 1 deletion types/webidl.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ export interface Webidl {
* @description Performs a brand-check on {@param V} to ensure it is a
* {@param cls} object.
*/
brandCheck <Interface>(V: unknown, cls: Interface): asserts V is Interface
brandCheck <Interface>(V: unknown, cls: Interface, opts?: { strict?: boolean }): asserts V is Interface

/**
* @see https://webidl.spec.whatwg.org/#es-sequence
Expand Down

0 comments on commit 635248b

Please sign in to comment.