11cb0ef41Sopenharmony_ci'use strict'
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst { parseSetCookie } = require('./parse')
41cb0ef41Sopenharmony_ciconst { stringify, getHeadersList } = require('./util')
51cb0ef41Sopenharmony_ciconst { webidl } = require('../fetch/webidl')
61cb0ef41Sopenharmony_ciconst { Headers } = require('../fetch/headers')
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci/**
91cb0ef41Sopenharmony_ci * @typedef {Object} Cookie
101cb0ef41Sopenharmony_ci * @property {string} name
111cb0ef41Sopenharmony_ci * @property {string} value
121cb0ef41Sopenharmony_ci * @property {Date|number|undefined} expires
131cb0ef41Sopenharmony_ci * @property {number|undefined} maxAge
141cb0ef41Sopenharmony_ci * @property {string|undefined} domain
151cb0ef41Sopenharmony_ci * @property {string|undefined} path
161cb0ef41Sopenharmony_ci * @property {boolean|undefined} secure
171cb0ef41Sopenharmony_ci * @property {boolean|undefined} httpOnly
181cb0ef41Sopenharmony_ci * @property {'Strict'|'Lax'|'None'} sameSite
191cb0ef41Sopenharmony_ci * @property {string[]} unparsed
201cb0ef41Sopenharmony_ci */
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci/**
231cb0ef41Sopenharmony_ci * @param {Headers} headers
241cb0ef41Sopenharmony_ci * @returns {Record<string, string>}
251cb0ef41Sopenharmony_ci */
261cb0ef41Sopenharmony_cifunction getCookies (headers) {
271cb0ef41Sopenharmony_ci  webidl.argumentLengthCheck(arguments, 1, { header: 'getCookies' })
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci  webidl.brandCheck(headers, Headers, { strict: false })
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ci  const cookie = headers.get('cookie')
321cb0ef41Sopenharmony_ci  const out = {}
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci  if (!cookie) {
351cb0ef41Sopenharmony_ci    return out
361cb0ef41Sopenharmony_ci  }
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci  for (const piece of cookie.split(';')) {
391cb0ef41Sopenharmony_ci    const [name, ...value] = piece.split('=')
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci    out[name.trim()] = value.join('=')
421cb0ef41Sopenharmony_ci  }
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci  return out
451cb0ef41Sopenharmony_ci}
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci/**
481cb0ef41Sopenharmony_ci * @param {Headers} headers
491cb0ef41Sopenharmony_ci * @param {string} name
501cb0ef41Sopenharmony_ci * @param {{ path?: string, domain?: string }|undefined} attributes
511cb0ef41Sopenharmony_ci * @returns {void}
521cb0ef41Sopenharmony_ci */
531cb0ef41Sopenharmony_cifunction deleteCookie (headers, name, attributes) {
541cb0ef41Sopenharmony_ci  webidl.argumentLengthCheck(arguments, 2, { header: 'deleteCookie' })
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci  webidl.brandCheck(headers, Headers, { strict: false })
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci  name = webidl.converters.DOMString(name)
591cb0ef41Sopenharmony_ci  attributes = webidl.converters.DeleteCookieAttributes(attributes)
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci  // Matches behavior of
621cb0ef41Sopenharmony_ci  // https://github.com/denoland/deno_std/blob/63827b16330b82489a04614027c33b7904e08be5/http/cookie.ts#L278
631cb0ef41Sopenharmony_ci  setCookie(headers, {
641cb0ef41Sopenharmony_ci    name,
651cb0ef41Sopenharmony_ci    value: '',
661cb0ef41Sopenharmony_ci    expires: new Date(0),
671cb0ef41Sopenharmony_ci    ...attributes
681cb0ef41Sopenharmony_ci  })
691cb0ef41Sopenharmony_ci}
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci/**
721cb0ef41Sopenharmony_ci * @param {Headers} headers
731cb0ef41Sopenharmony_ci * @returns {Cookie[]}
741cb0ef41Sopenharmony_ci */
751cb0ef41Sopenharmony_cifunction getSetCookies (headers) {
761cb0ef41Sopenharmony_ci  webidl.argumentLengthCheck(arguments, 1, { header: 'getSetCookies' })
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_ci  webidl.brandCheck(headers, Headers, { strict: false })
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci  const cookies = getHeadersList(headers).cookies
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci  if (!cookies) {
831cb0ef41Sopenharmony_ci    return []
841cb0ef41Sopenharmony_ci  }
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci  // In older versions of undici, cookies is a list of name:value.
871cb0ef41Sopenharmony_ci  return cookies.map((pair) => parseSetCookie(Array.isArray(pair) ? pair[1] : pair))
881cb0ef41Sopenharmony_ci}
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci/**
911cb0ef41Sopenharmony_ci * @param {Headers} headers
921cb0ef41Sopenharmony_ci * @param {Cookie} cookie
931cb0ef41Sopenharmony_ci * @returns {void}
941cb0ef41Sopenharmony_ci */
951cb0ef41Sopenharmony_cifunction setCookie (headers, cookie) {
961cb0ef41Sopenharmony_ci  webidl.argumentLengthCheck(arguments, 2, { header: 'setCookie' })
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci  webidl.brandCheck(headers, Headers, { strict: false })
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci  cookie = webidl.converters.Cookie(cookie)
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci  const str = stringify(cookie)
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci  if (str) {
1051cb0ef41Sopenharmony_ci    headers.append('Set-Cookie', stringify(cookie))
1061cb0ef41Sopenharmony_ci  }
1071cb0ef41Sopenharmony_ci}
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ciwebidl.converters.DeleteCookieAttributes = webidl.dictionaryConverter([
1101cb0ef41Sopenharmony_ci  {
1111cb0ef41Sopenharmony_ci    converter: webidl.nullableConverter(webidl.converters.DOMString),
1121cb0ef41Sopenharmony_ci    key: 'path',
1131cb0ef41Sopenharmony_ci    defaultValue: null
1141cb0ef41Sopenharmony_ci  },
1151cb0ef41Sopenharmony_ci  {
1161cb0ef41Sopenharmony_ci    converter: webidl.nullableConverter(webidl.converters.DOMString),
1171cb0ef41Sopenharmony_ci    key: 'domain',
1181cb0ef41Sopenharmony_ci    defaultValue: null
1191cb0ef41Sopenharmony_ci  }
1201cb0ef41Sopenharmony_ci])
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ciwebidl.converters.Cookie = webidl.dictionaryConverter([
1231cb0ef41Sopenharmony_ci  {
1241cb0ef41Sopenharmony_ci    converter: webidl.converters.DOMString,
1251cb0ef41Sopenharmony_ci    key: 'name'
1261cb0ef41Sopenharmony_ci  },
1271cb0ef41Sopenharmony_ci  {
1281cb0ef41Sopenharmony_ci    converter: webidl.converters.DOMString,
1291cb0ef41Sopenharmony_ci    key: 'value'
1301cb0ef41Sopenharmony_ci  },
1311cb0ef41Sopenharmony_ci  {
1321cb0ef41Sopenharmony_ci    converter: webidl.nullableConverter((value) => {
1331cb0ef41Sopenharmony_ci      if (typeof value === 'number') {
1341cb0ef41Sopenharmony_ci        return webidl.converters['unsigned long long'](value)
1351cb0ef41Sopenharmony_ci      }
1361cb0ef41Sopenharmony_ci
1371cb0ef41Sopenharmony_ci      return new Date(value)
1381cb0ef41Sopenharmony_ci    }),
1391cb0ef41Sopenharmony_ci    key: 'expires',
1401cb0ef41Sopenharmony_ci    defaultValue: null
1411cb0ef41Sopenharmony_ci  },
1421cb0ef41Sopenharmony_ci  {
1431cb0ef41Sopenharmony_ci    converter: webidl.nullableConverter(webidl.converters['long long']),
1441cb0ef41Sopenharmony_ci    key: 'maxAge',
1451cb0ef41Sopenharmony_ci    defaultValue: null
1461cb0ef41Sopenharmony_ci  },
1471cb0ef41Sopenharmony_ci  {
1481cb0ef41Sopenharmony_ci    converter: webidl.nullableConverter(webidl.converters.DOMString),
1491cb0ef41Sopenharmony_ci    key: 'domain',
1501cb0ef41Sopenharmony_ci    defaultValue: null
1511cb0ef41Sopenharmony_ci  },
1521cb0ef41Sopenharmony_ci  {
1531cb0ef41Sopenharmony_ci    converter: webidl.nullableConverter(webidl.converters.DOMString),
1541cb0ef41Sopenharmony_ci    key: 'path',
1551cb0ef41Sopenharmony_ci    defaultValue: null
1561cb0ef41Sopenharmony_ci  },
1571cb0ef41Sopenharmony_ci  {
1581cb0ef41Sopenharmony_ci    converter: webidl.nullableConverter(webidl.converters.boolean),
1591cb0ef41Sopenharmony_ci    key: 'secure',
1601cb0ef41Sopenharmony_ci    defaultValue: null
1611cb0ef41Sopenharmony_ci  },
1621cb0ef41Sopenharmony_ci  {
1631cb0ef41Sopenharmony_ci    converter: webidl.nullableConverter(webidl.converters.boolean),
1641cb0ef41Sopenharmony_ci    key: 'httpOnly',
1651cb0ef41Sopenharmony_ci    defaultValue: null
1661cb0ef41Sopenharmony_ci  },
1671cb0ef41Sopenharmony_ci  {
1681cb0ef41Sopenharmony_ci    converter: webidl.converters.USVString,
1691cb0ef41Sopenharmony_ci    key: 'sameSite',
1701cb0ef41Sopenharmony_ci    allowedValues: ['Strict', 'Lax', 'None']
1711cb0ef41Sopenharmony_ci  },
1721cb0ef41Sopenharmony_ci  {
1731cb0ef41Sopenharmony_ci    converter: webidl.sequenceConverter(webidl.converters.DOMString),
1741cb0ef41Sopenharmony_ci    key: 'unparsed',
1751cb0ef41Sopenharmony_ci    defaultValue: []
1761cb0ef41Sopenharmony_ci  }
1771cb0ef41Sopenharmony_ci])
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_cimodule.exports = {
1801cb0ef41Sopenharmony_ci  getCookies,
1811cb0ef41Sopenharmony_ci  deleteCookie,
1821cb0ef41Sopenharmony_ci  getSetCookies,
1831cb0ef41Sopenharmony_ci  setCookie
1841cb0ef41Sopenharmony_ci}
185