'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); require('./shims.js'); var _0SERVER = require('0SERVER'); require('assert'); require('net'); require('http'); require('stream'); require('buffer'); require('util'); require('stream/web'); require('perf_hooks'); require('util/types'); require('events'); require('tls'); require('async_hooks'); require('console'); require('zlib'); require('node:http'); require('node:https'); require('node:zlib'); require('node:stream'); require('node:buffer'); require('node:util'); require('node:url'); require('node:net'); require('node:fs'); require('node:path'); require('crypto'); var setCookie = {exports: {}}; var defaultParseOptions = { decodeValues: true, map: false, silent: false, }; function isNonEmptyString(str) { return typeof str === "string" && !!str.trim(); } function parseString(setCookieValue, options) { var parts = setCookieValue.split(";").filter(isNonEmptyString); var nameValue = parts.shift().split("="); var name = nameValue.shift(); var value = nameValue.join("="); // everything after the first =, joined by a "=" if there was more than one part options = options ? Object.assign({}, defaultParseOptions, options) : defaultParseOptions; try { value = options.decodeValues ? decodeURIComponent(value) : value; // decode cookie value } catch (e) { console.error( "set-cookie-parser encountered an error while decoding a cookie with value '" + value + "'. Set options.decodeValues to false to disable this feature.", e ); } var cookie = { name: name, // grab everything before the first = value: value, }; parts.forEach(function (part) { var sides = part.split("="); var key = sides.shift().trimLeft().toLowerCase(); var value = sides.join("="); if (key === "expires") { cookie.expires = new Date(value); } else if (key === "max-age") { cookie.maxAge = parseInt(value, 10); } else if (key === "secure") { cookie.secure = true; } else if (key === "httponly") { cookie.httpOnly = true; } else if (key === "samesite") { cookie.sameSite = value; } else { cookie[key] = value; } }); return cookie; } function parse(input, options) { options = options ? Object.assign({}, defaultParseOptions, options) : defaultParseOptions; if (!input) { if (!options.map) { return []; } else { return {}; } } if (input.headers && input.headers["set-cookie"]) { // fast-path for node.js (which automatically normalizes header names to lower-case input = input.headers["set-cookie"]; } else if (input.headers) { // slow-path for other environments - see #25 var sch = input.headers[ Object.keys(input.headers).find(function (key) { return key.toLowerCase() === "set-cookie"; }) ]; // warn if called on a request-like object with a cookie header rather than a set-cookie header - see #34, 36 if (!sch && input.headers.cookie && !options.silent) { console.warn( "Warning: set-cookie-parser appears to have been called on a request object. It is designed to parse Set-Cookie headers from responses, not Cookie headers from requests. Set the option {silent: true} to suppress this warning." ); } input = sch; } if (!Array.isArray(input)) { input = [input]; } options = options ? Object.assign({}, defaultParseOptions, options) : defaultParseOptions; if (!options.map) { return input.filter(isNonEmptyString).map(function (str) { return parseString(str, options); }); } else { var cookies = {}; return input.filter(isNonEmptyString).reduce(function (cookies, str) { var cookie = parseString(str, options); cookies[cookie.name] = cookie; return cookies; }, cookies); } } /* Set-Cookie header field-values are sometimes comma joined in one string. This splits them without choking on commas that are within a single set-cookie field-value, such as in the Expires portion. This is uncommon, but explicitly allowed - see https://tools.ietf.org/html/rfc2616#section-4.2 Node.js does this for every header *except* set-cookie - see https://github.com/nodejs/node/blob/d5e363b77ebaf1caf67cd7528224b651c86815c1/lib/_http_incoming.js#L128 React Native's fetch does this for *every* header, including set-cookie. Based on: https://github.com/google/j2objc/commit/16820fdbc8f76ca0c33472810ce0cb03d20efe25 Credits to: https://github.com/tomball for original and https://github.com/chrusart for JavaScript implementation */ function splitCookiesString(cookiesString) { if (Array.isArray(cookiesString)) { return cookiesString; } if (typeof cookiesString !== "string") { return []; } var cookiesStrings = []; var pos = 0; var start; var ch; var lastComma; var nextStart; var cookiesSeparatorFound; function skipWhitespace() { while (pos < cookiesString.length && /\s/.test(cookiesString.charAt(pos))) { pos += 1; } return pos < cookiesString.length; } function notSpecialChar() { ch = cookiesString.charAt(pos); return ch !== "=" && ch !== ";" && ch !== ","; } while (pos < cookiesString.length) { start = pos; cookiesSeparatorFound = false; while (skipWhitespace()) { ch = cookiesString.charAt(pos); if (ch === ",") { // ',' is a cookie separator if we have later first '=', not ';' or ',' lastComma = pos; pos += 1; skipWhitespace(); nextStart = pos; while (pos < cookiesString.length && notSpecialChar()) { pos += 1; } // currently special character if (pos < cookiesString.length && cookiesString.charAt(pos) === "=") { // we found cookies separator cookiesSeparatorFound = true; // pos is inside the next cookie, so back up and return it. pos = nextStart; cookiesStrings.push(cookiesString.substring(start, lastComma)); start = pos; } else { // in param ',' or param separator ';', // we continue from that comma pos = lastComma + 1; } } else { pos += 1; } } if (!cookiesSeparatorFound || pos >= cookiesString.length) { cookiesStrings.push(cookiesString.substring(start, cookiesString.length)); } } return cookiesStrings; } setCookie.exports = parse; setCookie.exports.parse = parse; setCookie.exports.parseString = parseString; var splitCookiesString_1 = setCookie.exports.splitCookiesString = splitCookiesString; /** * Splits headers into two categories: single value and multi value * @param {Headers} headers * @returns {{ * headers: Record, * multiValueHeaders: Record * }} */ function split_headers(headers) { /** @type {Record} */ const h = {}; /** @type {Record} */ const m = {}; headers.forEach((value, key) => { if (key === 'set-cookie') { m[key] = splitCookiesString_1(value); } else { h[key] = value; } }); return { headers: h, multiValueHeaders: m }; } /** * @param {import('@sveltejs/kit').SSRManifest} manifest * @returns {import('@netlify/functions').Handler} */ function init(manifest) { const server = new _0SERVER.Server(manifest); server.init({ env: process.env }); return async (event, context) => { const response = await server.respond(to_request(event), { platform: { context }, getClientAddress() { return event.headers['x-nf-client-connection-ip']; } }); const partial_response = { statusCode: response.status, ...split_headers(response.headers) }; if (!is_text(response.headers.get('content-type'))) { // Function responses should be strings (or undefined), and responses with binary // content should be base64 encoded and set isBase64Encoded to true. // https://github.com/netlify/functions/blob/main/src/function/response.ts return { ...partial_response, isBase64Encoded: true, body: Buffer.from(await response.arrayBuffer()).toString('base64') }; } return { ...partial_response, body: await response.text() }; }; } /** * @param {import('@netlify/functions').HandlerEvent} event * @returns {Request} */ function to_request(event) { const { httpMethod, headers, rawUrl, body, isBase64Encoded } = event; /** @type {RequestInit} */ const init = { method: httpMethod, headers: new Headers(headers) }; if (httpMethod !== 'GET' && httpMethod !== 'HEAD') { const encoding = isBase64Encoded ? 'base64' : 'utf-8'; init.body = typeof body === 'string' ? Buffer.from(body, encoding) : body; } return new Request(rawUrl, init); } const text_types = new Set([ 'application/xml', 'application/json', 'application/x-www-form-urlencoded', 'multipart/form-data' ]); /** * Decides how the body should be parsed based on its mime type * * @param {string | undefined | null} content_type The `content-type` header of a request/response. * @returns {boolean} */ function is_text(content_type) { if (!content_type) return true; // defaults to json const type = content_type.split(';')[0].toLowerCase(); // get the mime type return type.startsWith('text/') || type.endsWith('+xml') || text_types.has(type); } exports.init = init;