Urara-Blog/node_modules/.pnpm-store/v3/files/77/aedfcc058d62198ba434727d240dd5a632aec681ef8dd5fdc0eb2f2a9f58913f835c43fbaf2149e32195d5ef5faa9f5fde5cefa665de016fe314f25e066519
2022-08-14 01:14:53 +08:00

348 lines
9 KiB
Text

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;
/** @param {import('http').IncomingMessage} req */
function get_raw_body(req) {
const h = req.headers;
if (!h['content-type']) {
return null;
}
const length = Number(h['content-length']);
// check if no request body
// https://github.com/jshttp/type-is/blob/c1f4388c71c8a01f79934e68f630ca4a15fffcd6/index.js#L81-L95
if (isNaN(length) && h['transfer-encoding'] == null) {
return null;
}
if (req.destroyed) {
const readable = new ReadableStream();
readable.cancel();
return readable;
}
let size = 0;
let cancelled = false;
return new ReadableStream({
start(controller) {
req.on('error', (error) => {
controller.error(error);
});
req.on('end', () => {
if (cancelled) return;
controller.close();
});
req.on('data', (chunk) => {
if (cancelled) return;
size += chunk.length;
if (size > length) {
controller.error(new Error('content-length exceeded'));
return;
}
controller.enqueue(chunk);
if (controller.desiredSize === null || controller.desiredSize <= 0) {
req.pause();
}
});
},
pull() {
req.resume();
},
cancel(reason) {
cancelled = true;
req.destroy(reason);
}
});
}
/** @type {import('@sveltejs/kit/node').getRequest} */
async function getRequest(base, req) {
let headers = /** @type {Record<string, string>} */ (req.headers);
if (req.httpVersionMajor === 2) {
// we need to strip out the HTTP/2 pseudo-headers because node-fetch's
// Request implementation doesn't like them
// TODO is this still true with Node 18
headers = Object.assign({}, headers);
delete headers[':method'];
delete headers[':path'];
delete headers[':authority'];
delete headers[':scheme'];
}
return new Request(base + req.url, {
method: req.method,
headers,
body: get_raw_body(req)
});
}
/** @type {import('@sveltejs/kit/node').setResponse} */
async function setResponse(res, response) {
const headers = Object.fromEntries(response.headers);
if (response.headers.has('set-cookie')) {
const header = /** @type {string} */ (response.headers.get('set-cookie'));
const split = splitCookiesString_1(header);
// @ts-expect-error
headers['set-cookie'] = split;
}
res.writeHead(response.status, headers);
if (!response.body) {
res.end();
return;
}
const reader = response.body.getReader();
if (res.destroyed) {
reader.cancel();
return;
}
const cancel = (/** @type {Error|undefined} */ error) => {
res.off('close', cancel);
res.off('error', cancel);
// If the reader has already been interrupted with an error earlier,
// then it will appear here, it is useless, but it needs to be catch.
reader.cancel(error).catch(() => {});
if (error) res.destroy(error);
};
res.on('close', cancel);
res.on('error', cancel);
next();
async function next() {
try {
for (;;) {
const { done, value } = await reader.read();
if (done) break;
if (!res.write(value)) {
res.once('drain', next);
return;
}
}
res.end();
} catch (error) {
cancel(error instanceof Error ? error : new Error(String(error)));
}
}
}
export { getRequest, setResponse };